Skip to content

Abstract enums created by macros not behaving correctly #3514

Closed
@bendmorris

Description

(Currently using Haxe 3.1.3)

I'm trying to create an abstract enum with values defined in a macro, and am getting some strange behavior.

Here's a simple example of a regular abstract enum:

@:enum
abstract MyEnum(String) from String to String
{
    var A = 'a';
    var B = 'b';
    var C = 'c';
}

class MyClass
{
    static function myFunc(arg:MyEnum):String
    {
        switch(arg)
        {
            case A: return "GOT AN A";
            case B: return "GOT A B";
            default: return ""+arg;
        }
    }
}

I can compile this and it works correctly; if I leave out the "default" case, I get an error for the missing pattern.

Now I try to replicate this using a macro:

import haxe.macro.Context;
import haxe.macro.Expr;

class TestMacro
{
    macro static public function build():Array<Field>
    {
        var fields = Context.getBuildFields();
        var macroFields = ['a', 'b', 'c'];
        for (f in macroFields)
        {
            fields.push({
                name: f.toUpperCase(),
                doc: null,
                meta: [],
                access: [AStatic, APublic],
                kind: FVar(macro : String, macro $v{f}),
                pos: Context.currentPos(),
            });
        }
        return fields;
    }
}

#if !macro @:build(TestMacro.build()) #end
@:enum
abstract MyEnum(String) from String to String
{
}

#if !macro
class MyClass
{
    static function myFunc(arg:MyEnum):String
    {
        switch(arg)
        {
            case A: return "GOT AN A";
            case B: return "GOT A B";
            default: return ""+arg;
        }
    }
}
#end

I can use MyEnum.A, MyEnum.B, and MyEnum.C with no problem. However, I generate PHP code from this and notice:

  • there's no warning from the compiler when missing cases in the switch

  • also, more seriously: the default case from the switch doesn't show up in the generated PHP!

    <?php
    
    class MyClass {
        public function __construct(){}
        static function myFunc($arg) {
            switch($arg) {
            case "a":{
                return "GOT AN A";
            }break;
            case "b":{
                return "GOT A B";
            }break;
            }
        }
        function __toString() { return 'MyClass'; }
    }
    

So if I have an enum of 20 values and a switch with two cases followed by a default case, the PHP switch will only check for two of those values, and with no default, will return "null" for everything else.

Is this a bug, or am I not constructing the enum correctly? Is what I want to do possible?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

platform-macroEverything related to Haxe macros

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions