www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Exception handling

reply ANtlord <antlord92 gmail.com> writes:
Hello! I've tried to use nothrow keyword and I couldn't get a 
state of function satisfied the keyword. I have one more method 
that can throw an exception; it is called inside nothrow method. 
Every type of an exception from the throwable method is handled 
by the nothow method.

ubyte throwable_fn(ubyte state) {
	if(state < 2) {
		return 1;
	} else if(state == 3) {
		throw new MyException1("qwe");
	} else {
		throw new MyException2("asd");
	}
}

void nothrowable_fn() nothrow {
	try {
		auto val = throwable_fn(3);
		// do success staff
	} catch(MyException1 e) {
		// handle error 1
	} catch(MyException2 e) {
		// handle error 2
	}
}


I can't compile this. I get an error says nothrowable_fn function 
can't be nothrow. I get the message until I handle Exception 
class. But it is not appropriate for me because I can get another 
exception of another type. I mean case when code will be updated 
and new exceptions will come with a new piece of code.

How can I achieve nothrow statement without catching of an 
instance of Exception class? Thanks. Sorry if my English is not 
clear.
Jul 14
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 07/14/2017 12:36 PM, ANtlord wrote:
 Hello! I've tried to use nothrow keyword and I couldn't get a state of
 function satisfied the keyword. I have one more method that can throw an
 exception; it is called inside nothrow method. Every type of an
 exception from the throwable method is handled by the nothow method.

 ubyte throwable_fn(ubyte state) {
     if(state < 2) {
         return 1;
     } else if(state == 3) {
         throw new MyException1("qwe");
     } else {
         throw new MyException2("asd");
     }
 }
Although it's obvious to us that there are only those two exceptions, the compiler cannot in general know that.
 void nothrowable_fn() nothrow {
     try {
         auto val = throwable_fn(3);
         // do success staff
     } catch(MyException1 e) {
         // handle error 1
     } catch(MyException2 e) {
         // handle error 2
     }
All you need is to catch Exception there as well: catch(Exception) { assert(false, "throwable_fn threw something unexpected"); } Ali
Jul 14
next sibling parent reply Moritz Maxeiner <moritz ucworks.org> writes:
On Friday, 14 July 2017 at 20:22:21 UTC, Ali Çehreli wrote:
 On 07/14/2017 12:36 PM, ANtlord wrote:
 Hello! I've tried to use nothrow keyword and I couldn't get a
state of
 function satisfied the keyword. I have one more method that
can throw an
 exception; it is called inside nothrow method. Every type of
an
 exception from the throwable method is handled by the nothow
method.
 ubyte throwable_fn(ubyte state) {
     if(state < 2) {
         return 1;
     } else if(state == 3) {
         throw new MyException1("qwe");
     } else {
         throw new MyException2("asd");
     }
 }
Although it's obvious to us that there are only those two exceptions, the compiler cannot in general know that.
Not in general, no, but if the function's body (and the body of all functions it calls) are available, the compiler can aggregate the exception set and indeed perform a more precise nothrow analysis.
Jul 14
parent reply Jonathan M Davis via Digitalmars-d-learn writes:
On Friday, July 14, 2017 9:06:52 PM MDT Moritz Maxeiner via Digitalmars-d-
learn wrote:
 On Friday, 14 July 2017 at 20:22:21 UTC, Ali Çehreli wrote:
 Although it's obvious to us that there are only those two
 exceptions, the compiler cannot in general know that.
Not in general, no, but if the function's body (and the body of all functions it calls) are available, the compiler can aggregate the exception set and indeed perform a more precise nothrow analysis.
Except that that's not how it actually works, and it would probably violate the language spec if it did. Basically, the compiler _never_ looks at the bodies of other functions when determining which attributes apply. It always uses the signatures. Even if attribute inferrence it involved, the function's attributes (and therefore signature) are determined before any function that's calling it is examined to determine whether it's violating nothrow or nogc or whatnot (or whether it can be nothrow or nogc or whatnot if its attributes are being inferred). For it to work otherwise would actually cause a lot of problems with .di files. - Jonathan M Davis
Jul 14
parent reply Moritz Maxeiner <moritz ucworks.org> writes:
On Friday, 14 July 2017 at 21:20:29 UTC, Jonathan M Davis wrote:
 On Friday, July 14, 2017 9:06:52 PM MDT Moritz Maxeiner via 
 Digitalmars-d- learn wrote:
 On Friday, 14 July 2017 at 20:22:21 UTC, Ali Çehreli wrote:
 Although it's obvious to us that there are only those two 
 exceptions, the compiler cannot in general know that.
Not in general, no, but if the function's body (and the body of all functions it calls) are available, the compiler can aggregate the exception set and indeed perform a more precise nothrow analysis.
Except that that's not how it actually works, and it would probably violate the language spec if it did.
That the compiler currently does not do so is not relevant to the fact that it can do so, if implemented - AFAICT it wouldn't violate the spec.
 Basically, the  compiler _never_ looks at the bodies of other 
 functions when determining which attributes apply. It always 
 [...].
I'm well aware of that, but it doesn't mean that it can't be enhanced to do so (i.e. what it can do, not what it does do).
 For it to work otherwise would actually cause a lot of problems 
 with .di files.
The compiler would simply skip declarations without bodies, i.e. things for them would be exactly as they are now; that's precisely why I wrote that all bodies of called functions must be available for it to work. If one is missing, it just collapsed to what we have today (unless we introduced optional exception set declaring in function signatures, which is controversial).
Jul 14
parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Friday, 14 July 2017 at 23:02:24 UTC, Moritz Maxeiner wrote:
 On Friday, 14 July 2017 at 21:20:29 UTC, Jonathan M Davis wrote:
 Basically, the  compiler _never_ looks at the bodies of other 
 functions when determining which attributes apply. It always 
 [...].
I'm well aware of that, but it doesn't mean that it can't be enhanced to do so (i.e. what it can do, not what it does do).
"Enhancing" the compiler to do so comes at a very very high cost. Which would force the compiler to look at every body it can look at to maybe discover a closed set of execptions. This would kill fast compile-times!
Jul 14
next sibling parent "H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
On Fri, Jul 14, 2017 at 11:09:23PM +0000, Stefan Koch via Digitalmars-d-learn
wrote:
 On Friday, 14 July 2017 at 23:02:24 UTC, Moritz Maxeiner wrote:
 On Friday, 14 July 2017 at 21:20:29 UTC, Jonathan M Davis wrote:
 Basically, the  compiler _never_ looks at the bodies of other
 functions when determining which attributes apply. It always
 [...].
I'm well aware of that, but it doesn't mean that it can't be enhanced to do so (i.e. what it can do, not what it does do).
"Enhancing" the compiler to do so comes at a very very high cost. Which would force the compiler to look at every body it can look at to maybe discover a closed set of execptions. This would kill fast compile-times!
The compiler could internally keep track of which exceptions are thrown by a function when it does a semantic pass on the function body. This doesn't need to be represented in the language itself. Also, when the function body is available and the compiler is compiling code that calls this function, we're going to need to run semantic on that function anyway, so it doesn't hurt to run semantic right then to extract the list of exceptions. Later on semantic will just be no-op for functions that have already gotten semantic triggered by exception scanning. If that function already has semantic run, then the exception list is already available so you just read it. This won't slow the compiler down -- you're still doing the same work, just in a different order. T -- Computers are like a jungle: they have monitor lizards, rams, mice, c-moss, binary trees... and bugs.
Jul 14
prev sibling parent Moritz Maxeiner <moritz ucworks.org> writes:
On Friday, 14 July 2017 at 23:09:23 UTC, Stefan Koch wrote:
 On Friday, 14 July 2017 at 23:02:24 UTC, Moritz Maxeiner wrote:
 On Friday, 14 July 2017 at 21:20:29 UTC, Jonathan M Davis 
 wrote:
 Basically, the  compiler _never_ looks at the bodies of other 
 functions when determining which attributes apply. It always 
 [...].
I'm well aware of that, but it doesn't mean that it can't be enhanced to do so (i.e. what it can do, not what it does do).
"Enhancing" the compiler to do so comes at a very very high cost.
That depends on if, how, and when the compiler frontend currently does other (unrelated to exceptions) semantic analysis of function bodies.
 Which would force the compiler to look at every body it can 
 look at to maybe discover a closed set of execptions. This 
 would kill fast compile-times!
Again, this depends on the exact internals available at the semantic analysis time, but in theory, it should be possible that when a ThrowStatement is encountered, the surrounding scope aggregates the exception's type in it's aggregated exception set (ignoring things not inherited from Exception). I don't think this would necessarily kill fast compile times.
Jul 14
prev sibling parent ANtlord <antlord92 gmail.com> writes:
On Friday, 14 July 2017 at 20:22:21 UTC, Ali Çehreli wrote:
 On 07/14/2017 12:36 PM, ANtlord wrote:

 All you need is to catch Exception there as well:

     catch(Exception) {
         assert(false, "throwable_fn threw something 
 unexpected");
     }

 Ali
Thank you, Ali! You answer for my question again.
 Again, this depends on the exact internals available at the 
 semantic analysis time, but in theory, it should be possible 
 that when a ThrowStatement is encountered, the surrounding 
 scope aggregates the exception's type in it's aggregated 
 exception set (ignoring things not inherited from Exception).
Sounds good. It doesn't appear too hard for implementation. But I tried to understand dmd architecture at least 5 times. Unfortunaly I can't get it. If there is a thing for talking closer then it can help to ask mini questions. I mean something like Slack or Telegram.
Jul 15