Why can't we make reference variables?

Era Scarecrow rtcvb32 at yahoo.com
Wed Aug 29 05:00:06 PDT 2012


On Wednesday, 29 August 2012 at 04:54:31 UTC, Tommi wrote:
> On Wednesday, 29 August 2012 at 03:17:39 UTC, Era Scarecrow
>> I think that's right; Otherwise ref wouldn't be allowed in 
>> @safe code (at all).
>
> But couldn't the compiler disallow all unsafe ref use in @safe 
> code, and allow all use of ref in @system and @trusted code?

  So.... Ref can only then be used if it's heap allocated... That 
would be the only @safe way, but even that is ridden with 
timebombs.

  int[10] xyz;

  foreach(i; xyz) {
    //all's good, they are copies!
  }

  foreach(ref i; xyz) {
    // cannot use ref, (not even const ref) as it may be unsafe
  }

  //a ref function
  void func(ref int i);

  int *z = new int;
  func(z); //or is it *z? 'Might' be good
  func(xyz[0]); //Compile error, may be unsafe.

  class C {
    int cc;
  }

  struct S {
    int sc;
  }

  C cSomething = new C();
  S sSomething = S();
  S* sSomething2 = new S();

  func(cSomething.cc); //good, heap allocated enforced
  func(sSomething.sc); //error, may be unsafe!
  func(sSomething2.sc); //pointer dereference; It bypasses 
protections since it probably is heap (but not guaranteed), so 
maybe this should fail too.

  sSomething2 = &sSomething;
  func(sSomething2.sc); //back to a timebomb situation but the 
compiler can't verify it! only something from a class could be 
considered safe (maybe)



  Why is it unsafe? Let's assume we did this:

  ref int unsafe; //global ref. Hey it's legal if ref is allowed 
as you want it!

  void func(ref int i) {
    unsafe = i;
  }

  Now I ask you. If any of the 'unsafe' ones were used and then 
the scope ended that held that information and we use unsafe now, 
it can only be a time bomb: All of them stem from them being on 
the stack.

  void someFunc() {
    int stacked = 42;
    func(stacked);
  }

  someFunc();
  writeln(unsafe); //what will this print? Will it crash?

  //some scope. FOR loop? IF statement? who cares?
  {
    int local = 42;
    func(&local); //assuming the pointer bypasses and gets 
dereferenced to get past the heap only compiler problems 
(pointers and classes only) limitations
    writeln(unsafe); //prints 42 as expected
  }

  writeln(unsafe); //????? Scope ended. Now what? can't ensure 
local exists anymore as we reffed a stack


  class Reffed {
    ref int i;
  }

//some scope
  Reffed r = new Reffed();
  Reffed r2 = new Reffed();

  @trusted {
    int local;
    r.i = local; //may or may not work normally, @trusted should 
force it
  }

  //Why not copy a reference from a class?
  //it should be good (heap only), right?
  r2.i = r.i;

  writeln(r.i); //?????
  writeln(r2.i); //?!?!


  To make it 'safe' the only way to do it is ref can only be used 
on heap allocated data (or global fixed data). The current 
implementation as I see it anything referenced is safe because 
you can only reference something that currently exists (via 
function calls).

  The other way to make it safe is to silently include a flag that 
specifies if it was stack allocated or not, but even that becomes 
more complicated and more of an issue.


More information about the Digitalmars-d mailing list