Selaa lähdekoodia

[typer] don't consider @:structInit + @:from when inferring

closes #11535
Simon Krajewski 1 vuosi sitten
vanhempi
commit
c55da75267

+ 1 - 1
src/typing/matcher/exprToPattern.ml

@@ -315,7 +315,7 @@ let rec make pctx toplevel t e =
 					PatConstructor(con_array (List.length patterns) (pos e),patterns)
 				| TAbstract(a,tl) as t when not (List.exists (fun t' -> shallow_eq t t') seen) ->
 					begin match TyperBase.get_abstract_froms ctx a tl with
-						| [t2] -> pattern (t :: seen) t2
+						| [(_,t2)] -> pattern (t :: seen) t2
 						| _ -> fail()
 					end
 				| _ ->

+ 13 - 17
src/typing/typer.ml

@@ -96,7 +96,7 @@ let maybe_type_against_enum ctx f with_type iscall p =
 					false,a.a_path,fields,TAbstractDecl a
 				| TAbstract (a,pl) when not (Meta.has Meta.CoreType a.a_meta) ->
 					begin match get_abstract_froms ctx a pl with
-						| [t2] ->
+						| [(_,t2)] ->
 							if (List.exists (shallow_eq t) stack) then raise Exit;
 							loop (t :: stack) t2
 						| _ -> raise Exit
@@ -782,14 +782,15 @@ and type_object_decl ctx fl with_type p =
 	let dynamic_parameter = ref None in
 	let a = (match with_type with
 	| WithType.WithType(t,_) ->
-		let rec loop seen t =
+		let rec loop had_cast seen t =
 			match follow t with
-			| TAnon a -> ODKWithStructure a
+			| TAnon a ->
+				ODKWithStructure a
 			| TAbstract (a,pl) as t
 				when not (Meta.has Meta.CoreType a.a_meta)
 					&& not (List.exists (fun t' -> shallow_eq t t') seen) ->
 				let froms = get_abstract_froms ctx a pl in
-				let fold = fun acc t' -> match loop (t :: seen) t' with ODKPlain -> acc | t -> t :: acc in
+				let fold = fun acc (fk,t') -> match loop (fk = FromField) (t :: seen) t' with ODKPlain -> acc | t -> t :: acc in
 				begin match List.fold_left fold [] froms with
 					| [] -> ODKPlain (* If the abstract has no casts in the first place, we can assume plain typing (issue #10730) *)
 					| [t] -> t
@@ -801,12 +802,12 @@ and type_object_decl ctx fl with_type p =
 					a_status = ref Closed;
 					a_fields = PMap.empty;
 				}
-			| TInst(c,tl) when Meta.has Meta.StructInit c.cl_meta ->
+			| TInst(c,tl) when not had_cast && Meta.has Meta.StructInit c.cl_meta ->
 				ODKWithClass(c,tl)
 			| _ ->
 				ODKPlain
 		in
-		loop [] t
+		loop false [] t
 	| _ ->
 		ODKPlain
 	) in
@@ -1296,14 +1297,14 @@ and type_local_function ctx kind f with_type p =
 				maybe_unify_ret tr
 			| TAbstract(a,tl) ->
 				begin match get_abstract_froms ctx a tl with
-					| [t2] ->
+					| [(_,t2)] ->
 						if not (List.exists (shallow_eq t) stack) then loop (t :: stack) t2
 					| l ->
 						(* For cases like nested EitherType, we want a flat list of all possible candidates.
 						   This might be controversial because those could be considered transitive casts,
 						   but it's unclear if that's a bad thing for this kind of inference (issue #10982). *)
 						let rec loop stack acc l = match l with
-							| t :: l ->
+							| (_,t) :: l ->
 								begin match follow t with
 								| TAbstract(a,tl) as t when not (List.exists (shallow_eq t) stack) ->
 									loop (t :: stack) acc (l @ get_abstract_froms ctx a tl)
@@ -1398,15 +1399,10 @@ and type_array_decl ctx el with_type p =
 				with Not_found ->
 					None)
 			| TAbstract (a,pl) as t when not (List.exists (fun t' -> shallow_eq t t') seen) ->
-				let types =
-					List.fold_left
-						(fun acc t' -> match loop (t :: seen) t' with
-							| None -> acc
-							| Some t -> t :: acc
-						)
-						[]
-						(get_abstract_froms ctx a pl)
-				in
+				let types = List.fold_left (fun acc (_,t') -> match loop (t :: seen) t' with
+					| None -> acc
+					| Some t -> t :: acc
+				) [] (get_abstract_froms ctx a pl) in
 				(match types with
 				| [t] -> Some t
 				| _ -> None)

+ 6 - 2
src/typing/typerBase.ml

@@ -330,8 +330,12 @@ let unify_static_extension ctx e t p =
 		e
 	end
 
+type from_kind =
+	| FromType
+	| FromField
+
 let get_abstract_froms ctx a pl =
-	let l = List.map (apply_params a.a_params pl) a.a_from in
+	let l = List.map (fun t -> FromType,apply_params a.a_params pl t) a.a_from in
 	List.fold_left (fun acc (t,f) ->
 		(* We never want to use the @:from we're currently in because that's recursive (see #10604) *)
 		if f == ctx.f.curfield then
@@ -342,7 +346,7 @@ let get_abstract_froms ctx a pl =
 		| TFun ([_,_,v],t) ->
 			(try
 				ignore(type_eq EqStrict t (TAbstract(a,List.map duplicate pl))); (* unify fields monomorphs *)
-				v :: acc
+				(FromField,v) :: acc
 			with Unify_error _ ->
 				acc)
 		| _ ->

+ 34 - 0
tests/unit/src/unit/issues/Issue11535.hx

@@ -0,0 +1,34 @@
+package unit.issues;
+
+@:structInit
+private class BarImpl {
+	public function new() {}
+}
+
+@:structInit
+private class FooImpl {
+	public var x:Int;
+
+	public function new(x:Int) {
+		this.x = x;
+	}
+}
+
+@:forward
+private abstract Foo(FooImpl) from FooImpl to FooImpl {
+	public function new(x:Int) {
+		this = new FooImpl(x);
+	}
+
+	@:from
+	static public function fromVec4(v:BarImpl):Foo {
+		return new Foo(1);
+	}
+}
+
+class Issue11535 extends Test {
+	function test() {
+		var v:Foo = {x: 2};
+		eq(2, v.x);
+	}
+}