Bug 10506 – Purity should not be checked in a mixin statement
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-06-29T12:59:00Z
Last change time
2013-07-05T11:22:32Z
Keywords
pull, rejects-valid
Assigned to
nobody
Creator
andrej.mitrovich
Comments
Comment #0 by andrej.mitrovich — 2013-06-29T12:59:23Z
-----
import std.string;
void test() pure
{
mixin(["foo", "bar"].join());
}
void main() {}
-----
> test.d(5): Error: pure function 'test.test' cannot call impure function 'std.array.join!(string[]).join'
> test.d(5): Error: found 'EOF' when expecting ';' following statement
> test.d(5): Error: undefined identifier foobar
I think the above should be allowed. I can't think of a case where the code which *produces* the string to be mixed in can somehow affect the purity of the function the mixin statement is in.
Comment #1 by k.hara.pg — 2013-06-30T03:04:01Z
Currently (from 2.063) compiler disables purity check in CTFE context.
void foobar() pure {}
string gen() // impure
{ return "foobar;"; }
void test() pure
{
mixin(gen()); // succeed to compile
}
That was the std.array.join issue. It uses std.array.Appender, but Appender had impure operation until very recent days.
https://github.com/D-Programming-Language/phobos/commit/4da1639c98cb73d07858b17c2d225063889e4700#L0L2287
(static member function "Appender.newCapacity" was impure)
Right now Appender operation is potentially pure, and in the OP case has been also changed to pure.
Comment #2 by andrej.mitrovich — 2013-06-30T05:25:04Z
(In reply to comment #1)
> That was the std.array.join issue. It uses std.array.Appender, but Appender had
> impure operation until very recent days.
Here's the thing though, aren't all functions when CTFE evaluated pure?
You can't save any state or read global state while in CTFE, so I'm thinking that during a chain of CTFE calls (e.g. join -> appender -> newCapacity), it isn't necessary to check for purity?
Comment #3 by yebblies — 2013-06-30T22:34:45Z
This is issue 6169, which was fixed a while ago. I don't know what compiler version you were using but I double-checked the source and it calls ctfeSemantic like it should.
*** This issue has been marked as a duplicate of issue 6169 ***
Comment #4 by andrej.mitrovich — 2013-07-01T05:29:06Z
(In reply to comment #3)
> This is issue 6169, which was fixed a while ago. I don't know what compiler
> version you were using but I double-checked the source and it calls
> ctfeSemantic like it should.
>
> *** This issue has been marked as a duplicate of issue 6169 ***
Let's try this:
-----
import std.string;
void test() pure
{
mixin(["int ", "x;"].join());
}
void main() {}
-----
2.061: ok
2.062: Error: pure function 'test' cannot call impure function 'join'
2.063: Error: pure function 'test' cannot call impure function 'join'
2.064: ok (but I think this is because join has become pure?)
Note that the test-case in Issue 6169 works in all of these compilers, but not the sample I gave.
Comment #5 by monarchdodra — 2013-07-01T06:00:47Z
(In reply to comment #4)
> (In reply to comment #3)
> > This is issue 6169, which was fixed a while ago. I don't know what compiler
> > version you were using but I double-checked the source and it calls
> > ctfeSemantic like it should.
> >
> > *** This issue has been marked as a duplicate of issue 6169 ***
>
> Let's try this:
>
> -----
> import std.string;
>
> void test() pure
> {
> mixin(["int ", "x;"].join());
> }
>
> void main() {}
> -----
>
> 2.061: ok
> 2.062: Error: pure function 'test' cannot call impure function 'join'
> 2.063: Error: pure function 'test' cannot call impure function 'join'
> 2.064: ok (but I think this is because join has become pure?)
>
> Note that the test-case in Issue 6169 works in all of these compilers, but not
> the sample I gave.
I have reopened 6169 with this usecase:
--------
string bar(string op = "+") @property
{
return "a" ~ op ~ "b";
}
void foo()()
{
int a, b;
int c = mixin(bar);
}
@safe void main()
{
foo!()();
}
--------
main.d(14): Error: safe function 'D main' cannot call system function
'main.foo!().foo'
--------
Observations:
1) The problem is only with @safe, not pure.
2) Calling "min(bar("+"))" also makes the problem go away.
--------
Not sure if this is strictly 6169 or if I should have posted here and un-resolved as duplicate. But in any case, this is (I think) a simpler use case.
Comment #6 by yebblies — 2013-07-01T06:03:13Z
(In reply to comment #4)
>
> Let's try this:
>
> -----
> import std.string;
>
> void test() pure
> {
> mixin(["int ", "x;"].join());
> }
>
> void main() {}
> -----
>
> 2.061: ok
> 2.062: Error: pure function 'test' cannot call impure function 'join'
> 2.063: Error: pure function 'test' cannot call impure function 'join'
> 2.064: ok (but I think this is because join has become pure?)
>
> Note that the test-case in Issue 6169 works in all of these compilers, but not
> the sample I gave.
Ah, I think I know what's going on. Does it possibly work in 2.063 when not
using ufcs? I think it's only getting the direct calls to semantic, but some others are being missed (eg resolveProperties)
Comment #7 by andrej.mitrovich — 2013-07-01T06:10:13Z
(In reply to comment #6)
> Does it possibly work in 2.063 when not using ufcs?
No, I get the same results.