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