HaxeFoundation / haxe

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

Consider `toString` static extension in string coercion #11767

Open back2dos opened 2 months ago

back2dos commented 2 months ago

AFAF: https://try.haxe.org/#52ff1319

@:using(Test.MyEnumUtils)
enum A {
    VA;
    VB(isX:Bool);
}

abstract B(A) from A {
    @:to function toString() return this.toString();
}

class MyEnumUtils {
    public static function toString(v:A) return switch v {
        case VA: "this is va";
        case VB(false): "this is vb false";
        case VB(true): "this is vb true";
    };
}

class Test {
    static function main() {
        var m = VB(true);
        trace(m);// toString is not called
        trace('$m');// toString is not called
        trace(m.toString());// toString is called ... obviously
        var m:B = m;
        trace(m);// toString is called
        trace('$m');// toString is called
    }
}

In the trace('$m') case the compiler explicitly inserts a Std.string and to expect the toString to be used there if available seems quite reasonable. In the trace(m) case I'm not so sure what the behavior should be, but FWIW I think the best option would be to make it work the same as it works for abstracts.

Simn commented 2 months ago

Hmm, I thought trace(m) wasn't very strictly defined because we might want to utilize native tracing capabilities in that case. Abstracts seem a bit special in that regard because they have no run-time representation by their very nature, so toStringing them is fair enough. For normal types one could argue that String isn't involved at all.

I do agree that trace('$m') should call toString.