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

-D no-inline breaks map literals in HashLink #10912

Open
player-03 opened this issue Dec 30, 2022 · 3 comments
Open

-D no-inline breaks map literals in HashLink #10912

player-03 opened this issue Dec 30, 2022 · 3 comments
Milestone

Comments

@player-03
Copy link
Contributor

player-03 commented Dec 30, 2022

Edit: See my reply below for a minimal example.


I'm trying to build the Lime tools for HL, but it gives me an Invalid_argument("List.map2") error. Using OCAMLRUNPARAM=b I was able to track it down to genhl.ml line 519, but that's not very helpful.

I would absolutely love to give you a minimal example, but the error message isn't specific enough for me to narrow it down.

When I have more time, I think my plan is to insert a temporary try block in genhl.ml so I can get e.epos (which I would use to narrow the error down). But I have no Ocaml experience, so I was hoping someone else could tell me how to print that data. This is my best attempt at the code:

-				TFun (List.map2 (fun ((name,opt,t) as a) ((_,_,t2) as a2) ->
+				try TFun (List.map2 (fun ((name,opt,t) as a) ((_,_,t2) as a2) ->
					match t, t2 with
					(*
						Handle function variance:
						If we have type parameters which are function types, we need to keep the functions
						because we might need to insert a cast to coerce Void->Bool to Void->Dynamic for instance.
					*)
					| TInst ({cl_kind=KTypeParameter _},_), TFun _ -> a2
					(*
						If we have a number, it is more accurate to cast it to the type parameter before wrapping it as dynamic
						Ignore dynamic method (#7166)
					*)
					| TInst ({cl_kind=KTypeParameter _},_), t when is_number (to_type ctx t) && (match f with FInstance (_,_,{ cf_kind = Var _ | Method MethDynamic }) -> false | _ -> true) ->
						(name, opt, TAbstract (fake_tnull,[t]))
					| _ ->
-						a
+						a with
+				Invalid_argument -> print_endline e.epos; None
@Simn
Copy link
Member

Simn commented Dec 30, 2022

Yeah, OCaml has no "trace anything" functionality. You can try something like abort "Uhm" e.epos.

@player-03
Copy link
Contributor Author

Ok, the try ... with simply didn't work, but thanks to print_string() and print_int() I was able to narrow it down.

It turns out this is pretty easy to reproduce. Just compile the following for HashLink with -D no-inline:

class Main {
	public static function main():Void {
		var map:Map<String, String> = ["a" => "b"];
	}
}

(It's probably obvious, but e.epos will point to the characters ["a" => "b"].)

(I don't know why Lime would use no-inline, but that's what happened.)

@player-03 player-03 changed the title "Invalid_argument" error when rebuilding Lime for HL -D no-inline breaks map literals in HashLink Dec 31, 2022
@Apprentice-Alchemist
Copy link
Contributor

When map comprehension is used (with -D no-inline), this is passed to the generator: [Field:(String, String) -> Void] [TypeExpr haxe.ds._Map.Map_Impl_:Abstract<haxe.ds.Map>] [FStatic:(String, String) -> Void] haxe.ds._Map.Map_Impl_ set:(this : haxe.IMap<haxe.ds.Map.K, haxe.ds.Map.V>, key : haxe.ds.Map.K, value : haxe.ds.Map.V) -> Void
List.map2 is unhappy here because the type in the Field node is (String, String) -> Void, but field_type gives (this : haxe.IMap<haxe.ds.Map.K, haxe.ds.Map.V>, key : haxe.ds.Map.K, value : haxe.ds.Map.V) -> Void. One has 2 arguments, one has 3, therefore an exception is thrown.

When one builds the map manually, the types match, so this seems like bad codegen in whatever's responsible for desugaring map comprehension?

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