Bug 20316 – array properties fail hasMember

Status
RESOLVED
Resolution
WONTFIX
Severity
regression
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2019-10-24T16:39:01Z
Last change time
2019-12-12T10:20:40Z
Assigned to
No Owner
Creator
John Colvin

Comments

Comment #0 by john.loughran.colvin — 2019-10-24T16:39:01Z
pragma(msg, __traits(hasMember, int[], "length")); // false pragma(msg, __traits(hasMember, int[], "ptr")); // false pragma(msg, __traits(hasMember, int[], "capacity")); // false pragma(msg, __traits(hasMember, int[], "sizeof")); // true pragma(msg, __traits(hasMember, int[], "alignof")); // true
Comment #1 by john.loughran.colvin — 2019-10-24T17:40:25Z
This is a regression introduced in 2.065, before which .length and .ptr were found. AFAICT .capacity never worked
Comment #2 by razvan.nitu1305 — 2019-10-30T09:30:19Z
The problem here is that (int[]).length is not a valid D construction: static assert(__traits(compiles, (int[]).length)); will fail, therefore traits(hasMember) returns false. length, ptr and capacity were thought to work solely on expressions, not on types (it doesn't make sense to get the pointer of a type) so I'm a bit confused of what the compiler should do here. sizeof and alignof work because there are type properties.
Comment #3 by razvan.nitu1305 — 2019-10-30T09:31:49Z
Note that if a variable is declared: int[] a; traits(hasMember) on a works properly.
Comment #4 by razvan.nitu1305 — 2019-10-30T09:54:20Z
As for capacity, it is not listed on the list of properties for arrays and it is implemented as a druntime function. I guess this bug report opens the philosophical question of what hasMember actually means. For example, sizeof is not actually a member of any type, it is a property that may be queried; that property may be implemented as a function directly in the compiler or it may be a function in druntime or it may be an actual member of the int class; this all depends on how it was actually implemented, which is not something that the user cares. In my opinion, hasMember should only work on aggregates, because there we are talking about actual scope declarations that have members. builtin types should all return false on hasMember queries because builtin types don't have any members, rather they have properties. If you want to see what properties a type has you can simply use traits(compiles).
Comment #5 by bugzilla — 2019-12-12T10:17:15Z
I agree that hasMember should only work on aggregates. UFCS functions that syntactically look like members are still not members.
Comment #6 by bugzilla — 2019-12-12T10:20:40Z
> traits(hasMember) on a works properly. Meaning: int[] array; pragma(msg, __traits(hasMember, array, "length")); // true pragma(msg, __traits(hasMember, array, "ptr")); // true pragma(msg, __traits(hasMember, array, "capacity")); // true pragma(msg, __traits(hasMember, array, "sizeof")); // true pragma(msg, __traits(hasMember, array, "alignof")); // true Gaahhh. It's probably far too late to change this behavior now. Marking as WONTFIX.