HaxeFoundation / haxe

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

Multitype abstract from calling to #8739

Open Ilir-Liburn opened 5 years ago

Ilir-Liburn commented 5 years ago
interface IA<T> {}

@:multiType
abstract Above<T>(IA<T>) {
    public function new(v);
    @:from static inline function fromInt(v:Int) return (v:Above<Int>);
    @:from static inline function fromFloat(v:Float) return (v:Above<Float>);
    @:to static inline function toInt(t:IA<Int>, v) return {value:v, type:TInt};
    @:to static inline function toFloat(t:IA<Float>, v) return {value:v, type:TFloat};
}

        var a1 = new Above<Int>(0);
        a1 = 1;
        var a2 = new Above<Float>(0);

Shouldn't (v:Above\<Int>) at fromInt call toInt in above example? Instead, a1 = 1 makes a1 an object, casting 1 to object, being not inlined like a2

RealyUniqueName commented 5 years ago

Why would it call toInt()? Instead it should throw an error, because (intValue:Above<Int>) inside of fromInt() means a recursive cast. @Simn ?

Simn commented 5 years ago

Looks like it yeah... the more errors these multitype abstracts throw the better.

Ilir-Liburn commented 5 years ago

@RealyUniqueName, yes in the case of regular abstract, but multitype abstract is constructed from @:to, not @:from, right? That is why I proposed to unify them

abstract MyMap<K, V>(IMap<K, V>) {
    public function new();
    @:from inline function fromInt<K:Int>() this = new IntMap<V>();
    @:from inline function fromString<K:String>() this = new StringMap<V>();
    @:to function toIntMap():IntMap<V> return cast this;
    @:to function toStringMap():StringMap<V> return cast this;
    @:to function toInterface():IMap<K, V> return this;
} 

where

  1. non-static @:from is used for multitype abstract
  2. type parameter constraint is used at @:from for multitype abstract
  3. constructor without body is used to mark abstract as multitype

but @Simn have something other on his mind: "The abstract still has to know all of its specializations, and inline functions cause the abstract type to disappear."

RealyUniqueName commented 5 years ago

I still think that it shouldn't call toInt(). E.g. std Map doesn't invoke additional implicit casting inside of @:from functions.

Ilir-Liburn commented 5 years ago

Whatever you decide, it's fine with me. My goal is discussion of different aspects for abstract types because I think that's the most important and most powerful part of the Haxe for the end user like me. Until abstract type reaches its final design.

RealyUniqueName commented 5 years ago

Since @Simn already rejected that idea in #8743 let's focus on recursive implicit cast here. We need to change it to emit an error just like in normal abstracts.

Ilir-Liburn commented 5 years ago

Please note that fixing (v:Above\<Int>) will change nothing. I can do following

    @:from static inline function fromInt(v:Int) return cast {value:v, type:TInt};
    @:from static inline function fromFloat(v:Float) return null;

and result is

                a1 = ((object) (1) );
                a2 = ((object) (1.1) );

Multitype abstract is always casting argument, no matter what is returned.