digitalmars.D.bugs - [Issue 17374] New: Improve inferred attribute error message
- via Digitalmars-d-bugs (78/78) May 06 2017 https://issues.dlang.org/show_bug.cgi?id=17374
https://issues.dlang.org/show_bug.cgi?id=17374 Issue ID: 17374 Summary: Improve inferred attribute error message Product: D Version: D2 Hardware: All OS: Windows Status: NEW Severity: enhancement Priority: P1 Component: dmd Assignee: nobody puremagic.com Reporter: destructionator gmail.com Consider the following: void call(alias T)() { T(); } void foo() {} void main() nogc { call!foo(); } If you compile that, you get the error: Error: nogc function 'D main' cannot call non- nogc function 'test.call!(foo).call' The problem is that since `call` is inferred, you don't really know why - it likely has to do with some parameter, but you aren't sure. This has been a FAQ recently on the forums and chatroom. Here's my suggested solution: report that AND go down and report what in the call graph failed the check without inferring. In this case, the error message would be something like: Error: nogc function 'D main' cannot call non- nogc function 'test.call!(foo).call' because it eventually calls non- nogc function 'foo' The "eventually" is because of a case like this: void call(alias T)() { T(); } void secondLayer(alias T)() { T(); } void foo() {} void main() nogc { secondLayer!(call!foo)(); } The error message I want here is: Error: nogc function 'D main' cannot call non- nogc function 'test.secondLayer!(call).secondLayer' because it eventually calls 'foo'. secondLayer calls `call!foo`, but since that is inferred too, we don't want to put the blame there. So it doesn't issue a message about that per se (it could, but it would be useless error message spam). Instead, it keeps going until it hits a non-inferred function or inferred function that fails because it uses a built in (like a ~ b or the new keyword, etc.) and reports the first one of those it sees. A real world case of this would be: import std.range; import std.algorithm; void main() nogc { string foo; auto a = foo.retro(); foreach(item; a) {} } Well, imagine that with a bunch of maps and filters too, your regular range pipeline to make it more complicated, but even this short test case gives you: lll.d(7): Error: nogc function 'D main' cannot call non- nogc function 'std.range.retro!string.retro.Result!().Result.popFront' lll.d(7): Error: nogc function 'D main' cannot call non- nogc function 'std.range.retro!string.retro.Result!().Result.front' You can figure it has to do with `retro` and work around here, but if it has more maps and filters and so on, it would be really hard to figure out what this is (I had to trace this on IRC for a newb). And even if you did figure it was retry... why? Why wouldn't that work? Imagine the case of a unittest that is trying to compile this to test the library. The error message could solve that very quickly by saying "because it eventually calls `std.range.primitives.popBack` which is not nogc because of `throw new Exception`. This would make inferred attributes much better and take away one of my three major complaints against them in my recent reddit rant, and it is all knowledge the compiler already has.... --
May 06 2017