digitalmars.D - What is nothrow for?
- Janice Caron (50/50) Apr 24 2008 D2.013 just added the "nothrow" keyword, so that one can write, e.g.
- Walter Bright (13/16) Apr 25 2008 "nothrow" is, as you say, a contract. It specifies that a function must
- Michel Fortin (9/19) Apr 25 2008 I presume "aborts, crashes, or hangs" should also include "asserts".
- janderson (4/26) Apr 25 2008 It shouldn't include asserts. Asserts can be disabled and don't cause
- Walter Bright (3/4) Apr 25 2008 Yes. An assert is an error that is not recoverable, so there is no need
- Frank Benoit (2/7) Apr 25 2008 Perhaps to get the stack trace?
- Frits van Bommel (3/11) Apr 25 2008 Getting a stack trace doesn't require actually unwinding the stack, just...
- Walter Bright (3/11) Apr 25 2008 Sure, but that isn't "recovering" from the error. It's just collecting
- Yigal Chripun (14/33) Apr 25 2008 I'd like to point out that you both agree that "nothrow" is a
- janderson (14/50) Apr 25 2008 While attributes are a nice idea for somethings; for things like
- Yigal Chripun (21/38) Apr 25 2008 Regarding optimizations, I don't know if it would be possible with
- Walter Bright (3/6) Apr 25 2008 If attributes had meaning only in a library or for some special tool,
- Yigal Chripun (9/17) Apr 25 2008 if the compiler provides hooks for the attribute writers than an
- Janice Caron (8/10) Apr 25 2008 I don't agree. I think Walter's right. An attribute is a contract, and
- Yigal Chripun (20/32) Apr 25 2008 if I understand you correctly, you want a function that receives an
- Janice Caron (12/15) Apr 25 2008 No, I was merely postulating. It's not something I want, it was merely
- Yigal Chripun (11/30) Apr 25 2008 I don't understand what you're trying to say here...
- Walter Bright (4/5) Apr 25 2008 With nothrow, for example, it can verify that the code inside the
- Max Samukha (8/13) Apr 26 2008 Like in .NET. And the proposed syntax was taken from C#. A number of
- Christopher Wright (3/22) Apr 25 2008 It's a usability argument that Janice is making. She isn't saying that
- Ameer Armaly (9/59) Apr 26 2008 Disclaimer: I know nothing about the internals of compilers, so take it ...
- Janice Caron (5/9) Apr 26 2008 Without the nothrow keyword, the only way it could do that is by
- Bill Baxter (9/22) Apr 26 2008 Yeh, it's the same problem with deducing things like pure and const
- Steven Schveighoffer (11/18) Apr 28 2008 Enter your algorithmic friend, memoization :) The compiler could store
- Yigal Chripun (7/23) Apr 27 2008 After some googling I've stumbled upon Nemerle which apparently already ...
D2.013 just added the "nothrow" keyword, so that one can write, e.g. inf f() nothrow { return 42; } to indicate that f does not throw an exception. My question is, what's the point? The documentation notes that the semantics are not implemented, but I have to ask, why is this desirable in general? Like any annotation, "nothrow" indicates a /contract/. Like any annation, there are two rules (1) if a function is annotated with the nothrowkeyword, then the compiler will emit a compile error within the function body, if the function body of f throws an exception. (2) if the caller of a function requires that the the called function not throw any exceptions, then the compiler will emit a compile error at the caller site if the callee is not annotated with the nothrow keyword. Rule one helps the human. Rule two helps the compiler - but positively /hinders/ the human. The problem is one of logical fallacy - given the proposition "all dogs have four legs", one may /not/ assume that if it has four legs, it must be a dog. Likewise, given the proposition "any function decorated with the nothrow keyword will not throw an exception", one may /not/ assume that if it doesn't throw an exception, then it will be decorated with the nothrow keyword. Here's a simple counterexample: int f() { return 42; } int g() nothrow { return f(); } Once the semantics of nothrow are implemented, the above code will not compile. This is because, /even though/ f doesn't throw any exceptions, the compiler isn't able to prove that (or at least, can't be bothered to prove that) at the time g is compiled. Like all annotations, "nothrow" therefore /propogates/ throughout code. In order to get the above to compile, the user must now decorate f. This is all very well, unless f is in a library, and the user is unable to modify f. In that case, presumably the user must do something like: int g() nothrow { return cast(nothrow) f(); } or perhaps int g() nothrow { try { return f(); } catch(Exception e) { return 0; } } Sure - we could decorate /every/ function which does not throw an exception with "nothrow", but are we really going to do that? So I guess my question is, in what circumstance would "nothrow" be helpful? And is it helpful /enough/ to warrant "polluting" all library code with "nothrow" annotations?
Apr 24 2008
Janice Caron wrote:So I guess my question is, in what circumstance would "nothrow" be helpful? And is it helpful /enough/ to warrant "polluting" all library code with "nothrow" annotations?"nothrow" is, as you say, a contract. It specifies that a function must return normally (unless it aborts, crashes, or hangs). Such annotations: 1. improves the API documentation 2. enables significantly better code generation (if you use a lot of scope statements and struct destructors) 3. nothrow can be very useful in building up transactions, because you know that the components cannot fail 4. destructors cannot throw exceptions (because they are already in one). Andrei has proposed a method to deal with this, but it is as yet unimplemented. For more info, see http://www.gotw.ca/gotw/082.htm and http://www.boost.org/community/exception_safety.html
Apr 25 2008
On 2008-04-25 03:23:39 -0400, Walter Bright <newshound1 digitalmars.com> said:Janice Caron wrote:I presume "aborts, crashes, or hangs" should also include "asserts". After all, one can't assert in release mode so it doesn't hinder the part about better code generation.So I guess my question is, in what circumstance would "nothrow" be helpful? And is it helpful /enough/ to warrant "polluting" all library code with "nothrow" annotations?"nothrow" is, as you say, a contract. It specifies that a function must return normally (unless it aborts, crashes, or hangs).4. destructors cannot throw exceptions (because they are already in one). Andrei has proposed a method to deal with this, but it is as yet unimplemented.Hum, I wonder, can one assert in a destructor? -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Apr 25 2008
Michel Fortin wrote:On 2008-04-25 03:23:39 -0400, Walter Bright <newshound1 digitalmars.com> said:It shouldn't include asserts. Asserts can be disabled and don't cause the problems that exceptions do. -JoelJanice Caron wrote:I presume "aborts, crashes, or hangs" should also include "asserts". After all, one can't assert in release mode so it doesn't hinder the part about better code generation.So I guess my question is, in what circumstance would "nothrow" be helpful? And is it helpful /enough/ to warrant "polluting" all library code with "nothrow" annotations?"nothrow" is, as you say, a contract. It specifies that a function must return normally (unless it aborts, crashes, or hangs).4. destructors cannot throw exceptions (because they are already in one). Andrei has proposed a method to deal with this, but it is as yet unimplemented.Hum, I wonder, can one assert in a destructor?
Apr 25 2008
Michel Fortin wrote:I presume "aborts, crashes, or hangs" should also include "asserts".Yes. An assert is an error that is not recoverable, so there is no need for stack unwinding.
Apr 25 2008
Walter Bright schrieb:Michel Fortin wrote:Perhaps to get the stack trace?I presume "aborts, crashes, or hangs" should also include "asserts".Yes. An assert is an error that is not recoverable, so there is no need for stack unwinding.
Apr 25 2008
Frank Benoit wrote:Walter Bright schrieb:Getting a stack trace doesn't require actually unwinding the stack, just looking at it.Michel Fortin wrote:Perhaps to get the stack trace?I presume "aborts, crashes, or hangs" should also include "asserts".Yes. An assert is an error that is not recoverable, so there is no need for stack unwinding.
Apr 25 2008
Frank Benoit wrote:Walter Bright schrieb:Sure, but that isn't "recovering" from the error. It's just collecting diagnostic information.Michel Fortin wrote:Perhaps to get the stack trace?I presume "aborts, crashes, or hangs" should also include "asserts".Yes. An assert is an error that is not recoverable, so there is no need for stack unwinding.
Apr 25 2008
Walter Bright wrote:Janice Caron wrote:I'd like to point out that you both agree that "nothrow" is a _contract_. That immediately begs the question: why implement it as yet another ad hoc feature instead of making it part of D's DBC (which is yet to be implemented...)? Personally, I don't see the point of constantly adding more annotations and keywords to D2 since it complicates the syntax and makes D2 much less attractive from a syntax POV. D2 will allow the following: pure invariant invariant(int) func(invariant(int)) nothrow; Am I the only one that thinks the above is too much? It's time for a standardized Annotations/Attributes mechanism for D. I'll post my initial suggestion for such a mechanism in a new thread. --YigalSo I guess my question is, in what circumstance would "nothrow" be helpful? And is it helpful /enough/ to warrant "polluting" all library code with "nothrow" annotations?"nothrow" is, as you say, a contract. It specifies that a function must return normally (unless it aborts, crashes, or hangs). Such annotations: 1. improves the API documentation 2. enables significantly better code generation (if you use a lot of scope statements and struct destructors) 3. nothrow can be very useful in building up transactions, because you know that the components cannot fail 4. destructors cannot throw exceptions (because they are already in one). Andrei has proposed a method to deal with this, but it is as yet unimplemented. For more info, see http://www.gotw.ca/gotw/082.htm and http://www.boost.org/community/exception_safety.html
Apr 25 2008
Yigal Chripun wrote:Walter Bright wrote:While attributes are a nice idea for somethings; for things like invariants it would make the client syntax more difficult to read. Also invariant const etc.. could not go into the standard lib because then the compiler would make it much more difficult for the compiler to perform optimizations (Walters point 2). Also it would be more difficult to extend the concept of invariants; for example, to something like functional programming because of attribute system limitations. If your moving something like invariants to attributes, don't forget your not actually reducing the complexity to the end user. Now they have to figure-out what the standard lib is doing also. The complexity only reduces for the compiler writer. -JoelJanice Caron wrote:I'd like to point out that you both agree that "nothrow" is a _contract_. That immediately begs the question: why implement it as yet another ad hoc feature instead of making it part of D's DBC (which is yet to be implemented...)? Personally, I don't see the point of constantly adding more annotations and keywords to D2 since it complicates the syntax and makes D2 much less attractive from a syntax POV. D2 will allow the following: pure invariant invariant(int) func(invariant(int)) nothrow; Am I the only one that thinks the above is too much? It's time for a standardized Annotations/Attributes mechanism for D. I'll post my initial suggestion for such a mechanism in a new thread. --YigalSo I guess my question is, in what circumstance would "nothrow" be helpful? And is it helpful /enough/ to warrant "polluting" all library code with "nothrow" annotations?"nothrow" is, as you say, a contract. It specifies that a function must return normally (unless it aborts, crashes, or hangs). Such annotations: 1. improves the API documentation 2. enables significantly better code generation (if you use a lot of scope statements and struct destructors) 3. nothrow can be very useful in building up transactions, because you know that the components cannot fail 4. destructors cannot throw exceptions (because they are already in one). Andrei has proposed a method to deal with this, but it is as yet unimplemented. For more info, see http://www.gotw.ca/gotw/082.htm and http://www.boost.org/community/exception_safety.html
Apr 25 2008
janderson wrote:While attributes are a nice idea for somethings; for things like invariants it would make the client syntax more difficult to read. Also invariant const etc.. could not go into the standard lib because then the compiler would make it much more difficult for the compiler to perform optimizations (Walters point 2). Also it would be more difficult to extend the concept of invariants; for example, to something like functional programming because of attribute system limitations. If your moving something like invariants to attributes, don't forget your not actually reducing the complexity to the end user. Now they have to figure-out what the standard lib is doing also. The complexity only reduces for the compiler writer. -JoelRegarding optimizations, I don't know if it would be possible with attributes - I guess it depends on the compiler APIs exposed to the attribute writer. I do agree that not _all_things_ should be implemented as attributes. The invariants are a bad example and I just used that to illustrate how complex the D syntax has become. It's like the type system - D provides a a set of built in primitive types like int,char,long,etc.. and a way to use those to create your own via classes/unions/structs... so it may make sense to have a built-in const but IMO nothrow doesn't deserve the same status. I'm also not sure that pure should be provided by D. Look at the link bellow for a Java DBC using annotations. Seems much better than what D provides (nothing.. since it's not implemented). Since D is not backed up by a giant like Sun/MS/Google/etc it makes sense to delegate these features to the community, since it's obvious not high on Walter's todo list and annotations make perfect sense for that. Note, you mention "attribute system limitations" - since D does have that system yet, we do not know what limitations D's system would have compared to the .net or Java implementations. http://en.wikipedia.org/wiki/Java_Modeling_Language
Apr 25 2008
Yigal Chripun wrote:Since D is not backed up by a giant like Sun/MS/Google/etc it makes sense to delegate these features to the community, since it's obvious not high on Walter's todo list and annotations make perfect sense for that.If attributes had meaning only in a library or for some special tool, the compiler cannot extract any useful information from them.
Apr 25 2008
Walter Bright wrote:Yigal Chripun wrote:if the compiler provides hooks for the attribute writers than an attribute would have meaning for the compiler. for example, it should be possible to write a user defined attribute and via a hook, tell the compiler to verify transitivity of it at compile time. BTW, what information does the compiler extract from an attribute? wouldn't it be enough to use the above approach to tell the compiler what to do for each attribute? --YigalSince D is not backed up by a giant like Sun/MS/Google/etc it makes sense to delegate these features to the community, since it's obvious not high on Walter's todo list and annotations make perfect sense for that.If attributes had meaning only in a library or for some special tool, the compiler cannot extract any useful information from them.
Apr 25 2008
On 25/04/2008, Yigal Chripun <yigal100 gmail.com> wrote:if the compiler provides hooks for the attribute writers than an attribute would have meaning for the compiler.I don't agree. I think Walter's right. An attribute is a contract, and only the compiler is in a position to enforce that code complies with contracts. For example, suppose I wanted an attribute that meant "this function does not modify static members" - what kind of "hooks" would make it possible to enforce that contract, if it were not built into the compiler?
Apr 25 2008
Janice Caron wrote:On 25/04/2008, Yigal Chripun <yigal100 gmail.com> wrote:if I understand you correctly, you want a function that receives an instance of some class and an attribute that makes sure that the above function does not modify any static members (data members) of that instance. I'm not sure how the compiler can verify that at all due to polymorphism - the dynamic type of the instance will be known only at run-time. maybe something like the following can work: you should be able to get a list of all the static members of an instance via introspection and for each of those, you'd need to check in your attribute implementation that the old value (before executing the function body) is the same as the one after executing the function body. what if there was a way to "keep" the old value? than you'd throw an exception if (old(var) != var). I don't understand how this can be checked by the compiler at all (even if the attribute is not user defined) without analyzing the entire code of the program. if you compile only one module the compiler does not know if there are derived classes that add more static data members. I'm not sure I'm correct on all of this so please point out errors. somewhat confused, Yigalif the compiler provides hooks for the attribute writers than an attribute would have meaning for the compiler.I don't agree. I think Walter's right. An attribute is a contract, and only the compiler is in a position to enforce that code complies with contracts. For example, suppose I wanted an attribute that meant "this function does not modify static members" - what kind of "hooks" would make it possible to enforce that contract, if it were not built into the compiler?
Apr 25 2008
On 25/04/2008, Yigal Chripun <yigal100 gmail.com> wrote:if I understand you correctly, you wantNo, I was merely postulating. It's not something I want, it was merely an example of something the compiler could do that a library add-on couldn't.I'm not sure how the compiler can verify that at all due to polymorphism - the dynamic type of the instance will be known only at run-time.Who cares? If I'm going to invent an arbitrary attribute, I can define it to do anything I want. Besides, structs have a "this", but not polymorphism, so the compiler could certainly check in the case of structs. To give an even sillier example, a compiler could introduce a function attribute that meant "this function will not modify any variable starting with the letter x". I don't see how an add-on could do that through hooks.
Apr 25 2008
Janice Caron wrote:On 25/04/2008, Yigal Chripun <yigal100 gmail.com> wrote:I don't understand what you're trying to say here... anyway, I've searched the Java docs to see How Java works with annotations.I've found [1] which is a reflective API for build-time. This API provides information about the source code of a program. java 5 had a tool called apt that as of java 6 is part of the compiler, it runs annotation processors on the code. (these are Java programs that use the APIs in [1] and [2] and generate new source files) [1]http://java.sun.com/javase/6/docs/jdk/api/apt/mirror/overview-summary.html [2]http://java.sun.com/javase/6/docs/technotes/guides/apt/index.html --Yigalif I understand you correctly, you wantNo, I was merely postulating. It's not something I want, it was merely an example of something the compiler could do that a library add-on couldn't.I'm not sure how the compiler can verify that at all due to polymorphism - the dynamic type of the instance will be known only at run-time.Who cares? If I'm going to invent an arbitrary attribute, I can define it to do anything I want. Besides, structs have a "this", but not polymorphism, so the compiler could certainly check in the case of structs. To give an even sillier example, a compiler could introduce a function attribute that meant "this function will not modify any variable starting with the letter x". I don't see how an add-on could do that through hooks.
Apr 25 2008
Yigal Chripun wrote:BTW, what information does the compiler extract from an attribute?With nothrow, for example, it can verify that the code inside the function cannot propagate an exception outside of it. I have no idea how you could do that with a user defined attribute.
Apr 25 2008
On Fri, 25 Apr 2008 14:10:23 -0700, Walter Bright <newshound1 digitalmars.com> wrote:Yigal Chripun wrote:intrinsic attributes are treated specially by the IL compiler. For example, DllImport, Obsolete, MarshalAs, StructLayout etc. .NET has a nice extensible attribute system. User defined attributes can be inspected through reflection at run-time. I guess, D could allow to do that at compile time as well.BTW, what information does the compiler extract from an attribute?With nothrow, for example, it can verify that the code inside the function cannot propagate an exception outside of it. I have no idea how you could do that with a user defined attribute.
Apr 26 2008
Walter Bright wrote:Janice Caron wrote:It's a usability argument that Janice is making. She isn't saying that nothrow lacks benefits.So I guess my question is, in what circumstance would "nothrow" be helpful? And is it helpful /enough/ to warrant "polluting" all library code with "nothrow" annotations?"nothrow" is, as you say, a contract. It specifies that a function must return normally (unless it aborts, crashes, or hangs). Such annotations: 1. improves the API documentation 2. enables significantly better code generation (if you use a lot of scope statements and struct destructors) 3. nothrow can be very useful in building up transactions, because you know that the components cannot fail 4. destructors cannot throw exceptions (because they are already in one). Andrei has proposed a method to deal with this, but it is as yet unimplemented. For more info, see http://www.gotw.ca/gotw/082.htm and http://www.boost.org/community/exception_safety.html
Apr 25 2008
"Janice Caron" <caron800 googlemail.com> wrote in message news:mailman.465.1209106347.2351.digitalmars-d puremagic.com...D2.013 just added the "nothrow" keyword, so that one can write, e.g.Disclaimer: I know nothing about the internals of compilers, so take it with a grain of salt: It seems to me that the compiler could figure out whether or not a function throws exceptions and act accordingly; I really don't see why it needs to be told. That means the only real use of nothrow that I could see would be to say that you don't want this function ever throwing an exception in any current or future incarnation.inf f() nothrow { return 42; } to indicate that f does not throw an exception. My question is, what's the point? The documentation notes that the semantics are not implemented, but I have to ask, why is this desirable in general? Like any annotation, "nothrow" indicates a /contract/. Like any annation, there are two rules (1) if a function is annotated with the nothrowkeyword, then the compiler will emit a compile error within the function body, if the function body of f throws an exception. (2) if the caller of a function requires that the the called function not throw any exceptions, then the compiler will emit a compile error at the caller site if the callee is not annotated with the nothrow keyword. Rule one helps the human. Rule two helps the compiler - but positively /hinders/ the human. The problem is one of logical fallacy - given the proposition "all dogs have four legs", one may /not/ assume that if it has four legs, it must be a dog. Likewise, given the proposition "any function decorated with the nothrow keyword will not throw an exception", one may /not/ assume that if it doesn't throw an exception, then it will be decorated with the nothrow keyword. Here's a simple counterexample: int f() { return 42; } int g() nothrow { return f(); } Once the semantics of nothrow are implemented, the above code will not compile. This is because, /even though/ f doesn't throw any exceptions, the compiler isn't able to prove that (or at least, can't be bothered to prove that) at the time g is compiled. Like all annotations, "nothrow" therefore /propogates/ throughout code. In order to get the above to compile, the user must now decorate f. This is all very well, unless f is in a library, and the user is unable to modify f. In that case, presumably the user must do something like: int g() nothrow { return cast(nothrow) f(); } or perhaps int g() nothrow { try { return f(); } catch(Exception e) { return 0; } } Sure - we could decorate /every/ function which does not throw an exception with "nothrow", but are we really going to do that? So I guess my question is, in what circumstance would "nothrow" be helpful? And is it helpful /enough/ to warrant "polluting" all library code with "nothrow" annotations?
Apr 26 2008
On 26/04/2008, Ameer Armaly <ameer.armaly furman.edu> wrote:It seems to me that the compiler could figure out whether or not a function throws exceptions and act accordingly;Without the nothrow keyword, the only way it could do that is by checking not only the function itself, but the function bodies of all functions called by the function, and so, recursively, forever.I really don't see why it needs to be told.With nothrow, it doesn't have to recurse.
Apr 26 2008
Janice Caron wrote:On 26/04/2008, Ameer Armaly <ameer.armaly furman.edu> wrote:Yeh, it's the same problem with deducing things like pure and const (which is the conclusion I came to following our previous discussion on the topic... though I just let the thread fizzle rather than stating this conclusion.). If you want to have the benefits of separate compilation then you have to tell the compiler what to expect of functions without it having to have the bodies of those functions present. --bbIt seems to me that the compiler could figure out whether or not a function throws exceptions and act accordingly;Without the nothrow keyword, the only way it could do that is by checking not only the function itself, but the function bodies of all functions called by the function, and so, recursively, forever.I really don't see why it needs to be told.With nothrow, it doesn't have to recurse.
Apr 26 2008
"Janice Caron" wroteOn 26/04/2008, Ameer Armaly wrote:Enter your algorithmic friend, memoization :) The compiler could store attributes with the functions as they are compiled, marking ones which don't throw exceptions and ones which are pure, etc. in the object files. The only issue then is if you are a developer and you desire a function to be a nothrow, it must be marked by the developer. Otherwise it's like inlining. You never know which functions will be marked nothrow/pure and which ones will not. It also becomes a question of maintainability, if one makes a change in a nothrow function that throws an exception, this is no good for dynamic libraries, who may depend on it keeping the nothrow status. -SteveIt seems to me that the compiler could figure out whether or not a function throws exceptions and act accordingly;Without the nothrow keyword, the only way it could do that is by checking not only the function itself, but the function bodies of all functions called by the function, and so, recursively, forever.
Apr 28 2008
Max Samukha Wrote:On Fri, 25 Apr 2008 14:10:23 -0700, Walter Bright <newshound1 digitalmars.com> wrote:After some googling I've stumbled upon Nemerle which apparently already implements most of my ideas. Nemerle is built on top of .net and has a bootstrapping compiler (the compiler itself is written in Nemerle). Nemerle provides many cool features including macros and attributes. From what I understand, the way macros work is: you write a macro using their Compiler APIs [1] and compile it, when you compile your program you also provide to the compiler the compiled macro DLLs and the compiler uses them as "extensions" to the compiler. This is very powerful and allows the user to even add his own syntax to the language. Nemerle also provides CTFE and generics. When I'll have more time, I'll read more about Nemerle and perhaps I'll write a comparison. IMO, D has a lot to learn from Nemerle and Its IMO superior design (based on what I've seen so far). [1] http://nemerle.org/Class_library -- YigalYigal Chripun wrote:intrinsic attributes are treated specially by the IL compiler. For example, DllImport, Obsolete, MarshalAs, StructLayout etc. .NET has a nice extensible attribute system. User defined attributes can be inspected through reflection at run-time. I guess, D could allow to do that at compile time as well.BTW, what information does the compiler extract from an attribute?With nothrow, for example, it can verify that the code inside the function cannot propagate an exception outside of it. I have no idea how you could do that with a user defined attribute.
Apr 27 2008