1228 – Class invariants should not be called before the object is fully constructed

D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 1228 - Class invariants should not be called before the object is fully constructed
Summary: Class invariants should not be called before the object is fully constructed
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D1 (retired)
Hardware: Other Linux
: P2 normal
Assignee: Walter Bright
URL:
Keywords:
Depends on:
Blocks:
Reported: 2007年05月11日 13:04 UTC by Jari-Matti Mäkelä
Modified: 2014年02月16日 15:22 UTC (History)
0 users

See Also:


Attachments
Add an attachment (proposed patch, testcase, etc.)

Note You need to log in before you can comment on or make changes to this issue.
Description Jari-Matti Mäkelä 2007年05月11日 13:04:28 UTC
The spec should state whether invariants hold only after the constructor has finished or not. http://www.webber-labs.com/research/paste01.ps contains some discussion about class invariants in Java, and might be helpful. 
The following code shows how D currently checks invariants even before the class has been fully constructed. IMO invariants should hold only after the constructor has finished and there is a valid reference to the object.
Code:
import tango.io.Stdout;
class foo {
 this() {
 Stdout("entering constructor").newline;
 bar();
 Stdout("leaving constructor").newline;
 }
 void bar() {
 Stdout("method bar()").newline;
 }
 invariant {
 Stdout("invariant").newline;
 }
}
void main() {
 auto a = new foo();
}
Output:
entering constructor
invariant
method bar()
invariant
leaving constructor
invariant
Comment 1 Brad Roberts 2007年05月11日 14:25:52 UTC
Invariants are checked after every public member function's execution as well, so the behavior you're seeing at least meets the spec. Now, I can see some arguments for not having invariants checked until construction is complete, but that'd be a change in documented behavior.
Comment 2 Ary Borenszweig 2007年05月11日 15:10:19 UTC
d-bugmail@puremagic.com escribi
Comment 3 Jari-Matti Mäkelä 2007年05月12日 04:11:27 UTC
(In reply to comment #2)
> Sound reasonable to me, too. You can always refactor to:
> 
> class foo {
> 
> this() {
> Stdout("entering constructor").newline;
> barInternal();
> Stdout("leaving constructor").newline;
> }
> 
> void bar() {
> barInternal();
> }
> 
> private void barInternal() {
> Stdout("method bar()").newline;
> }
> 
> invariant {
> Stdout("invariant").newline;
> }
> }
This slows down the release build since at least DMD doesn't inline member functions. Yes, this is a design decision and I'm not sure which one is better.
Comment 4 Walter Bright 2007年07月01日 00:38:19 UTC
Since the invariant is called at the start of public or
exported members, such members should not be called from
constructors. I'll update the documentation to indicate this.
Comment 5 Jari-Matti Mäkelä 2007年07月01日 03:05:48 UTC
(In reply to comment #4)
> Since the invariant is called at the start of public or
> exported members, such members should not be called from
> constructors. I'll update the documentation to indicate this.
Good, updating the docs works for me.
Comment 6 Walter Bright 2007年07月01日 14:02:41 UTC
Fixed DMD 1.018 and DMD 2.002


AltStyle によって変換されたページ (->オリジナル) /