Thread overview
[Issue 4974] New: Cannot have pure constructor due to impure invariant
Oct 02, 2010
Jonathan M Davis
Nov 09, 2010
Don
Nov 09, 2010
Jonathan M Davis
Nov 09, 2010
Don
Jul 10, 2011
yebblies
October 02, 2010
http://d.puremagic.com/issues/show_bug.cgi?id=4974

           Summary: Cannot have pure constructor due to impure invariant
           Product: D
           Version: unspecified
          Platform: Other
        OS/Version: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: nobody@puremagic.com
        ReportedBy: jmdavisProg@gmx.com


--- Comment #0 from Jonathan M Davis <jmdavisProg@gmx.com> 2010-10-02 02:49:43 PDT ---
This code

struct S
{
    this(int x) pure
    {
        this.x = x;
    }

    invariant()
    {
        assert(x >= 0);
    }

    int x;
}

void main()
{
}


results in this compilation error

Error: pure function 'this' cannot call impure function '__invariant'
d.d(8): Error: function d.S.__invariant () is not callable using argument types
()
Error: pure function 'this' cannot call impure function '__invariant'


Maybe this will be fixed by the changes that Don has suggested, I don't know. But with dmd 2.049, it is, as far as I can tell, impossible to have a pure constructor and an invariant - and the lack of a pure constructor really limits how much you can make pure. There doesn't appear to be a way to make invariant pure either.

So, I see three possible solutions

1. Make it possible to mark invariants as pure.
2. Consider invariant pure as long as it doesn't access mutable globals.
3. Have invariant act like it's pure but don't care whether it really is or
(probably better) output a warning if it isn't.


The one I'd like best would be #3 on the theory that it would allow you to use writeln() and have a pure invariant. The invariant would be compiled out in release builds, so it wouldn't affect release code anyway. And if it means that writeln() doesn't print as often due to a pure function call being optimized out, then tough luck. It would just be temporary debugging code anyway. And since there's a halfway decent chance that pure function calls don't get cached in debug builds anyway, then you really wouldn't lose anything.

Now, assuming that #3 isn't acceptable, #2 would likely be the best, since it wouldn't require changing the grammar to somehow mark an invariant as pure, but any of the three would be better than the current situation.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
October 02, 2010
http://d.puremagic.com/issues/show_bug.cgi?id=4974


bearophile_hugs@eml.cc changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bearophile_hugs@eml.cc


--- Comment #1 from bearophile_hugs@eml.cc 2010-10-02 04:29:22 PDT ---
See also bug 3856

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
November 09, 2010
http://d.puremagic.com/issues/show_bug.cgi?id=4974


Don <clugdbug@yahoo.com.au> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |clugdbug@yahoo.com.au


--- Comment #2 from Don <clugdbug@yahoo.com.au> 2010-11-08 19:14:18 PST ---
In DMD2.050, 'pure invariant()' compiles, which was your solution 1. Not sure if that's enough to mark the bug as fixed.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
November 09, 2010
http://d.puremagic.com/issues/show_bug.cgi?id=4974



--- Comment #3 from Jonathan M Davis <jmdavisProg@gmx.com> 2010-11-08 22:36:47 PST ---
Well, marking an invariant as pure does seem to actually make it pure which is a definite improvement, though honestly, I rather like the idea of the compiler acting like all invariants are pure so that you can have pure functions and still be able to use stuff like writeln() in your invariant when debugging. As it is, marking an invariant as pure does seem to make it possible to have pure functions, but it eliminates your ability to print debug statements in invariants.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
November 09, 2010
http://d.puremagic.com/issues/show_bug.cgi?id=4974



--- Comment #4 from bearophile_hugs@eml.cc 2010-11-09 04:13:41 PST ---
(In reply to comment #3)
> I rather like the idea of the compiler
> acting like all invariants are pure so that you can have pure functions and
> still be able to use stuff like writeln() in your invariant when debugging. As
> it is, marking an invariant as pure does seem to make it possible to have pure
> functions, but it eliminates your ability to print debug statements in
> invariants.

A possible solution using the idea in bug 5125 (syntax is temporary):

pure nothrow bool isDebug() {
    debug return true;
    return false;
}

@optional_tag(ifDebug(), pure) invariant() { ...

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
November 09, 2010
http://d.puremagic.com/issues/show_bug.cgi?id=4974



--- Comment #5 from Don <clugdbug@yahoo.com.au> 2010-11-09 04:33:50 PST ---
(In reply to comment #3)
> As
> it is, marking an invariant as pure does seem to make it possible to have pure
> functions, but it eliminates your ability to print debug statements in
> invariants.

I don't think that problem is unique to invariants.  It's the same issue as logging in pure functions, and in CTFE functions.

You should be able to do printf-style debugging in ANY pure function.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
November 09, 2010
http://d.puremagic.com/issues/show_bug.cgi?id=4974



--- Comment #6 from bearophile_hugs@eml.cc 2010-11-09 04:40:16 PST ---
(In reply to comment #5)

> You should be able to do printf-style debugging in ANY pure function.

Do you mean something like this?

pure void foo() {
    debug { printf("foo"); }
}


And even giving the compiler an explicit debug{} tag that is tricky. In general writing is a side effect. So if your programs output is the text it produces, its output may change according to how much the compiler optimizes away pure function calls.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
November 09, 2010
http://d.puremagic.com/issues/show_bug.cgi?id=4974



--- Comment #7 from bearophile_hugs@eml.cc 2010-11-09 04:45:54 PST ---
(In reply to comment #5)

> You should be able to do printf-style debugging in ANY pure function.

Another simple solution is to add a special pure printf version, that's just a pure alias of printf:


pure void foo() {
    pureprintf("foo");
}


pureprintf() is not meant for normal output, but just for debugging and the
like. And the person that uses pureprintf() has to remember that it's not
deterministic, its output may appear or not appear.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
July 10, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=4974


yebblies <yebblies@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
                 CC|                            |yebblies@gmail.com
         Resolution|                            |FIXED


--- Comment #8 from yebblies <yebblies@gmail.com> 2011-07-10 17:31:56 EST ---
Now that we have printing from pure functions inside debug conditions, I think this is all solved.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------