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

[flash] Bitwise compound assignment with Map<Int, Int> and UInt inside of a switch statement causes Unbound variable and Compiler failure: Failed to locate variable declaration #11248

Closed
Oxdeception opened this issue Jun 8, 2023 · 5 comments
Assignees

Comments

@Oxdeception
Copy link

Minimal example:

class Main {
    public static inline var BIT_A:UInt = 1 << 15;
    public static inline var BIT_B:UInt = 1 << 18;
    public static inline var FLAG_1:Int = 0;

    static final flags:Map<Int, Int> = [0 => 1010];
    static function main() {
        switch Std.int(Math.random() * 2) {
            case 0: flags[FLAG_1] |= BIT_A;
            case 1: flags[FLAG_1] |= BIT_B;
        }
        trace(flags[FLAG_1]);
    }
}

Compiler output

Unbound variable, please report this
{
        v_id = 1045;
        v_name = `;
        v_type = Map<Int, Int>;
        v_capture = false;
        v_extra = None;
        v_meta = [];
        v_pos = src/Main.hx: 306-328;
}
Unbound variable, please report this
{
        v_id = 1057;
        v_name = `;
        v_type = Map<Int, Int>;
        v_capture = false;
        v_extra = None;
        v_meta = [];
        v_pos = src/Main.hx: 350-372;
}
src/Main.hx:7: lines 7-13 Compiler failure: Failed to locate variable declaration
src/Main.hx:7: lines 7-13 Please submit an issue at https://github.com/HaxeFoundation/haxe/issues/new
src/Main.hx:7: lines 7-13 Attach the expression example and the following information:
Haxe: 4.3.1; OS type: unix;
File "src/filters/renameVars.ml", line 336, characters 20-27
Called from RenameVars.run in file "src/filters/renameVars.ml", line 336, characters 2-27
Called from Stdlib__List.fold_left in file "list.ml", line 121, characters 24-34
Called from TUnification.rec_stack_loop in file "src/core/tUnification.ml", line 458, characters 10-15
Called from FiltersCommon.run_expression_filters.process_field in file "src/filters/filtersCommon.ml", line 75, characters 23-71
Called from Stdlib__List.iter in file "list.ml", line 110, characters 12-15
Called from FiltersCommon.run_expression_filters in file "src/filters/filtersCommon.ml", line 81, characters 2-46
Called from Stdlib__List.iter in file "list.ml", line 110, characters 12-15
Called from Filters.run in file "src/filters/filters.ml", line 1012, characters 1-96
Called from Compiler.filter in file "src/compiler/compiler.ml", line 298, characters 1-38
Called from Compiler.compile in file "src/compiler/compiler.ml", line 328, characters 2-17
Called from Compiler.compile_safe in file "src/compiler/compiler.ml", line 347, characters 1-5
Called from Compiler.compile_ctx.run in file "src/compiler/compiler.ml", line 434, characters 2-157
Called from Compiler.catch_completion_and_exit in file "src/compiler/compiler.ml", line 408, characters 2-9
Called from Compiler.HighLevel.entry.loop in file "src/compiler/compiler.ml", line 630, characters 5-43
Called from Compiler.HighLevel.entry in file "src/compiler/compiler.ml", line 640, characters 13-22
Called from Server.process in file "src/compiler/server.ml", line 979, characters 1-39
Called from Dune__exe__Haxe in file "src/compiler/haxe.ml", line 53, characters 0-56
File "src/core/globals.ml", line 156, characters 1-7: Assertion failed

Tested on all targets except C#, only occurs for the Flash target

@Simn Simn self-assigned this Jun 26, 2023
@Simn
Copy link
Member

Simn commented Jun 26, 2023

Reduced a bit:

class Main {
	public static var BIT_A:UInt = 1;
	public static var FLAG_1:Int = 0;

	static final flags = [0 => 1010];

	@:matchDebug
	static function main() {
		switch Std.int(Math.random()) {
			case 0:
				flags[FLAG_1] |= BIT_A;
		}
	}
}

The problem already shows up in the matcher output:

DECISION TREE BEGIN
 4  var `<1058> = {
        var x<1044> = Math.random();
        __int__(x<1044>);
    }
 3  switch (`<1058>)
        case 0(unguarded):
 0          var lhs<1051> = cast cast `<1046>.get(`<1045>)
 1          var rhs<1052> = Main.BIT_A
            {
                var `<1045> = Main.FLAG_1;
                var `<1046> = Main.flags;
                {
                        var v<1057> = rhs<1052> | lhs<1051>;
                        cast `<1046>.set(`<1045>, v<1057>);
                        v<1057>;
                };
            }
        default
 2          <fail>
DECISION TREE END

Note how 1045 and 1046 both appear before their definition. I struggle to reproduce this without the weird Map/UInt interaction, so I'm not sure yet where the problem actually comes from.

@Oxdeception
Copy link
Author

Possibly related

class Main {
    public static var BIT_A:UInt = 1;
    public static var FLAG_1:Int = 0;

    static final _flags:Map<Int, Int> = [0 => 1010];
    public static var flags(get, never):Map<Int, Int>;

    public static function get_flags() {
        return _flags;
    }

    static function main() {
        flags[FLAG_1] ^= BIT_A;
    }
}
src/Main.hx:12: lines 12-14 Compiler failure: Failed to locate variable declaration
src/Main.hx:12: lines 12-14 Please submit an issue at https://github.com/HaxeFoundation/haxe/issues/new
src/Main.hx:12: lines 12-14 Attach the expression example and the following information:
Haxe: 4.3.1; OS type: unix;
File "src/filters/renameVars.ml", line 336, characters 20-27
Called from RenameVars.run in file "src/filters/renameVars.ml", line 336, characters 2-27
Called from Stdlib__List.fold_left in file "list.ml", line 121, characters 24-34
Called from TUnification.rec_stack_loop in file "src/core/tUnification.ml", line 458, characters 10-15
Called from FiltersCommon.run_expression_filters.process_field in file "src/filters/filtersCommon.ml", line 75, characters 23-71
Called from Stdlib__List.iter in file "list.ml", line 110, characters 12-15
Called from FiltersCommon.run_expression_filters in file "src/filters/filtersCommon.ml", line 81, characters 2-46
Called from Stdlib__List.iter in file "list.ml", line 110, characters 12-15
Called from Filters.run in file "src/filters/filters.ml", line 1012, characters 1-96
Called from Compiler.filter in file "src/compiler/compiler.ml", line 298, characters 1-38
Called from Compiler.compile in file "src/compiler/compiler.ml", line 328, characters 2-17
Called from Compiler.compile_safe in file "src/compiler/compiler.ml", line 347, characters 1-5
Called from Compiler.compile_ctx.run in file "src/compiler/compiler.ml", line 434, characters 2-157
Called from Compiler.catch_completion_and_exit in file "src/compiler/compiler.ml", line 408, characters 2-9
Called from Compiler.HighLevel.entry.loop in file "src/compiler/compiler.ml", line 630, characters 5-43
Called from Compiler.HighLevel.entry in file "src/compiler/compiler.ml", line 640, characters 13-22
Called from Server.process in file "src/compiler/server.ml", line 979, characters 1-39
Called from Dune__exe__Haxe in file "src/compiler/haxe.ml", line 53, characters 0-56
File "src/core/globals.ml", line 156, characters 1-7: Assertion failed

@Simn
Copy link
Member

Simn commented Jun 27, 2023

I've isolated that example:

abstract NotIntMap(String) {
	@:arrayAccess public function get(key:Int)
		return 1;

	@:arrayAccess public function arrayWrite(k:Int, v:Int):Int {
		return 1;
	}
}

@:coreType
abstract NotUInt to Int from Int {
	@:commutative @:op(A ^ B) private static function xorI(lhs:NotUInt, rhs:Int):NotUInt;
}

class Main {
	public static var BIT_A:NotUInt = 1;

	static final _flags:NotIntMap = null;
	public static var flags(get, never):NotIntMap;

	public static function get_flags() {
		return _flags;
	}

	@:analyzer(full_debug)
	static function main() {
		flags[0] ^= BIT_A;
	}
}

The analyzer receives a use-before-def thing again:

function() {
        var lhs<6520> = _Main.NotIntMap_Impl_.get(`<6519>, 0);
        var rhs<6521> = Main.BIT_A;
        {
                var `<6519> = Main.get_flags();
                _Main.NotIntMap_Impl_.arrayWrite(`<6519>, 0, rhs<6521> ^ lhs<6520>);
        };
}

Looks like some ordering issue in the operator handling code.

@Simn Simn closed this as completed in 83b6412 Jun 27, 2023
@kLabz
Copy link
Contributor

kLabz commented Jun 27, 2023

@Simn should this be added to 4.3_bugfix? (maybe I should release a 4.3.x soon btw..)

@Simn
Copy link
Member

Simn commented Jun 27, 2023

Did this fail on 4.2 already? If not then yes, otherwise no.

kLabz pushed a commit to kLabz/haxe that referenced this issue Jul 10, 2023
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

3 participants