Browse Source

mark current field with `@:has_untyped` and ignore it in the analyzer (closes #3845)

Simon Krajewski 10 years ago
parent
commit
f744218240
5 changed files with 42 additions and 3 deletions
  1. 26 3
      analyzer.ml
  2. 1 0
      ast.ml
  3. 1 0
      common.ml
  4. 13 0
      tests/unit/src/unit/issues/Issue3845.hx
  5. 1 0
      typer.ml

+ 26 - 3
analyzer.ml

@@ -27,7 +27,7 @@ let has_analyzer_option meta s =
 			| (Meta.Analyzer,el,_) :: ml ->
 				if List.exists (fun (e,p) ->
 					match e with
-						| EConst(Ident s2) when s = s2 -> true
+						| EConst(Ident s2) when flag_ignore = s2 -> true
 						| _ -> false
 				) el then
 					true
@@ -42,6 +42,29 @@ let has_analyzer_option meta s =
 	with Not_found ->
 		false
 
+let is_ignored meta =
+	try
+		let rec loop ml = match ml with
+			| (Meta.Analyzer,el,_) :: ml ->
+				if List.exists (fun (e,p) ->
+					match e with
+						| EConst(Ident s2) when "ignore" = s2 -> true
+						| _ -> false
+				) el then
+					true
+				else
+					loop ml
+			| (Meta.HasUntyped,_,_) :: _ ->
+				true
+			| _ :: ml ->
+				loop ml
+			| [] ->
+				false
+		in
+		loop meta
+	with Not_found ->
+		false
+
 let rec get_type_meta t = match t with
 	| TMono r ->
 		begin match !r with
@@ -1433,7 +1456,7 @@ module Run = struct
 
 	let run_on_field ctx config cf =
 		match cf.cf_expr with
-		| Some e when not (has_analyzer_option cf.cf_meta flag_ignore) && not (Codegen.is_removable_field ctx cf) ->
+		| Some e when not (is_ignored cf.cf_meta) && not (Codegen.is_removable_field ctx cf) ->
 			let config = update_config_from_meta config cf.cf_meta in
 			let is_var_expression = match cf.cf_kind with
 				| Var _ -> true
@@ -1458,7 +1481,7 @@ module Run = struct
 
 	let run_on_type ctx config t =
 		match t with
-		| TClassDecl c when (has_analyzer_option c.cl_meta flag_ignore) -> ()
+		| TClassDecl c when (is_ignored c.cl_meta) -> ()
 		| TClassDecl c -> run_on_class ctx config c
 		| TEnumDecl _ -> ()
 		| TTypeDecl _ -> ()

+ 1 - 0
ast.ml

@@ -80,6 +80,7 @@ module Meta = struct
 		| GenericInstance
 		| Getter
 		| Hack
+		| HasUntyped
 		| HaxeGeneric
 		| HeaderClassCode
 		| HeaderCode

+ 1 - 0
common.ml

@@ -400,6 +400,7 @@ module MetaInfo = struct
 		| GenericInstance -> ":genericInstance",("Internally used to mark instances of @:generic methods",[UsedOn TClassField;Internal])
 		| Getter -> ":getter",("Generates a native getter function on the given field",[HasParam "Class field name";UsedOn TClassField;Platform Flash])
 		| Hack -> ":hack",("Allows extending classes marked as @:final",[UsedOn TClass])
+		| HasUntyped -> (":has_untyped",("Used by the typer to mark fields that have untyped expressions",[Internal]))
 		| HaxeGeneric -> ":haxeGeneric",("Used internally to annotate non-native generic classes",[Platform Cs; UsedOnEither[TClass;TEnum]; Internal])
 		| HeaderClassCode -> ":headerClassCode",("",[Platform Cpp])
 		| HeaderCode -> ":headerCode",("",[Platform Cpp])

+ 13 - 0
tests/unit/src/unit/issues/Issue3845.hx

@@ -0,0 +1,13 @@
+package unit.issues;
+
+class Issue3845 extends Test {
+	function test() {
+		var o = {};
+
+		var m = new haxe.ds.ObjectMap();
+		m.set(o, 1);
+		m.set(o, 2);
+
+		eq(2, m.get(o));
+	}
+}

+ 1 - 0
typer.ml

@@ -3434,6 +3434,7 @@ and type_expr ctx (e,p) (with_type:with_type) =
 	| EUntyped e ->
 		let old = ctx.untyped in
 		ctx.untyped <- true;
+		if not (Meta.has Meta.HasUntyped ctx.curfield.cf_meta) then ctx.curfield.cf_meta <- (Meta.HasUntyped,[],p) :: ctx.curfield.cf_meta;
 		let e = type_expr ctx e with_type in
 		ctx.untyped <- old;
 		{