View Issue Details
|ID||Project||Category||View Status||Date Submitted||Last Update|
|0033960||FPC||Documentation||public||2018-07-10 10:28||2018-07-14 15:54|
|Reporter||Thaddy de Koning||Assigned To||Michael Van Canneyt|
|Priority||normal||Severity||minor||Reproducibility||have not tried|
|Product Version||3.1.1||Product Build||39423|
|Target Version||3.2.0||Fixed in Version||3.1.1|
|Summary||0033960: generics chapter 8.8 "A word about scope" needs maybe a remark about accessing members of T that are not yet specialized.|
|Description||related to 0033700|
Given the following code:
generic TLstEnumerator<T> = record
lst, lst_save: T;
constructor Create(const Value: T);
function GetEnumerator: specialize TLstEnumerator<T>;
function MoveNext: boolean;
property Current: T read lst;
constructor TLstEnumerator.Create(const Value: T);
lst := Value;
lst_save := nil;
function TLstEnumerator.GetEnumerator: specialize TLstEnumerator<T>;
Result := Self;
function TLstEnumerator.MoveNext: boolean;
if lst <> nil then
// At this point it is simply not known that lst is a type that has
// a field called next. So the compiler throws an illegal qualifier.
// The compiler is correct. This is not a bug! lst is not in scope here.
Result := True;
end else Result := False;
Here the programmer knows that T has a specific member, but the compiler can not know that at that point. It has not enough context within that scope to resolve T fully.
|Steps To Reproduce||Compile my files attached to 0033700|
- mode delphi
- mode objfpc
Note Delphi barks even more but essentially also does not accept such code.
|Additional Information||It is simply not clear to OP from 0033700 that lst^.next is not specialized at all at that point. That needs maybe some clarification in the documentation.|
I filed it as a separate bug report because I feel it belongs to documentation.
|Tags||No tags attached.|
|Fixed in Revision||1493|
Note that this is maybe already implied by the first sentence and the last few remarks of the 8.8 chapter and section, but it maybe can be a bit clearer.
I specifically reduced the code to the bare minimum. The rest of 0033700 is very cloudy and becomes ever more confusing at first glance.
Also note that a constraints mechanism would resolve this, but in this case constraints are not available (nor do they exist for this situation).
A constraint would provide the necessary context. As can be done with classes.
Note there is another possible bug here.
if lst <> nil then
lst is of type T. Type T need not be a pointer type. Same confusion though.
||I have explained in detail in the docs why example in the related bug report does not work, I also show how it can be fixed using classes and type restrictions.|
|2018-07-10 10:28||Thaddy de Koning||New Issue|
|2018-07-10 10:28||Thaddy de Koning||Status||new => assigned|
|2018-07-10 10:28||Thaddy de Koning||Assigned To||=> Michael Van Canneyt|
|2018-07-10 10:31||Thaddy de Koning||Note Added: 0109332|
|2018-07-10 10:37||Thaddy de Koning||Note Edited: 0109332||View Revisions|
|2018-07-10 10:38||Thaddy de Koning||Note Edited: 0109332||View Revisions|
|2018-07-10 10:51||Thaddy de Koning||Note Added: 0109333|
|2018-07-10 11:33||Michael Van Canneyt||Relationship added||related to 0033700|
|2018-07-10 11:34||Michael Van Canneyt||Fixed in Revision||=> 1493|
|2018-07-10 11:34||Michael Van Canneyt||Note Added: 0109336|
|2018-07-10 11:34||Michael Van Canneyt||Status||assigned => resolved|
|2018-07-10 11:34||Michael Van Canneyt||Fixed in Version||=> 3.1.1|
|2018-07-10 11:34||Michael Van Canneyt||Resolution||open => fixed|
|2018-07-10 11:34||Michael Van Canneyt||Target Version||=> 3.2.0|
|2018-07-14 15:54||Florian||Relationship added||related to 0033961|