Why can't we make reference variables?

Era Scarecrow rtcvb32 at yahoo.com
Tue Aug 28 19:57:26 PDT 2012


On Wednesday, 29 August 2012 at 01:28:49 UTC, Jonathan M Davis 
wrote:
> On Wednesday, August 29, 2012 02:21:28 Tommi wrote:
>> Foreach loops can make reference variables, and function calls 
>> can do it for the parameters passed in. So, my question is, 
>> wouldn't it be better if we could, in general, make reference 
>> variables?
>
> Not going to happen. Unfortunately though, I don't remember all 
> of Walter's reasons for it, so I can't really say why (partly 
> due to complications it causes in the language, I think, but I 
> don't know). Use a pointer, std.typecons.RefCounted, a class, 
> or make your struct a reference type (which would probably mean 
> having the data held in a separate struct with a pointer to it 
> in the outer struct). It's really not hard to have a type which 
> is a reference type if that's what you really want. You just 
> can't declare a ref to a variable as a local variable.

  You would need a flag added to EVERY variable and item to 
specify if it was stack allocated or not. Otherwise it would be 
quite annoying to deal with. The compiler has to work blindly, 
assuming everything is correct. You can ref what you've been 
given but making more permanent references aren't possible 
without bypassing the safeguards.

  Assuming 'ref' works:

  struct S {
    ref int r;
  }

  //ref local variable/stack, Ticking timebomb
  //compiler may refuse
  void useRef(ref S input, int r) {
    input.r = r;
  }

  //should be good, right?
  S useRef2(S input, ref int r) {  //Can declare @safe, right???
    input.r = r; //maybe, maybe not.
    return S;
  }

  //Shy should indirect care if it's local/stack or heap?
  S indirect(ref int r) {
    return useRef2(S(), r);
  }

  //local variables completely okay to ref! Right?
  S indirect2() {
    int r;
    return useRef2(S(), r);
  }

  S someScope() {
    int* pointer = new int(31); //i think that's right
    int local = 127;

    S s;

    //reference to calling stack! (which may be destroyed now);
    //Or worse it may silently work for a while
    useRef(s, 99);
    assert(s.r == 99);
    return s;

    s = useRef2(s, pointer); //or is it *pointer?
    assert(s.r == 31); //good so far if it passes correctly
    return s; //good, heap allocated

    s = useRef2(s, local);
    assert(s.r == 127); //good so far (still local)
    return s; //Ticking timebomb!

    s = indirect(local);
    assert(s.r == 127); //good so far (still local)
    return s; //timebomb!

    s = indirect2();
    return s; //already destroyed! Unknown consequences!
  }

  assuming a flag is silently passed to ensure if it is stack or 
heap allocated, then useRef2 silently becomes...

  //safe! But not C callable!
  S useRef2(S input, ref int r, bool __r_isHeap) {
    assert(__r_isHeap, "Cannot use a stack allocated variable!");
    input.r = r; //now @safe-able!
    return S;
  }

  Or at the end of the scope it could check all structs if the 
ref's had a silent flag specifying if a referenced variable was 
set for local, so it would assert/throw an exception at the end 
of the call.

  Am I wrong?


More information about the Digitalmars-d mailing list