There is a construct, where one defines a parameter template function, so that the compiler can infer its attributes. The problem is that when said function is a property, it doesn't mix with traits, because it fails the typeof blocks. Explanation: //---- import std.range; struct Infered { size_t length()(){return 0;} } void main() { Infered r; auto len = r.length; //OK static assert(hasLength!Infered); //Error: static assert (hasLength!(Infered)) is false static assert(is(typeof(r.length) : ulong)); //Error: static assert (is(typeof(r.length()()) : ulong)) is false pragma(msg, typeof(r.length).stringof); //Error: expression (r.length()()) has no type // while evaluating pragma(msg, (_error_).stringof) } //---- Such usage is very interesting for wrapper ranges, but they are the most vulnerable: Are concerned: hasLength. isForwardRange. isRandomAccessRange. One workaround is to make the call outside of the typeof, and store the result, and then test result itself eg is(typeof(len) : ulong)). Doing this would shuffle around a lot of code though, so I don't think it's worth doing it.
The specs say that typeof(F) gets the function F return type only when it's marked @property. (https://dlang.org/spec/declaration.html#typeof, ยง4) When this rule is followed, the assertions are valid: ``` import std.range; struct Infered { size_t length()() @property {return 0;} } void main() { Infered r; auto len = r.length; //OK static assert(hasLength!Infered); //OK static assert(is(typeof(r.length) : ulong)); //OK pragma(msg, typeof(r.length).stringof); //OK } ```