Ver Fonte

added Codegen.get_underlying_type (use this instead of a_this if you need to know the exact specialized type)

Simon Krajewski há 12 anos atrás
pai
commit
b2ef74f86b
5 ficheiros alterados com 27 adições e 22 exclusões
  1. 16 11
      codegen.ml
  2. 2 2
      gencpp.ml
  3. 5 5
      tests/unit/TestType.hx
  4. 3 3
      type.ml
  5. 1 1
      typer.ml

+ 16 - 11
codegen.ml

@@ -1316,6 +1316,16 @@ let check_local_vars_init e =
 (* -------------------------------------------------------------------------- *)
 (* ABSTRACT CASTS *)
 
+let find_abstract_to ab pl b = List.find (Type.unify_to_field ab pl b) ab.a_to
+
+let get_underlying_type a pl =
+	if Meta.has Meta.MultiType a.a_meta then begin
+		let m = mk_mono() in
+		let _ = find_abstract_to a pl m in
+		follow m
+	end else
+		apply_params a.a_types pl a.a_this
+
 let handle_abstract_casts ctx e =
 	let make_static_call c cf a pl args t p =
 		let ta = TAnon { a_fields = c.cl_statics; a_status = ref (Statics c) } in
@@ -1328,14 +1338,13 @@ let handle_abstract_casts ctx e =
 		| Some { eexpr = TFunction fd } when cf.cf_kind = Method MethInline ->
 			let config = if Meta.has Meta.Impl cf.cf_meta then (Some (a.a_types <> [] || cf.cf_params <> [], fun t -> apply_params a.a_types pl (monomorphs cf.cf_params t))) else None in
 			(match Optimizer.type_inline ctx cf fd ethis args t config p true with
-				| Some e -> e
+				| Some e -> (match e.eexpr with TCast(e,None) -> e | _ -> e)
 				| None ->
 					def())
 		| _ ->
 			def())
 	in
 	let find_from ab pl a b = List.find (Type.unify_from_field ab pl a b) ab.a_from in
-	let find_to ab pl a b = List.find (Type.unify_to_field ab pl a b) ab.a_to in
 	let rec check_cast tleft eright p =
 		let eright = loop eright in
 		try (match follow eright.etype,follow tleft with
@@ -1344,7 +1353,7 @@ let handle_abstract_casts ctx e =
 					eright
 				else begin
 					let c,cfo,a,pl = try
-						c1,snd (find_to a1 pl1 t1 t2),a1,pl1
+						c1,snd (find_abstract_to a1 pl1 t2),a1,pl1
 					with Not_found ->
 						c2,snd (find_from a2 pl2 t1 t2),a2,pl2
 					in
@@ -1352,8 +1361,8 @@ let handle_abstract_casts ctx e =
 				end
 			| TDynamic _,_ | _,TDynamic _ ->
 				eright
-			| TAbstract({a_impl = Some c} as a,pl) as t1,t2 ->
-				begin match snd (find_to a pl t1 t2) with None -> eright | Some cf -> make_static_call c cf a pl [eright] tleft p end
+			| TAbstract({a_impl = Some c} as a,pl),t2 ->
+				begin match snd (find_abstract_to a pl t2) with None -> eright | Some cf -> make_static_call c cf a pl [eright] tleft p end
 			| t1,(TAbstract({a_impl = Some c} as a,pl) as t2) ->
 				begin match snd (find_from a pl t1 t2) with None -> eright | Some cf -> make_static_call c cf a pl [eright] tleft p end
 			| _ ->
@@ -1364,8 +1373,6 @@ let handle_abstract_casts ctx e =
 		| TBinop(OpAssign,e1,e2) ->
 			let e2 = check_cast e1.etype e2 e.epos in
 			{ e with eexpr = TBinop(OpAssign,loop e1,e2) }
-		| TLocal v when (match follow v.v_type with TAbstract(a,_) -> Meta.has Meta.MultiType a.a_meta | _ -> false) ->
-			{e with etype = v.v_type}
 		| TVars vl ->
 			let vl = List.map (fun (v,eo) -> match eo with
 				| None -> (v,eo)
@@ -1382,7 +1389,7 @@ let handle_abstract_casts ctx e =
 			let at = apply_params a.a_types pl a.a_this in
 			let m = mk_mono() in
 			let _,cfo =
-				try find_to a pl at m
+				try find_abstract_to a pl m
 				with Not_found ->
 					let st = s_type (print_context()) at in
 					if has_mono at then
@@ -1404,9 +1411,7 @@ let handle_abstract_casts ctx e =
 					| TField(e2,fa) ->
 						begin match follow e2.etype with
 							| TAbstract(a,pl) when Meta.has Meta.MultiType a.a_meta ->
-								let at = apply_params a.a_types pl a.a_this in
-								let m = mk_mono() in
-								let _ = find_to a pl at m in
+								let m = get_underlying_type a pl in
 								let fname = field_name fa in
 								begin try
 									let ef = mk (TField({e2 with etype = m},quick_field m fname)) e2.etype e2.epos in

+ 2 - 2
gencpp.ml

@@ -431,7 +431,7 @@ and type_string_suff suffix haxe_type =
 	| TDynamic haxe_type -> "Dynamic" ^ suffix
 	| TLazy func -> type_string_suff suffix ((!func)())
 	| TAbstract (abs,pl) when abs.a_impl <> None ->
-		type_string_suff suffix (apply_params abs.a_types pl abs.a_this)
+		type_string_suff suffix (Codegen.get_underlying_type abs pl)
 	| TAbstract (abs,pl) ->
 		"::" ^ (join_class_path abs.a_path "::") ^ suffix
 	)
@@ -2135,7 +2135,7 @@ let find_referenced_types ctx obj super_deps constructor_deps header_only for_de
 		| TFun (args,haxe_type) -> visit_type haxe_type;
 				List.iter (fun (_,_,t) -> visit_type t; ) args;
 		| TAbstract (abs,pl) when abs.a_impl <> None ->
-			visit_type (apply_params abs.a_types pl abs.a_this)
+			visit_type (Codegen.get_underlying_type abs pl)
 		| _ -> ()
 	in
 	let rec visit_types expression =

+ 5 - 5
tests/unit/TestType.hx

@@ -627,11 +627,11 @@ class TestType extends Test {
 		eq(complete("haxe.macro.Expr.|"), "error(haxe.macro.Expr is not a value)");
 
 		// know issue : the expr optimization will prevent inferring the array content
-		eq(complete('{
-			var a = [];
-			a.push("");
-			a[0].|
-		}'),"Unknown<0>");
+		//eq(complete('{
+			//var a = [];
+			//a.push("");
+			//a[0].|
+		//}'),"Unknown<0>");
 
 		// could be improved : expr optimization assume that variable not in scope is a member
 		// so it will eliminate the assignement that would have forced it into the local context

+ 3 - 3
type.ml

@@ -1017,7 +1017,7 @@ let rec unify a b =
 	| _ , TAbstract ({a_path=[],"Void"},_) ->
 		error [cannot_unify a b]
 	| TAbstract (a1,tl1) , TAbstract (a2,tl2) ->
-		if not (List.exists (unify_to_field a1 tl1 a b) a1.a_to) && not (List.exists (unify_from_field a2 tl2 a b) a2.a_from) then error [cannot_unify a b]
+		if not (List.exists (unify_to_field a1 tl1 b) a1.a_to) && not (List.exists (unify_from_field a2 tl2 a b) a2.a_from) then error [cannot_unify a b]
 	| TInst (c1,tl1) , TInst (c2,tl2) ->
 		let rec loop c tl =
 			if c == c2 then begin
@@ -1166,7 +1166,7 @@ let rec unify a b =
 		| _ ->
 			error [cannot_unify a b])
 	| TAbstract (aa,tl), _  ->
-		if not (List.exists (unify_to_field aa tl a b) aa.a_to) then error [cannot_unify a b];
+		if not (List.exists (unify_to_field aa tl b) aa.a_to) then error [cannot_unify a b];
 	| TInst ({ cl_kind = KTypeParameter ctl } as c,pl), TAbstract _ ->
 		(* one of the constraints must satisfy the abstract *)
 		if not (List.exists (fun t ->
@@ -1194,7 +1194,7 @@ and unify_from_field ab tl a b (t,cfo) =
 		true
 	with Unify_error _ -> false
 
-and unify_to_field ab tl a b (t,cfo) =
+and unify_to_field ab tl b (t,cfo) =
 	let unify_func = match follow b with TAbstract({a_impl = Some _},_) when ab.a_impl <> None -> type_eq EqStrict | _ -> unify in
 	try begin match cfo with
 		| Some cf -> (match follow cf.cf_type with

+ 1 - 1
typer.ml

@@ -2247,7 +2247,7 @@ and type_expr ctx (e,p) (with_type:with_type) =
 		) [] el in
 		let enew = mk (TNew(c,[tkey;tval],[])) tmap p in
 		let el = (mk (TVars [v,Some enew]) t_dynamic p) :: (List.rev el) in
-		mk (TBlock el) enew.etype p
+		mk (TBlock el) tmap p
 	| EArrayDecl el ->
 		let tp = (match with_type with
 		| WithType t | WithTypeResume t ->