Bug 4995 – invariant() can violate a function's nothrow

Status
NEW
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
Other
OS
Linux
Creation time
2010-10-04T22:49:07Z
Last change time
2024-12-13T17:53:37Z
Keywords
contracts, pull, wrong-code
Assigned to
No Owner
Creator
Jonathan M Davis
See also
https://issues.dlang.org/show_bug.cgi?id=13118, https://issues.dlang.org/show_bug.cgi?id=18494
Moved to GitHub: dmd#18304 →

Comments

Comment #0 by issues.dlang — 2010-10-04T22:49:07Z
Take this program: import std.stdio; struct S { int val() nothrow { return 7; } invariant() { throw new Exception("Hello from your friendly, neighborhood invariant!"); } } void main() { auto s = S(); writeln(s.val); } It results in this output: object.Exception: Hello from invariant ---------------- ./d(nothrow int d.S.val()) [0x807ece2] ./d(_Dmain+0x12) [0x807ed3a] ./d(extern (C) int rt.dmain2.main(int, char**)) [0x8084cd6] ./d(extern (C) int rt.dmain2.main(int, char**)) [0x8084c30] ./d(extern (C) int rt.dmain2.main(int, char**)) [0x8084d1a] ./d(extern (C) int rt.dmain2.main(int, char**)) [0x8084c30] ./d(main+0x96) [0x8084bd6] /usr/lib32/libc.so.6(__libc_start_main+0xe6) [0xf7595c76] ./d() [0x807ec21] This, in spite of the fact that val() is specifically marked as nothrow. This is particularly interesting since the compiler does complain about impure invariants (bug # 4974). Now, I hate to make invariants even pickier about whether they'll compile or let your struct/class compile, but this clearly violates the fact that val() is marked as nothrow. This program should not compile (or at least not with these semantics). I see two options: 1. The compiler should refuse to compile an invariant which throws if any function on the type is nothrow (very annoying, but possible necessary). 2. Merely change the generated code to consider any exception escaping the invariant to result in the invariant failing, as if you had scope(FAILURE) assert(0, "Exception thrown in invariant."); at the top of the invariant. This seems like a much nicer solution to me. Regardless, the code which is currently generated is obviously wrong.
Comment #1 by henning — 2013-06-09T17:19:48Z
Comment #2 by bugzilla — 2014-06-01T20:46:04Z
(In reply to Henning Pohl from comment #1) > https://github.com/D-Programming-Language/dmd/pull/2155 This PR has a number of possible approaches. The difficulty is there are a number of attributes: nothrow, @safe, pure, @nogc, const, immutable, shared that may apply to invariants. Currently, const is applied. The PR applies pure (but does not check it) and @trusted, and adds code to silently convert thrown Exceptions to Errors inside of nothrow functions. I'm uneasy with this. We also have backwards compatibility to be concerned about. 1. I can't think of a legitimate case where invariant can throw an Exception. Calling invariants or not should not be altering the normal behavior of a program. Hence, invariant should be implicitly nothrow. 2. Removal of checks for @system and purity is a hidden escape from the static guarantees of the language - seems wrong to me. 3. I think we can require the existence of a function body for invariants, and then do attribute inference on it.
Comment #3 by robert.schadek — 2024-12-13T17:53:37Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/18304 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB