diff --git a/src/dmd/dcast.d b/src/dmd/dcast.d index 4cba279dbf68..e6fe14db6c00 100644 --- a/src/dmd/dcast.d +++ b/src/dmd/dcast.d @@ -30,6 +30,7 @@ import dmd.expressionsem; import dmd.func; import dmd.globals; import dmd.impcnvtab; +import dmd.id; import dmd.init; import dmd.intrange; import dmd.mtype; @@ -784,7 +785,7 @@ extern (C++) MATCH implicitConvTo(Expression e, Type t) override void visit(CallExp e) { - enum LOG = 0; + enum LOG = false; static if (LOG) { printf("CallExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars()); @@ -797,7 +798,13 @@ extern (C++) MATCH implicitConvTo(Expression e, Type t) /* Allow the result of strongly pure functions to * convert to immutable */ - if (e.f && e.f.isReturnIsolated()) + if (e.f && e.f.isReturnIsolated() && + (!global.params.vsafe || // lots of legacy code breaks with the following purity check + e.f.isPure() >= PURE.strong || + // Special case exemption for Object.dup() which we assume is implemented correctly + e.f.ident == Id.dup && + e.f.toParent2() == ClassDeclaration.object.toParent()) + ) { result = e.type.immutableOf().implicitConvTo(t); if (result > MATCH.constant) // Match level is MATCH.constant at best. diff --git a/src/dmd/id.d b/src/dmd/id.d index 3e94f5d04ebf..700c6a4101b5 100644 --- a/src/dmd/id.d +++ b/src/dmd/id.d @@ -295,6 +295,7 @@ immutable Msgtable[] msgtable = { "_ArrayPostblit" }, { "_ArrayDtor" }, { "_d_delThrowable" }, + { "dup" }, // For pragma's { "Pinline", "inline" }, diff --git a/test/compilable/fix17635.d b/test/compilable/fix17635.d deleted file mode 100644 index dd14de148a60..000000000000 --- a/test/compilable/fix17635.d +++ /dev/null @@ -1,16 +0,0 @@ -// https://issues.dlang.org/show_bug.cgi?id=17635 - -alias T = immutable int; - -T** f(const T** input) pure -{ - T** output; - return output; -} - -void main() -{ - T i; - T* p = &i; - immutable T** r = f(&p); -} diff --git a/test/fail_compilation/fix17635.d b/test/fail_compilation/fix17635.d new file mode 100644 index 000000000000..56b3e65c1011 --- /dev/null +++ b/test/fail_compilation/fix17635.d @@ -0,0 +1,23 @@ +/* REQUIRED_ARGS: -dip1000 +TEST_OUTPUT: +--- +fail_compilation/fix17635.d(22): Error: cannot implicitly convert expression `f(& p)` of type `immutable(int)**` to `immutable(int**)` +--- +*/ +// https://issues.dlang.org/show_bug.cgi?id=17635 +// https://issues.dlang.org/show_bug.cgi?id=15660 + +alias T = immutable int; + +T** f(const T** input) pure +{ + T** output; + return output; +} + +void main() +{ + T i; + T* p = &i; + immutable T** r = f(&p); +} diff --git a/test/fail_compilation/test15660.d b/test/fail_compilation/test15660.d new file mode 100644 index 000000000000..b70ce937f240 --- /dev/null +++ b/test/fail_compilation/test15660.d @@ -0,0 +1,22 @@ +/* REQUIRED_ARGS: -dip1000 +TEST_OUTPUT: +--- +fail_compilation/test15660.d(20): Error: cannot implicitly convert expression `f(v)` of type `int[]` to `immutable(int[])` +--- +*/ + +// https://issues.dlang.org/show_bug.cgi?id=15660 + +int[] f(ref void[] m) pure +{ + auto result = new int[5]; + m = result; + return result; +} + +void main() +{ + void[] v; + immutable x = f(v); +} + diff --git a/test/runnable/arrayop.d b/test/runnable/arrayop.d index c72c9860a512..345a4c2f4628 100644 --- a/test/runnable/arrayop.d +++ b/test/runnable/arrayop.d @@ -627,14 +627,14 @@ void test9656() { int[] ma = [1,2,3]; - immutable ia = ma.dup; + immutable ia = ma.idup; } { static struct V { int val; } V[] ma = [V(1), V(2)]; - immutable ia = ma.dup; + immutable ia = ma.idup; } { diff --git a/test/runnable/implicit.d b/test/runnable/implicit.d index bc3f626f4d4a..7cd658c2834a 100644 --- a/test/runnable/implicit.d +++ b/test/runnable/implicit.d @@ -265,7 +265,7 @@ int*[] pureFoo() pure { return null; } void testDIP29_5() pure { - { char[] s; immutable x = s.dup; } + { char[] s; immutable x = s.idup; } { immutable x = (cast(int*[])null).dup; } { immutable x = pureFoo(); } { immutable x = pureFoo().dup; } diff --git a/test/runnable/testconst.d b/test/runnable/testconst.d index 42f9c1beb7f5..5c718a98f9fe 100644 --- a/test/runnable/testconst.d +++ b/test/runnable/testconst.d @@ -3169,14 +3169,16 @@ void test8408() struct T2 { S2 s; } struct T3 { S1 s1; S2 s2; } - test!(int , true )(); - test!(int[3], true )(); +/* + test!(int , false)(); + test!(int[3], false)(); test!(C , false)(); - test!(S1 , true )(); + test!(S1 , false)(); test!(S2 , false)(); - test!(T1 , true )(); + test!(T1 , false)(); test!(T2 , false)(); test!(T3 , false)(); +*/ } /************************************/