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
}

Reply via email to