http://d.puremagic.com/issues/show_bug.cgi?id=7355



--- Comment #12 from timon.g...@gmx.ch 2012-02-03 14:42:21 PST ---
(In reply to comment #11)
> (In reply to comment #10)
> > For example, this should type check:
> > 
> > immutable(int)[] arr = [2,3,4];
> > inout(const(int))[] foo(inout(int)[] x){
> >     return uniform(0,2) ? arr : x;
> > }
> > inout(int)[] id(inout(int)[] x){
> >     return x;
> > }
> > inout(int)[] bar(inout(int)[] x){
> >     inout(int)[] y = [1,2,3];
> >     inout(const(int))[] z = id(foo(y)); // inout const substitute for inout
> >     return z~x;
> > }
> 
> This typechecks even if we don't have inout(const) as an option:
> [snip.]
> 

My point was that it does not _if_ we have it as an option (and it has to be an
option if we want inout to be powerful enough to replace identical overloads on
const). Furthermore, foo cannot type check without inout(const) and provide the
same guarantees.

Maybe my example was not illustrative enough, second try:

immutable(int)[] arr = [2,3,4];
inout(const(int))[] foo(inout(int)[] x){
    return uniform(0,2) ? arr : x;
}
inout(int)[] id(inout(int)[] x){
    return x;
}
inout(const(int))[] bar(inout(int)[] x){
    inout(int)[] y = [1,2,3];
    return id(foo(y)); // !!!!
}
void main(){
    auto a = new int[10];
    auto b = bar(a);
    static assert(is(typeof(b)==const(int)[])); // !!!
    auto c = new immutable(int)[10];
    immutable(int)[] d = bar(c); // !!!
}

foo(y) => inout(const(int))[]
id(foo(y)) =>! inout(const(int))[]// has to use inout const as inout
substitute!

resolve inout to mutable or const:
return type inout(const(int))[] => const(int)[]

resolve inout to immutable:
return type inout(const(int))[] => immutable(int)[]



> Besides, you are assuming here that the lvalue side of the expression plays a
> role in determining the inout match.  It doesn't.  The return type is solely
> determined by the argument expressions.
> 

I don't see why you think I am.

> > There are indeed corner cases, for example:
> > 
> > void foo(immutable(int) x, float y){}
> > void foo(const(int) x, float y){}
> > void foo(int x, float y){}
> > 
> > void main(){foo(1,1);} // error, matches all three
> 
> This case has no relevance, there is no inout return value.  Who cares what
> inout resolves to?

Nobody. You claimed that the overload resolution rules are good enough to
uniquely determine what inout should resolve to in all cases, and I provided a
minimal counter-example. If you want something a little bit more concrete,
consider this:

immutable(int)[] foo(immutable(int)[] x, float f){return x;}
int[] foo(int[] x, float f){return x;}

void main(){foo([1,2,3],4);} // error

I am becoming quite confident that the overload resolution rules are the
culprit. A parameter type should be considered more specialized than another
one if it better matches the argument type. That would render the
disambiguation steps in my sketch unnecessary.

> 
> Not to be nit picky, but we should consider that any polysemous value type is
> not going to play a vital role in an inout function, since it's implicitly
> convertible to any modifier.  It's references or contained references which
> make a difference.

I was making a statement about the overload resolution rules. Those also apply
to reference types.

> 
> If it comes down to supporting this, choosing any inout match arbitrarily is
> good enough.

In this exact case, yes. In general, no.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------

Reply via email to