HaxeFoundation / haxe

Haxe - The Cross-Platform Toolkit
https://haxe.org
6.17k stars 654 forks source link

Unification change #4003

Open waneck opened 9 years ago

waneck commented 9 years ago

Strangely, while tackling #4001 , it seems that the following is invalid:

class Main 
{
    static function main() 
    {
        var x:cs.NativeArray<{}> = new cs.NativeArray<Dynamic>(1);
    }
}

This fails now with:

Main.hx:5: characters 2-60 : cs.NativeArray<Dynamic> should be cs.NativeArray<{ }>
Main.hx:5: characters 2-60 : Type parameters are invariant
Main.hx:5: characters 2-60 : Dynamic should be { }

Not that I'm advocating for <Dynamic> to be how it was. But this was a recent change, wasn't it? Is this intentional?

Simn commented 9 years ago

I'm not sure what you want from me here, type parameters have always been invariant and Dynamic is no exception there.

waneck commented 9 years ago

You're right. It has always been like that, my bad. But there's something weird going on with the typer. See the following case:

class Main
{
    static function main()
    {
            var vec = new haxe.ds.Vector<Dynamic>(10);
            var t:NotArray<{}> = test(vec.toData());
    }

        inline public static function test<T>(arr:cs.NativeArray<T>):NotArray<T>
        {
            return new NotArray(arr);
        }
}

class NotArray<T>
{
    public var arr:cs.NativeArray<T>;
    public function new(nv:cs.NativeArray<T>)
    {
        this.arr = nv;
    }
}

This when compiled with -D dump gives the following:

            [Var t(2503):NotArray<{ }>]
                [New:NotArray<{ }>]
                    NotArray<{ }>
                    [Cast:haxe.ds._Vector.VectorData<Dynamic>] [Cast:haxe.ds._Vector.VectorData<Dynamic>] [Local vec(2494):haxe.ds.Vector<Dynamic>]

As you can see, NativeArray<Dynamic> is used in an argument that was expected to be NativeArray<{}>. When trying to find which overload was used, the two types don't unify anymore so gencommon can't determine.

Interestingly, if we replace var t:NotArray<{}> = test(vec.toData()); with var t = new NotArray<{}>(vec.toData()), the error haxe.ds._Vector.VectorData<Dynamic> should be cs.NativeArray<{ }> pops up as expected

Simn commented 9 years ago

So this is about inlining, right?

Simn commented 9 years ago

This happens because Dynamic is never bound to a monomorph. test.T remains a monomorph throughout the inlining of test because the only unification happening is NativeArray<Unknown<0>> vs. NativeArray<Dynamic> (the function argument). This means you get NotArray<Unknown<0>> as a return type which is ultimately unified with the explicit NotArray<{}>.

Also I have no idea what to do about that.