Bug 15660 – break immutable with pure function and mutable reference params
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2016-02-08T20:58:19Z
Last change time
2018-03-21T07:24:52Z
Keywords
accepts-invalid, safe
Assigned to
No Owner
Creator
Iakh
Comments
Comment #0 by iaktakh — 2016-02-08T20:58:19Z
Compiler can't determine result of pure function is not unique
import std.stdio;
struct S
{
void[] arr; // with int instead of void program doesn't compiles
auto f() pure @safe
{
int[] a = new int[4];
arr = a;
return a;
}
}
void main() @safe
{
S s;
immutable a = s.f();
int[] b = (cast(int[])s.arr);
writeln(a); // [0, 0, 0, 0]
b[0] = 1;
writeln(a); // [1, 0, 0, 0]
}
Comment #1 by iaktakh — 2016-02-08T22:07:22Z
Also this works
import std.stdio;
class A
{
int i;
}
class B : A {}
struct S
{
A a;
auto f() pure @safe
{
B b = new B;
a = b;
return b;
}
}
void main() @safe
{
S s;
immutable a = s.f();
A b = s.a;
writeln(a.i);
b.i = 1;
writeln(a.i);
}
Comment #2 by schveiguy — 2016-02-09T16:35:43Z
This doesn't require member functions.
int[] f(ref void[] m) pure
{
auto result = new int[5];
m = result;
return result;
}
void main()
{
void[] v;
immutable x = f(v);
}
One significant problem here is that the compiler may not consider the parameter to f in these cases to be a *return* avenue, only a parameter. The compiler should take into account references to ensure that they cannot escape the same data that is being returned.
Fixing this may break a lot of code, but probably for the better. May need a deprecation cycle for this.
Comment #3 by iaktakh — 2016-02-09T17:48:25Z
(In reply to Steven Schveighoffer from comment #2)
Even this works:
import std.stdio;
int[] f(void[] a) @safe pure
{
return cast(int[])a;
}
void main() @safe
{
int[] a = new int[4];
immutable b = a.f();
writeln(b);
a[0] = 1;
writeln(b);
}
> One significant problem here is that the compiler may not consider the
> parameter to f in these cases to be a *return* avenue, only a parameter. The
> compiler should take into account references to ensure that they cannot
> escape the same data that is being returned.
So not only escape. Compiler just traverses params's AST and search for
exactly match with ReturnType.
> Fixing this may break a lot of code, but probably for the better. May need a
> deprecation cycle for this.
Comment #4 by schveiguy — 2016-02-09T18:51:45Z
(In reply to Iakh from comment #3)
> (In reply to Steven Schveighoffer from comment #2)
> Even this works:
> import std.stdio;
>
> int[] f(void[] a) @safe pure
> {
> return cast(int[])a;
> }
In this case, you are using a cast. The compiler pretty much gives up trying to ensure anything when you cast, so I think it's OK to allow that.
Although, I thought such a cast wouldn't work in @safe code.
Comment #5 by iaktakh — 2016-02-09T21:05:08Z
(In reply to Steven Schveighoffer from comment #4)
> In this case, you are using a cast. The compiler pretty much gives up trying
> to ensure anything when you cast, so I think it's OK to allow that.
>
> Although, I thought such a cast wouldn't work in @safe code.
Me too. Casting of array types does in reinterpret_cast manner. So it's a
bug in @safe definition.
Comment #6 by bugzilla — 2016-08-26T01:22:19Z
(In reply to Steven Schveighoffer from comment #4)
> (In reply to Iakh from comment #3)
> > (In reply to Steven Schveighoffer from comment #2)
> > Even this works:
> > import std.stdio;
> >
> > int[] f(void[] a) @safe pure
> > {
> > return cast(int[])a;
> > }
>
> In this case, you are using a cast. The compiler pretty much gives up trying
> to ensure anything when you cast, so I think it's OK to allow that.
>
> Although, I thought such a cast wouldn't work in @safe code.
And indeed, it no longer is compilable:
test.d(3): Error: cast from void[] to int[] not allowed in safe code