ref is unsafe
Zach the Mystic
reachBUTMINUSTHISzach at gOOGLYmail.com
Sat Jan 5 13:26:51 PST 2013
I've here formalized how I think the constraints on a non-scope
ref taking and ref returning function should work. This
represents a whole addition to the type system. The attribute
"@outref" from my previous post has been shortened to keyword
"out" (must come before parentheses). This is all I have left to
say about this topic:
ref int lugs(ref int a) { return a; }
ref int h(ref int a)
{
return lugs(a); // Okay
int local;
return lugs(local); // Error: the result of a function which
accepts a local as non-scope ref and returns ref is treated as
local and cannot be escaped unless that function is marked "out"
int* p = &lugs(local); // Same error
}
int d;
out ref int saml(ref int a)
{
return *(new int); // Fine
return d; // Fine
return a; // Error: a function marked "out" may not escape a
non-scope ref parameter
}
ref int lugh(ref int a) { return a; }
out ref int druh(ref int a)
{
return lugh(a); // Error: a function marked "out" may not
escape the result of a function which accepts its non-scope ref
parameter and returns a ref unless that function is also marked
"out"
}
out int boops(ref int a) {} // Error: a function marked "out"
must return a reference
out ref int bop(int a, in ref b, scope ref c) {} // Error: a
non-member function marked "out" must accept at least one
non-scope ref parameter
// "cast(out)" provides all needed flexibility:
out ref int lit(ref int a)
{
return cast(out) a; // Not @safe
// But with @trusted blocks, we could do:
@trusted { return cast(out) a; } // @safe
// And with @trusted statements, the brackets are gone:
@trusted return cast(out) a; // @safe
// Otherwise, this function must be marked "@trusted"
}
// You can use cast(out) anywhere:
ref int hugs(ref int a) { return a; }
ref int g(ref int a)
{
int local;
return cast(out) (hugs(local)); // Okay
return cast(out) local; // Okay??
return hugs(cast(out) local); // Won't know what hit 'em
}
// Nor did I forget about structs:
struct S
{
int _i;
static int _s;
out ref int club() { return _i; } // Error: a member function
marked "out" may not escape a non-static field
out ref int trob() { return _s; } // Okay
out ref int blub() { return cast(out) _i; } //Okay
}
struct B { int _i; ref int snub() { return _i; } }
ref int bub()
{
B b;
return b.snub(); // Error: the result of a local instance's
non-static method which returns ref is considered local and may
not be escaped unless that method is marked "out"
int* i = &b.snub(); // Same error
}
More information about the Digitalmars-d
mailing list