| Thread overview | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
|
July 14, 2017 Exception handling | ||||
|---|---|---|---|---|
| ||||
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.
| ||||
July 14, 2017 Re: Exception handling | ||||
|---|---|---|---|---|
| ||||
Posted in reply to ANtlord | 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
| |||
July 14, 2017 Re: Exception handling | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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.
| |||
July 14, 2017 Re: Exception handling | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Moritz Maxeiner | 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
| |||
July 14, 2017 Re: Exception handling | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | 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). | |||
July 14, 2017 Re: Exception handling | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Moritz Maxeiner | 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!
| |||
July 14, 2017 Re: Exception handling | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Stefan Koch | 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. | |||
July 14, 2017 Re: Exception handling | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Stefan Koch | 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. | |||
July 15, 2017 Re: Exception handling | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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. | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply