Search code examples
haxe

Why doesn't the Haxe compiler complain when returning a Dynamic (String) from a function with a generic (Int) return type?


I'm wondering why the following Haxe code compiles:

class Test<T> { // 1
    var l:List<Dynamic> = new List<Dynamic>(); // 2
    public function new() {} // 3
    public function add(d:Dynamic):Void { l.add(d); } // 4
    public function get():T { return l.pop(); }  // 5
    public static function main() { // 6
        var t:Test<Int> = new Test<Int>(); // 7
        t.add("-"); // 8
        trace(t.get());  // 9
    } // 10
}

The compilation problem I see:

As seen in line 1, this class has a type parameter T. In line 7, it is specified that T is an Int. So the get() function (line 5) should only return an Int. However - magically - this function returns a String (line 9).

So ... why doesn't the compiler complain about this?


Solution

  • A dynamic value can be assigned to anything; and anything can be assigned to it.

    According to the Haxe manual: https://haxe.org/manual/types-dynamic.html

    Since l is a List<Dynamic>, the result of l.pop() will also be Dynamic. This will be implicitly cast to Int when it is returned in get().

    I think the runtime behavior when tracing the value out at line 9 would depend on the Haxe target.

    If you change l into a List<T> and make add() take a parameter of type T, then the compiler would complain. Try this: https://try.haxe.org/#11327

    class Test<T> { // 1
        var l:List<T> = new List<T>(); // 2
        public function new() {} // 3
        public function add(d:T):Void { l.add(d); } // 4
        public function get():T { return l.pop(); }  // 5
        public static function main() { // 6
            var t:Test<Int> = new Test<Int>(); // 7
            t.add("-"); // 8 - this won't compile anymore
            trace(t.get());  // 9
        } // 10
    }