July 10, 2017 Re: proposed @noreturn attribute | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Sabalausky (Abscissa) | On Sun, Jul 09, 2017 at 02:49:35PM -0400, Nick Sabalausky (Abscissa) via Digitalmars-d wrote: > On 07/09/2017 06:51 AM, Daniel N wrote: > > On Sunday, 9 July 2017 at 10:31:47 UTC, Mr.D wrote: > > > On Saturday, 8 July 2017 at 10:15:39 UTC, Walter Bright wrote: > > > > > > > Has anyone a better idea? > > > > > > What about > > > > > > scope(exit) assert(0); > > > > > > ? > > > > void func() > > out { assert(0); } > > body > > { > > } > > Too indirect and verbose. An attribute or special "return type" would just cut straight to the case. If DIP 1009 is accepted, this would not be verbose at all: void func() out(false) // it even tells you it won't return { ... } Plus, this has the advantage that you can specify a valid return type for when you need to override a base class method, e.g.: class JitCompiler { Code compile(string code); } class InvalidCompiler : JitCompiler { override Code compile(string code) out(false) {...} } A Bottom type that implicitly converts to anything would also fit the bill, granted, but does require changing the language. The main thing I have against adding a Bottom type is that it adds yet another built-in type to the language, which means (1) a combinatorial explosion of existing language constructs combined with the new type, with currently-unknown consequences (and possibly corner cases we haven't thought of that will come back to bite us), (2) yet another special type newcomers have to learn with special semantics (I can already anticipate complaints to D.learn about what's the difference between null and bottom); (3) having to implement lots of compiler changes to handle how this new type interacts with operators and other types in all possible cases; (4) all of this just for something that (a) is only rarely used, and (b) could have been easily implemented by adding @noreturn or using existing contract syntax without adding a whole new basic type to the language. Honestly, I'd vote for @noreturn as the simplest, most straightforward solution, and the only reason I'm arguing for out{assert(0);} (or out(false) if DIP 1009 is accepted) is because people are all up in arms about adding Gosh Yet Another Special UDA In Addition To The Numerous Special UDAs We Already Have Like @safe and @nogc. T -- The diminished 7th chord is the most flexible and fear-instilling chord. Use it often, use it unsparingly, to subdue your listeners into submission! |
July 10, 2017 Re: proposed @noreturn attribute | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 7/10/2017 4:00 AM, Steven Schveighoffer wrote:
> But I have to ask, what is the benefit of statically determining that a function is noreturn?
It is useful anywhere dataflow analysis is useful.
FunctionThatDoesnotReturn();
a = b; // error: unreachable code
|
July 10, 2017 Re: proposed @noreturn attribute | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On 7/10/17 2:38 PM, Walter Bright wrote:
> On 7/10/2017 4:00 AM, Steven Schveighoffer wrote:
>> But I have to ask, what is the benefit of statically determining that a function is noreturn?
>
> It is useful anywhere dataflow analysis is useful.
>
> FunctionThatDoesnotReturn();
> a = b; // error: unreachable code
That doesn't require static introspection. The compiler can see that, the user doesn't have to worry about it.
Note, one thing that hasn't been mentioned is how we are now going to be able to make regular functions noreturn. This means templates that accept aliases will now have to deal with the possibility that those aliases are noreturn.
So if the compiler, for instance, marks the above as an error, what happens here?
foo(alias f)()
{
f();
auto a = b;
}
if f is a noreturn function, is this instantiation an error? That's going to get messy. It's not a problem today, because you can't alias `assert`, and the compiler doesn't care about other functions that don't return (even if they are completely available).
I learned the hard way with inout not to proactively make obvious errors errors. For instance, you can't return inout if you don't have any inout parameters. It makes complete logical sense when you think about it, just use const. This leads to the (inout int = 0) crap we see everywhere in phobos.
-Steve
|
July 10, 2017 Re: proposed @noreturn attribute | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On 2017-07-08 12:15, Walter Bright wrote: > C compilers (and by extension C++ compilers) usually have an extension > which allows a function to be marked as one that never returns. The > point of this is it enables improved data flow analysis and better code > being generated. > > Noreturn functions crop up in things like assert's and enforce's. DMD > internally hardcodes a few functions it knows about that are noreturn, > and the DMD optimizer and codegen take advantage of it. > > But when people write their own assert's and enforce's, this falls > apart. While the programs will still work, they won't be as efficient as > they could be. I'm going to ask the stupid question: I understand that this is for the compiler to generate better code. But, since the attribute (or whatever it is) indicates that a function won't return, it can only be used in very few cases. Are those few cases worth optimizing for? -- /Jacob Carlborg |
July 10, 2017 Re: proposed @noreturn attribute | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Monday, 10 July 2017 at 18:50:54 UTC, Steven Schveighoffer wrote:
> On 7/10/17 2:38 PM, Walter Bright wrote:
>> On 7/10/2017 4:00 AM, Steven Schveighoffer wrote:
>>> But I have to ask, what is the benefit of statically determining that a function is noreturn?
>>
>> It is useful anywhere dataflow analysis is useful.
>>
>> FunctionThatDoesnotReturn();
>> a = b; // error: unreachable code
>
> That doesn't require static introspection. The compiler can see that, the user doesn't have to worry about it.
>
> Note, one thing that hasn't been mentioned is how we are now going to be able to make regular functions noreturn. This means templates that accept aliases will now have to deal with the possibility that those aliases are noreturn.
>
> So if the compiler, for instance, marks the above as an error, what happens here?
>
> foo(alias f)()
> {
> f();
> auto a = b;
> }
>
> if f is a noreturn function, is this instantiation an error?
Currently not. This is either a bug or the compiler's flow analysis is not robust enough to detect this case.
int b;
auto foo(alias f)()
{
f();
auto a = b; //no unreachable code error
}
void main()
{
foo!(() => assert(0))();
}
|
July 10, 2017 Re: proposed @noreturn attribute | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On Monday, 10 July 2017 at 18:09:54 UTC, H. S. Teoh wrote:
> On Sun, Jul 09, 2017 at 02:49:35PM -0400, Nick Sabalausky (Abscissa) via Digitalmars-d wrote:
>> On 07/09/2017 06:51 AM, Daniel N wrote:
>> > On Sunday, 9 July 2017 at 10:31:47 UTC, Mr.D wrote:
>> > > On Saturday, 8 July 2017 at 10:15:39 UTC, Walter Bright wrote:
>> > >
>> > > > Has anyone a better idea?
>> > >
>> > > What about
>> > >
>> > > scope(exit) assert(0);
>> > >
>> > > ?
>> >
>> > void func()
>> > out { assert(0); }
>> > body
>> > {
>> > }
>>
>> Too indirect and verbose. An attribute or special "return type" would just cut straight to the case.
>
> If DIP 1009 is accepted, this would not be verbose at all:
>
> void func()
> out(false) // it even tells you it won't return
> {
> ...
> }
>
> Plus, this has the advantage that you can specify a valid return type for when you need to override a base class method, e.g.:
>
> class JitCompiler {
> Code compile(string code);
> }
> class InvalidCompiler : JitCompiler {
> override Code compile(string code) out(false) {...}
> }
>
> A Bottom type that implicitly converts to anything would also fit the bill, granted, but does require changing the language.
>
> The main thing I have against adding a Bottom type is that it adds yet another built-in type to the language, which means (1) a combinatorial explosion of existing language constructs combined with the new type, with currently-unknown consequences (and possibly corner cases we haven't thought of that will come back to bite us), (2) yet another special type newcomers have to learn with special semantics (I can already anticipate complaints to D.learn about what's the difference between null and bottom); (3) having to implement lots of compiler changes to handle how this new type interacts with operators and other types in all possible cases; (4) all of this just for something that (a) is only rarely used, and (b) could have been easily implemented by adding @noreturn or using existing contract syntax without adding a whole new basic type to the language.
>
> Honestly, I'd vote for @noreturn as the simplest, most straightforward solution, and the only reason I'm arguing for out{assert(0);} (or out(false) if DIP 1009 is accepted) is because people are all up in arms about adding Gosh Yet Another Special UDA In Addition To The Numerous Special UDAs We Already Have Like @safe and @nogc.
>
+1
|
July 10, 2017 Re: proposed @noreturn attribute | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | Jacob Carlborg wrote:
> I'm going to ask the stupid question: I understand that this is for the compiler to generate better code. But, since the attribute (or whatever it is) indicates that a function won't return, it can only be used in very few cases. Are those few cases worth optimizing for?
the case that makes @noreturn worth having is even not optimizing, but don't adding visual noise at the call site.
case Smth: error("boo");
case Other: ...
oops. i know that `error()` will never return, but compiler doesn't, and insisting on adding `break;` there.
sure, i can either put break, or always put `assert(0);` after noreturn functions, but hey, aren't we invented computers exactly to lay off such borning things onto them!? ;-)
|
July 10, 2017 Re: proposed @noreturn attribute | ||||
---|---|---|---|---|
| ||||
Posted in reply to Meta | On 7/10/2017 12:05 PM, Meta wrote:
> Currently not. This is either a bug or the compiler's flow analysis is not robust enough to detect this case.
Flow analysis relies on the function's signature, not its implementation, and currently the signature contains no information about noreturn.
Addressing this is the whole point of this thread.
|
July 10, 2017 Re: proposed @noreturn attribute | ||||
---|---|---|---|---|
| ||||
Posted in reply to Meta | On 7/10/17 3:05 PM, Meta wrote: > On Monday, 10 July 2017 at 18:50:54 UTC, Steven Schveighoffer wrote: >> On 7/10/17 2:38 PM, Walter Bright wrote: >>> On 7/10/2017 4:00 AM, Steven Schveighoffer wrote: >>>> But I have to ask, what is the benefit of statically determining that a function is noreturn? >>> >>> It is useful anywhere dataflow analysis is useful. >>> >>> FunctionThatDoesnotReturn(); >>> a = b; // error: unreachable code >> >> That doesn't require static introspection. The compiler can see that, the user doesn't have to worry about it. >> >> Note, one thing that hasn't been mentioned is how we are now going to be able to make regular functions noreturn. This means templates that accept aliases will now have to deal with the possibility that those aliases are noreturn. >> >> So if the compiler, for instance, marks the above as an error, what happens here? >> >> foo(alias f)() >> { >> f(); >> auto a = b; >> } >> >> if f is a noreturn function, is this instantiation an error? > > Currently not. This is either a bug or the compiler's flow analysis is not robust enough to detect this case. I think the implication from Walter is that f would be treated just like a direct call to assert(0) (i.e. it doesn't return). So where code like this produces an "unreachable statement" error: void foo() { assert(0); auto a = b; } with dmd -w, code like the above will potentially produce an unreachable code error if f is a noreturn (the compiler can now do dataflow analysis and determine it's unreachable). This means that you get errors for some instantiations. Which ironically means you'd need to do something like this: void foo(alias f)() { f(); static if(!isNoreturn!f) { auto a = 5; ...// etc. } } Today, it's not a big issue. We can't alias `assert` function directly, so it's obvious where it's an assert or not (because you have to spell it out!). We have similar problems today with generic code causing unreachability errors. See for instance https://issues.dlang.org/show_bug.cgi?id=14835 -Steve |
July 10, 2017 Re: proposed @noreturn attribute | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On 7/10/2017 12:02 PM, Jacob Carlborg wrote:
> Are those few cases worth optimizing for?
Yes. Not having it makes enforce(), for example, generate poor code.
|
Copyright © 1999-2021 by the D Language Foundation