[dmd-beta] rvalue references
Andrei Alexandrescu
andrei at erdani.com
Fri Apr 13 11:40:20 PDT 2012
I'm busy right now, give me some time to look over it.
Thanks,
Andrei
On 4/13/12 1:39 PM, kenji hara wrote:
> How about my idea, Andrei?
>
> Kenji Hara
>
> 2012/04/13 17:47 "kenji hara" <k.hara.pg at gmail.com
> <mailto:k.hara.pg at gmail.com>>:
>
> I think the main purpose of rvalue reference is:
> "Called function requires the address of given value, but not need to
> change its value semantics."
>
> We can never rewrite basic literals, therefore we can say that they
> have constant value semantics, even if their types are mutable. And
> then, it seems that rewriting literal through rvalue reference (==
> temporary variable) is counter-intuitive, and less useful.
> On the other hand, compound literals usually have mutable
> elements/fields, so called function may use and rewrite them. It is
> often useful.
>
> More details of my proposal with an actual code:
>
> struct S{}
>
> void foo(const ref int v){}
> void foo(const ref double v){}
> void foo(const ref cdouble v){}
> void foo(const ref int[] v){}
> void foo(const ref int[int] v){}
> void foo(const ref S v){}
> void bar( ref int v){}
> void bar( ref double v){}
> void bar( ref cdouble v){}
> void bar( ref int[] v){}
> void bar( ref int[int] v){}
> void bar( ref S v){}
>
> void hoo(T)(const ref T v){}
> void var(T)( ref T v){}
>
> void main()
> {
> // cannot bind basic literals to mutable ref
> enum int ei = 1024;
> foo(1024); static assert(!__traits(compiles, bar(1024)));
> hoo(1024); static assert(!__traits(compiles, var(1024)));
> foo(ei); static assert(!__traits(compiles, bar(ei)));
> hoo(ei); static assert(!__traits(compiles, var(ei)));
>
> enum double ef = 3.14;
> foo(3.14); static assert(!__traits(compiles, bar(3.14)));
> hoo(3.14); static assert(!__traits(compiles, var(3.14)));
> foo(ef); static assert(!__traits(compiles, bar(ef)));
> hoo(ef); static assert(!__traits(compiles, var(ef)));
>
> enum cdouble ec = 1+1i;
> /*foo(1+1i);*/static assert(!__traits(compiles, bar(1+1i)));
> /*hoo(1+1i);*/static assert(!__traits(compiles, var(1+1i)));
> foo(ec); static assert(!__traits(compiles, bar(ec)));
> hoo(ec); static assert(!__traits(compiles, var(ec)));
>
> // can bind compound literals to mutable ref
> enum int[] ea = [1,2];
> foo([1,2]); bar([1,2]);
> hoo([1,2]); var([1,2]);
> foo(ea); bar(ea);
> hoo(ea); var(ea);
>
> enum int[int] eaa = [1:1];
> foo([1:1]); bar([1:1]);
> hoo([1:1]); var([1:1]);
> foo(eaa); bar(eaa);
> hoo(eaa); var(eaa);
>
> enum S es = S();
> foo(S()); bar(S());
> hoo(S()); var(S());
> foo(es); bar(es);
> hoo(es); var(es);
> }
>
> Kenji Hara
>
> 2012年4月13日14:58 kenji hara <k.hara.pg at gmail.com
> <mailto:k.hara.pg at gmail.com>>:
> > I think to avoid some useless case, I'd like to add a rule.
> >
> > In basic, literals (e.g. 10, 3.14, "hello") in D are typed as
> mutable.
> > typeof(10) == int
> > typeof(3.14) == double
> > typeof("hello") == immutable(char)[] // array itself is mutable
> >
> > Then, with new rvalue reference mechanism, literals are assigned to
> > mutable temporaries, and be bound to ref.
> >
> > void foo(ref int n){}
> > foo(10);
> > // same as int tmp = 10; foo(tmp);
> >
> > But it is less useful behavior.
> >
> > I propose that if rvalue reference binding is needed, and the rvalue
> > is built-in literal, its type is treated as const.
> >
> > void foo(ref int n){}
> > foo(10);
> > // same as const(int) tmp = 10; foo(tmp);
> > // tmp is const, and binding const variable to mutable ref is
> illegal,
> > then raises an error.
> >
> > Finally, I don't know we should apply this rule to struct literal
> too.
> > It sounds good, but I afraid that is too restrict.
> >
> > Kenji Hara
> >
> > 2012年4月11日13:33 Andrei Alexandrescu <andrei at erdani.com
> <mailto:andrei at erdani.com>>:
> >> On 4/10/12 7:57 PM, Walter Bright wrote:
> >>>
> >>> 2.
> >>> double& d;
> >>> int i;
> >>> void foo() {
> >>> d = i;
> >>> }
> >>
> >>
> >> This example is off; a reference can't be rebound. The relevant
> example is:
> >>
> >> void increment(double& d)
> >> {
> >> ++d;
> >> }
> >> ...
> >> int i;
> >> increment(i);
> >>
> >> People think the int has been incremented, but in fact a useless
> temporary
> >> has.
> >>
> >> The discussion about what to do in D has been a bit longer and more
> >> far-reaching than Walter mentioned.
> >>
> >> The long-term plan is to never let the address of a ref escape the
> >> expression in which the ref occurs. That means in essence that
> user code
> >> can't take the address of a ref.
> >>
> >> Once that is in place, we will know for sure that all ref passed
> into and
> >> returned by functions will not escape the immediate expression
> in which that
> >> happens - great for safe code.
> >>
> >> People who need to take &this and escape it (e.g in linked lists
> implemented
> >> with struct) will not be able to; they'll have to use static
> functions and
> >> pointers for that. Generally any work that involves escaping
> pointers will
> >> have to use pointers, not references.
> >>
> >> I think this puts us in a very good spot:
> >>
> >> 1. Safe code will be able to use ref liberally
> >>
> >> 2. Functions will be able to return ref knowing the ref won't
> survive the
> >> current expression. This is awesome for sealed containers - safe
> and fast.
> >>
> >> What does this have to do with rvalues and lvalues? It means
> that with the
> >> appropriate precautions, we _can_ transform rvalues into
> lvalues, because we
> >> know their address can't unsafely escape.
> >>
> >> There is one precautions to take: we should never convert a
> value of type T
> >> to a ref of another type U. That would cause the problems we
> learned from
> >> C++. There are 3 cases of such implicit conversions:
> >>
> >> 1. built-in numerics, e.g. an int should not convert to a ref
> double.
> >>
> >> 2. Class inheritance, e.g. a Widget should not convert to a ref
> Object.
> >>
> >> 3. alias this, e.g.:
> >>
> >> struct T {}
> >> struct A { @property T fun(); alias fun this; }
> >> void fun(ref T);
> >> ...
> >> A a;
> >> fun(a); // should not work
> >>
> >>
> >> I think this all holds water. Destroy!
> >>
> >> Andrei
> >>
> >>
> >> _______________________________________________
> >> dmd-beta mailing list
> >> dmd-beta at puremagic.com <mailto:dmd-beta at puremagic.com>
> >> http://lists.puremagic.com/mailman/listinfo/dmd-beta
>
>
>
> _______________________________________________
> dmd-beta mailing list
> dmd-beta at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/dmd-beta
More information about the dmd-beta
mailing list