Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with inline + multi multitype #6412

Open
MSGhero opened this issue Jun 28, 2017 · 1 comment
Open

Issue with inline + multi multitype #6412

MSGhero opened this issue Jun 28, 2017 · 1 comment
Assignees
Milestone

Comments

@MSGhero
Copy link

MSGhero commented Jun 28, 2017

A multityped abstract over a multityped abstract over an interface provides unexpected behavior if the outermost abstract has inlined @:to converters. inline or not in the inner abstract"s @:to does not appear to matter.

Explanation of code: new A<Int>() should result in a C being created, tracing out "C". new A<String>() should result in D and "D". Because the string path"s @:to is inlined, it seems like a B is being created and used instead of a D even though B is abstract.

Note: if A,B,C,D have a parameter in their constructors, new A<String>("param") will cause a runtime error for too many arguments. However, deleting the argument leads to a compile time error for not enough arguments, which is expected.

class Test {
    static function main() {
        // should trace "C"
        trace(new A<Int>()); // "C"
        // should trace "D"
        trace(new A<String>()); // "[object B_Impl_]", issues with double inlined @:to
    }
}

@:multiType(T)
@:forward
abstract A<T>(B<T>) {
    public function new();
    @:to static function aToC<T:Int>(b:B<T>):B<Int> { return new B<Int>(); }
    @:to static inline function aToD<T:String>(b:B<T>):B<String> { return new B<String>(); }
}

@:multiType(T)
@:forward
abstract B<T>(I<T>) {
    public function new();
    @:to static function bToC<T:Int>(c:I<T>):C { return new C(); }
    @:to static function bToD<T:String>(d:I<T>):D { return new D(); }
}

class C implements I<Int> {
    public function new() { }
    public function toString():String { return "C"; }
}

class D implements I<String> {
    public function new() { }
    public function toString():String { return "D"; }
}

interface I<T> {
    function toString():String;
}

(sorry if there"s a more minimal example)

Relevant js output:

Test.main = function() {
	console.log(_$Test_A_$Impl_$.aToC(null));
	console.log(new _$Test_B_$Impl_$());
};
var _$Test_A_$Impl_$ = {};
_$Test_A_$Impl_$.aToC = function(b) {
	return _$Test_B_$Impl_$.bToC(null);
};
_$Test_A_$Impl_$.aToD = function(b) {
	return _$Test_B_$Impl_$.bToD(null);
};
var _$Test_B_$Impl_$ = {};
_$Test_B_$Impl_$.bToC = function(c) {
	return new C();
};
_$Test_B_$Impl_$.bToD = function(d) {
	return new D();
};

Haxe 3.4.2 master and latest dev if I installed it properly

@Simn
Copy link
Member

Simn commented Jun 28, 2017

Inlining + @:multiType is such a big problem even for our Map implementation. I"m considering getting rid of @:multiType entirely in favor of something more robust, but I have yet to come up with something that"s actually more robust.

@Simn Simn self-assigned this Jun 28, 2017
@Simn Simn added this to the Design milestone Apr 17, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants