February 25, 2008 Re: DMD 1.027 and 2.011 releases | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | Walter Bright, el 20 de febrero a las 18:58 me escribiste: > Graham St Jack wrote: > >It is also very helpful when writing code to know that a function you are calling won't throw an exception - it means you have three kinds of functions: those that don't throw, those with comments telling you what they throw, and those that you need to fix the comments for. > > Experience with this indicates that it is impractical to specify what exceptions a function may throw. The only practical states to specify are: > > 1) does not throw > 2) always throws > 3) might throw > > What is thrown is not reliably computable. For example: > > import foo; > void test() > { > foo.bar(); > } > > What exceptions does test() throw? That would require knowledge of the import foo, which is not necessarily knowable and can change over time. And what's the difference with nothrow? foo.bar's nothrow-ness "is not necessarily knowable and can change over time". It's exactly the same, you're just limiting the way you specify exceptions, but you are specifing them after all. This is like limiting C++ exception specification to nothing or an empty throw() qualifier. -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- Hace diez años tenía una visión Pero nadie más la vió y hoy sigo pidiendo perdón |
February 25, 2008 Re: DMD 1.027 and 2.011 releases | ||||
---|---|---|---|---|
| ||||
Posted in reply to Graham St Jack | Graham St Jack wrote: > It will be a good trick if you can pull it off. I don't see how it can be done without examining the source code of all the called functions, leaving us back where we started with throw specs. > > The C++ approach of a runtime check isn't perfect, but at least it can be done, and provides a more definite form of documentation than comments. Are you sure it does a runtime check for nothrow? > If the static checks aren't done well enough and runtime checks aren't done at all, I would prefer to rely on comments. |
February 25, 2008 Re: DMD 1.027 and 2.011 releases | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | The example would be (reasonably) compilable, without whole-program knowledege, if foo() had an in{} condition which asserted that the index was valid.
It would be possible (though not trivial) for the compiler to say "ah, provided that the caller follows the in{} contract, this function cannot throw an exception."
Walter Bright wrote:
> Ary Borenszweig wrote:
>> Does this mean this will not compile:
>>
>> int foo(int[] someArray, int someIndex) nothrow {
>> return someArray[someIndex];
>> }
>>
>> but this will:
>>
>> int foo(int[] someArray, int someIndex) nothrow {
>> if (someIndex < someArray.length) {
>> return someArray[someIndex];
>> } else {
>> return -1;
>> }
>> }
>
> I don't know yet. But the idea is to do static checking of what can throw.
|
February 26, 2008 Re: DMD 1.027 and 2.011 releases | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ary Borenszweig | Ary Borenszweig wrote:
> Walter Bright escribió:
>> Graham St Jack wrote:
>>>> It would work just like "nothrow" does for C++.
>>>
>>> Just checking - I hope this means that if a nothrow function actually
>>> DID try to throw an exception (by calling something that throws),
>>> compiler-
>>> generated code would trap it and terminate the program with an error
>>> message?
>>
>> No, but it will try to detect errors at compile time.
>
> Does this mean this will not compile:
>
> int foo(int[] someArray, int someIndex) nothrow {
> return someArray[someIndex];
> }
I sincerely hope that design by contract will allow for us to iron out issues like this. Ideally, something very near the following should be valid:
int foo(int[] someArray, int someIndex) nothrow
in{
assert(someIndex < someArray.length && someIndex >= 0);
}
body{
return someArray[someIndex];
}
I've always hoped for in and out contracts to be usable by the compiler for optimization (such as verifying nothrow). I know this looks like it violates the nothrow (when not compiled with the release flag), but I'm ok with that for code I'm debugging. Printing the failed assert and ending the program is more useful to me anyway.
|
February 26, 2008 Re: DMD 1.027 and 2.011 releases | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | == Quote from Walter Bright (newshound1@digitalmars.com)'s article
> Graham St Jack wrote:
> > It will be a good trick if you can pull it off. I don't see how it can be done without examining the source code of all the called functions, leaving us back where we started with throw specs.
> >
> > The C++ approach of a runtime check isn't perfect, but at least it can be done, and provides a more definite form of documentation than comments.
> Are you sure it does a runtime check for nothrow?
I think it depends on the compiler. The MS compiler, for example, ignores exception specs, except
possibly for nothrow (it's been a while and I cant recall). However, isn't the app supposed to terminate if an
exception is thrown from a nothrow routine? I don't have my copy of the spec handy or I'd check.
Sean
|
February 27, 2008 Re: DMD 1.027 and 2.011 releases | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Mon, 25 Feb 2008 08:55:17 -0800, Walter Bright wrote: > Graham St Jack wrote: >> It will be a good trick if you can pull it off. I don't see how it can be done without examining the source code of all the called functions, leaving us back where we started with throw specs. >> >> The C++ approach of a runtime check isn't perfect, but at least it can be done, and provides a more definite form of documentation than comments. > > Are you sure it does a runtime check for nothrow? g++ certainly does runtime checking. I'm sure it does no static checking at all. We use the throw() and throw(list-of-exceptions) specs all the time in our C++ code, relying on the runtime checking to tell us if we get it wrong. This is quite horrible compared to static checking, but it is a lot better than nothing, because we find out what exception was thrown and which throw-spec was violated. The vast majority of functions in our C++ code use an empty throw-spec, so if D had nothrow with some static checking plus a runtime check, I would be better off than I am now with C++. Of course I would be even better off if the static checking was complete, but that seems to be too tricky. > >> If the static checks aren't done well enough and runtime checks aren't done at all, I would prefer to rely on comments. |
February 27, 2008 Re: DMD 1.027 and 2.011 releases | ||||
---|---|---|---|---|
| ||||
Posted in reply to Graham St Jack | == Quote from Graham St Jack (Graham.StJack@internode.on.net)'s article > On Mon, 25 Feb 2008 08:55:17 -0800, Walter Bright wrote: > > Graham St Jack wrote: > >> It will be a good trick if you can pull it off. I don't see how it can be done without examining the source code of all the called functions, leaving us back where we started with throw specs. > >> > >> The C++ approach of a runtime check isn't perfect, but at least it can be done, and provides a more definite form of documentation than comments. > > > > Are you sure it does a runtime check for nothrow? > g++ certainly does runtime checking. I'm sure it does no static checking > at all. > We use the throw() and throw(list-of-exceptions) specs all the time in > our C++ code, relying on the runtime checking to tell us if we get it > wrong. This is quite horrible compared to static checking, but it is a > lot better than nothing, because we find out what exception was thrown > and which throw-spec was violated. > The vast majority of functions in our C++ code use an empty throw-spec, > so if D had nothrow with some static checking plus a runtime check, I > would be better off than I am now with C++. Of course I would be even > better off if the static checking was complete, but that seems to be too > tricky. The nice thing about offering nothrow only is that it implicitly marks any unlabeled routine as one that may throw an exception. The problem in C++ with explicit exception specs is those unlabeled routines--they can throw anything but they're also callable from nothrow routines because they might not actually throw anything. It's a mess. Sean |
February 27, 2008 Re: DMD 1.027 and 2.011 releases | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | On Wed, 27 Feb 2008 00:47:00 +0000, Sean Kelly wrote:
> == Quote from Graham St Jack (Graham.StJack@internode.on.net)'s article
>> On Mon, 25 Feb 2008 08:55:17 -0800, Walter Bright wrote:
>> > Graham St Jack wrote:
>> >> It will be a good trick if you can pull it off. I don't see how it can be done without examining the source code of all the called functions, leaving us back where we started with throw specs.
>> >>
>> >> The C++ approach of a runtime check isn't perfect, but at least it can be done, and provides a more definite form of documentation than comments.
>> >
>> > Are you sure it does a runtime check for nothrow?
>> g++ certainly does runtime checking. I'm sure it does no static
>> checking at all.
>> We use the throw() and throw(list-of-exceptions) specs all the time in
>> our C++ code, relying on the runtime checking to tell us if we get it
>> wrong. This is quite horrible compared to static checking, but it is a
>> lot better than nothing, because we find out what exception was thrown
>> and which throw-spec was violated.
>> The vast majority of functions in our C++ code use an empty throw-spec,
>> so if D had nothrow with some static checking plus a runtime check, I
>> would be better off than I am now with C++. Of course I would be even
>> better off if the static checking was complete, but that seems to be
>> too tricky.
>
> The nice thing about offering nothrow only is that it implicitly marks any unlabeled routine as one that may throw an exception. The problem in C++ with explicit exception specs is those unlabeled routines--they can throw anything but they're also callable from nothrow routines because they might not actually throw anything. It's a mess.
>
>
> Sean
Agreed.
|
February 27, 2008 Re: DMD 1.027 and 2.011 releases | ||||
---|---|---|---|---|
| ||||
Posted in reply to Graham St Jack | Graham St Jack wrote:
> It will be a good trick if you can pull it off. I don't see how it can be done without examining the source code of all the called functions, leaving us back where we started with throw specs.
I think the idea would be that nothrow is part of the function signature and a nothrow function can only call other nothrow functions or wrap any function calls or news in a catch(Exception) (since there's no way to know specifically which exceptions could be thrown).
|
February 27, 2008 Re: DMD 1.027 and 2.011 releases | ||||
---|---|---|---|---|
| ||||
Posted in reply to eao197 | eao197 wrote:
> On Mon, 25 Feb 2008 12:44:15 +0300, Walter Bright <newshound1@digitalmars.com> wrote:
>
>> Ary Borenszweig wrote:
>>> Does this mean this will not compile:
>>> int foo(int[] someArray, int someIndex) nothrow {
>>> return someArray[someIndex];
>>> }
>>> but this will:
>>> int foo(int[] someArray, int someIndex) nothrow {
>>> if (someIndex < someArray.length) {
>>> return someArray[someIndex];
>>> } else {
>>> return -1;
>>> }
>>> }
>>
>> I don't know yet. But the idea is to do static checking of what can throw.
>
> Just my $0.02 about nothrow and DesignByContract: I think that nothrow are incompatible with DbC. A function/method could have contracts or nothrow but not both of them. It is especially actual for virtual (non-final) methods. Suppose that some class has:
>
> class A {
> public void cleanup() nothrow { ... };
> }
>
> so it could be safely used in 'finally' statement:
>
> A someResource = acquireResource();
> try { ... /* some processing */ ... }
> finally {
> someResource.cleanup; /* looks like exception-safe action */
> }
>
> But if there is a derived class B, which overrides cleanup() with postcondition:
>
> class B : A {
> public void cleanup() nothrow
> out { ... some checking ... }
> body { ... some actions ... }
> }
>
> and acquireResource() would return B instead of A, then the code above won't be exception-safe. Moreover the behaviour of 'someResource.cleanup' would depend on compiler switches.
>
So the code generated depends on compiler switches... Isn't this always true? The "nothrow" spec could only actually be used when building release mode, and in non-release mode code, exception handling frames are always set up. This means that nothrow functions can still use assert() and array indexing without worries, since these only throw exceptions in non-release-mode code.
Of course, then problems occur when mixing code compiled with different switches...
|
Copyright © 1999-2021 by the D Language Foundation