Bug 9630 – DMD git: can't access array field properties from static method
Status
RESOLVED
Resolution
INVALID
Severity
regression
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-03-01T20:47:00Z
Last change time
2013-03-02T12:08:43Z
Keywords
rejects-valid
Assigned to
nobody
Creator
dlang-bugzilla
Comments
Comment #0 by dlang-bugzilla — 2013-03-01T20:47:21Z
struct S
{
int i[1];
static void foo()
{
assert(0 < i[0].max);
}
}
I assume this code is valid, as the problem appears with e.g. arrays of ints, but not ints.
Works in 2.062, breaks in DMD git master (d0e1476c1).
Comment #1 by andrej.mitrovich — 2013-03-01T20:50:55Z
Comment #2 by andrej.mitrovich — 2013-03-01T20:52:02Z
Workaround:
assert(0 < typeof(i[0]).max);
Comment #3 by dlang-bugzilla — 2013-03-01T20:53:14Z
You mean it was accidentally broken by that pull? It certainly does not look intentional.
Another workaround is: typeof(this).init.i[0].max
Comment #4 by andrej.mitrovich — 2013-03-01T20:54:14Z
(In reply to comment #3)
> You mean it was accidentally broken by that pull? It certainly does not look
> intentional.
>
> Another workaround is: typeof(this).init.i[0].max
Kenji mentioned it was going to break code (I don't know if it applies for this case though). I suggested keeping a list of pulls like that in a file so we can deliver a better change log for 2.063.
Comment #5 by dlang-bugzilla — 2013-03-01T20:57:24Z
Well, the observable effect is inconsistent and makes no sense:
someInt.max works, but someArrayOfInt[0].max doesn't.
The tests included with the pull do not test attributes of array elements, only of individual fields and concatenation with arrays, so I'm quite sure it's a bug.
Comment #6 by k.hara.pg — 2013-03-01T21:49:19Z
(In reply to comment #5)
> Well, the observable effect is inconsistent and makes no sense:
> someInt.max works, but someArrayOfInt[0].max doesn't.
> The tests included with the pull do not test attributes of array elements, only
> of individual fields and concatenation with arrays, so I'm quite sure it's a
> bug.
That is mostly intended. The introduced rule by pull 1687 is:
1. In expr.aStaticMember exists, if expr is just a variable that needs this, it is specially treated as typeof(expr).someStaticMember.
This is useful for Type.field.init, Type.field.offsetof, etc.
2. In expr.aFieldVariable, if expr is just a variable that needs this, the "need this" error for aFieldVariable access is specially delayed.
This is more specialized 'exception' than #1.
The chain of field access like following would be accepted by this.
Type.field1.field2.field3.staticFieldOrFunction
#2 is introduced by @dawgfoto's comment.
https://github.com/D-Programming-Language/dmd/pull/1687#issuecomment-14090801
In original code, index access `i[0]` does not fit to above rule. So it will raise "need this" error normally.
Comment #7 by dlang-bugzilla — 2013-03-01T21:54:14Z
> Now, the unreal variable access doesn't make errors if it is not actually used.
But i[0] is not used as well.
I guess you mean to say that the behavior is "intended", as in it has been deemed an acceptable flaw?
Comment #8 by k.hara.pg — 2013-03-01T22:03:52Z
If `i[0].max` should be accepted, how about this?
struct S
{
int[] arr;
static void foo()
{
auto x = arr.map!(x => x*2).filter!(x > 4).array[0].max;
}
}
The part expression `arr.map!(x => x*2).filter!(x > 4).array[0]` is never evaluated, because it is just used for calculate its type. It looks much weird to me. I think such *implicit typeof* feature is not good. Instead:
auto x = typeof(arr.map!(x => x*2).filter!(x > 4).array[0]).max;
is much better. I think language should enforce the latter.
Comment #9 by k.hara.pg — 2013-03-01T22:07:26Z
(In reply to comment #7)
> > Now, the unreal variable access doesn't make errors if it is not actually used.
>
> But i[0] is not used as well.
>
> I guess you mean to say that the behavior is "intended", as in it has been
> deemed an acceptable flaw?
Because i[0] is _not_ a variable. `i[0]` should be evaluated in runtime but it is impossible, so compiler reports "need this" error.
Comment #10 by dlang-bugzilla — 2013-03-01T22:09:16Z
> auto x = typeof(arr.map!(x => x*2).filter!(x > 4).array[0]).max;
Well, I don't know about how this fits with backwards compatibility and such, but the above line looks wrong to me as well, since it's passing a non-existent variable (arr) to a function (map). This is as much "runtime evaluated" as taking its index.
Comment #11 by k.hara.pg — 2013-03-01T22:15:23Z
(In reply to comment #6)
> 2. In expr.aFieldVariable, if expr is just a variable that needs this, the
> "need this" error for aFieldVariable access is specially delayed.
>
> This is more specialized 'exception' than #1.
> The chain of field access like following would be accepted by this.
>
> Type.field1.field2.field3.staticFieldOrFunction
Why it is explicitly allowed? The reason of rule #2 is "a variable access can be regarded as a symbol access". For example, symbol access is already allowed in template argument.
template X(alias symbol) {}
struct S {
T field1;
struct T { int field2; }
}
void main() {
alias x = X!(S.field1.field2); // access symbol S.T.field2
auto y = S.field1.field2.offsetof; // access symbol S.T.field2
}
This is consistent behavior.
Comment #12 by dlang-bugzilla — 2013-03-01T22:17:28Z
OK, I'm clearly in over my head so I'll take your word for it.
Comment #13 by k.hara.pg — 2013-03-01T22:27:27Z
(In reply to comment #10)
> > auto x = typeof(arr.map!(x => x*2).filter!(x > 4).array[0]).max;
>
> Well, I don't know about how this fits with backwards compatibility and such,
> but the above line looks wrong to me as well, since it's passing a non-existent
> variable (arr) to a function (map). This is as much "runtime evaluated" as
> taking its index.
Using non-static variable directly under the typeof should be allowed.
If you use 'typeof', you means "I want to just get the type of specified expression, and does not consider whether the expression can be evaluate in runtime." In this point, D accepts it explicitly.
Moreover, that is necessary for the use at out of function scope.
struct S {
int field1;
typeof(field1) field2; // field1 access has no "valid this", but allowed
static void foo() {
typeof(field1) x; // field1 access has no "valid this", but allowed
}
}
This is also consistent behavior.
Comment #14 by k.hara.pg — 2013-03-01T22:29:36Z
(In reply to comment #12)
> OK, I'm clearly in over my head so I'll take your word for it.
Thanks.
Comment #15 by bearophile_hugs — 2013-03-02T05:31:13Z
(In reply to comment #2)
> Workaround:
>
> assert(0 < typeof(i[0]).max);
This is acceptable.
This program:
struct Foo {
int i[1];
static void bar() {
assert(0 < i[0].max);
}
}
Currently gives:
temp.d(4): Error: need 'this' for i type int[1u].
But is it possible for the error message to suggest your solution to fix the error?
temp.d(4): Error: need 'this' for i type int[1]. Use typeof(i[0]).max instead
Comment #16 by andrej.mitrovich — 2013-03-02T07:24:23Z
(In reply to comment #15)
> Currently gives:
>
> temp.d(4): Error: need 'this' for i type int[1u].
This is already a bad message. 'i' should be quoted and the wording should be improved:
> temp.d(4): Error: need 'this' for 'i' of type int[1u].
Feel free to open an enhancement for these.
Comment #17 by bearophile_hugs — 2013-03-02T12:08:43Z
(In reply to comment #16)
> Feel free to open an enhancement for these.
OK, filed as Issue 9635