digitalmars.D.learn - Bug?
- Jack Applegame (42/42) May 11 2020 Why doesn't it compile?
- Jack Applegame (4/5) May 11 2020 Damn! I made a typo. It must be:
- Jack Applegame (18/18) May 11 2020 And the first example still doesn't compile:
- Adam D. Ruppe (9/10) May 11 2020 UFCS is only defined to work with global scope functions. A
- Jack Applegame (6/9) May 11 2020 But in this case the error should be displayed for lines 4 and 5,
- Steven Schveighoffer (8/20) May 11 2020 Yeah, this is definitely a bug. If I change the return type of front to
- Adam D. Ruppe (4/6) May 11 2020 Since the imported front is also a local symbol the compiler
- Simen =?UTF-8?B?S2rDpnLDpXM=?= (15/24) May 11 2020 You're right, and it absolutely seems the call on lines 4 and 5
- Jack Applegame (2/3) May 11 2020 Thanks.
Why doesn't it compile? ``` struct Range(R) { import std.array : empty, front, popFront; R range; bool empty() const { return range.empty; } auto front() const { return range.front; } void popFront() { range.popFront(); } } void main() { auto rng = Range!string("1234"); assert(rng.front == 1); } ``` onlineapp.d(11): Error: void has no value onlineapp.d(11): Error: incompatible types for (rng.front) == (1): void and int try here: https://run.dlang.io/is/Dg8Fpr If you move the import to the global scope, you will get a weird result: ``` import std.stdio; import std.array : empty, front, popFront; struct Range(R) { R range; bool empty() const { return range.empty; } auto front() const { return range.front; } void popFront() { range.popFront(); } } void main() { auto rng = Range!string("1234"); writefln("front: %s", rng.front); assert(rng.front == 1); } ``` front: 1 core.exception.AssertError onlineapp.d(14): Assertion failure ---------------- ??:? _d_assertp [0x56107489bc75] onlineapp.d:14 _Dmain [0x561074889902] try here: https://run.dlang.io/is/arieKR WAT???
May 11 2020
On Monday, 11 May 2020 at 12:20:06 UTC, Jack Applegame wrote:assert(rng.front == 1);Damn! I made a typo. It must be: assert(rng.front == '1') So the second example works fine.
May 11 2020
And the first example still doesn't compile: ``` struct Range(R) { import std.array : empty, front, popFront; R range; bool empty() const { return range.empty; } auto front() const { return range.front; } void popFront() { range.popFront(); } } void main() { auto rng = Range!string("1234"); assert(rng.front == '1'); } ``` onlineapp.d(11): Error: void has no value onlineapp.d(11): Error: incompatible types for (rng.front) == ('1'): void and char ```
May 11 2020
On Monday, 11 May 2020 at 12:20:06 UTC, Jack Applegame wrote:If you move the import to the global scopeUFCS is only defined to work with global scope functions. A restricted import (module : symbol, symbols) puts things in local scope so ufcs doesn't apply. (interestingly an unrestricted import does NOT do that, it keeps the functions in their original scope, so UFCS works if you locally `import std.range;` but not if you `import std.range : front, popFront, empty;`! lol. but this is... im pretty sure by design, it has been this way for ages.)
May 11 2020
On Monday, 11 May 2020 at 12:30:22 UTC, Adam D. Ruppe wrote:UFCS is only defined to work with global scope functions. A restricted import (module : symbol, symbols) puts things in local scope so ufcs doesn't apply.But in this case the error should be displayed for lines 4 and 5, not 11. Line 11 contains a call to a member function, not UFCS. In addition, if you add the parentheses, then it works: assert(rng.front() == '1');
May 11 2020
On 5/11/20 8:44 AM, Jack Applegame wrote:On Monday, 11 May 2020 at 12:30:22 UTC, Adam D. Ruppe wrote:Yeah, this is definitely a bug. If I change the return type of front to dchar from auto, it still thinks it's returning void. Calling things like popFront without parentheses has an error "rng.popFront has no effect". Clearly something isn't connecting properly, it's almost like it's resolving to the function itself instead of calling it. -SteveUFCS is only defined to work with global scope functions. A restricted import (module : symbol, symbols) puts things in local scope so ufcs doesn't apply.But in this case the error should be displayed for lines 4 and 5, not 11. Line 11 contains a call to a member function, not UFCS. In addition, if you add the parentheses, then it works: assert(rng.front() == '1');
May 11 2020
On Monday, 11 May 2020 at 13:06:59 UTC, Steven Schveighoffer wrote:Clearly something isn't connecting properly, it's almost like it's resolving to the function itself instead of calling it.Since the imported front is also a local symbol the compiler probably thinks it is overloaded and not handling that right.....
May 11 2020
On Monday, 11 May 2020 at 12:44:45 UTC, Jack Applegame wrote:On Monday, 11 May 2020 at 12:30:22 UTC, Adam D. Ruppe wrote:You're right, and it absolutely seems the call on lines 4 and 5 work correctly. Instead, the compiler is confused by the presence of two different overloads for front in Range!T, and doesn't attempt to call the one it can call. We get the exact same behavior here: struct S { int gun()(int i) { return 0; } alias fun = gun; int fun() { return 1; } } static assert(S().fun == 1); Filed here: https://issues.dlang.org/show_bug.cgi?id=20821 -- SimenUFCS is only defined to work with global scope functions. A restricted import (module : symbol, symbols) puts things in local scope so ufcs doesn't apply.But in this case the error should be displayed for lines 4 and 5, not 11. Line 11 contains a call to a member function, not UFCS. In addition, if you add the parentheses, then it works: assert(rng.front() == '1');
May 11 2020
On Monday, 11 May 2020 at 13:12:37 UTC, Simen Kjærås wrote:Filed here: https://issues.dlang.org/show_bug.cgi?id=20821Thanks.
May 11 2020