Ver Fonte

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

closes #11535
Simon Krajewski há 1 ano atrás
pai
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)
 					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) ->
 				| 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
 					begin match TyperBase.get_abstract_froms ctx a tl with
-						| [t2] -> pattern (t :: seen) t2
+						| [(_,t2)] -> pattern (t :: seen) t2
 						| _ -> fail()
 						| _ -> fail()
 					end
 					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
 					false,a.a_path,fields,TAbstractDecl a
 				| TAbstract (a,pl) when not (Meta.has Meta.CoreType a.a_meta) ->
 				| TAbstract (a,pl) when not (Meta.has Meta.CoreType a.a_meta) ->
 					begin match get_abstract_froms ctx a pl with
 					begin match get_abstract_froms ctx a pl with
-						| [t2] ->
+						| [(_,t2)] ->
 							if (List.exists (shallow_eq t) stack) then raise Exit;
 							if (List.exists (shallow_eq t) stack) then raise Exit;
 							loop (t :: stack) t2
 							loop (t :: stack) t2
 						| _ -> raise Exit
 						| _ -> raise Exit
@@ -782,14 +782,15 @@ and type_object_decl ctx fl with_type p =
 	let dynamic_parameter = ref None in
 	let dynamic_parameter = ref None in
 	let a = (match with_type with
 	let a = (match with_type with
 	| WithType.WithType(t,_) ->
 	| WithType.WithType(t,_) ->
-		let rec loop seen t =
+		let rec loop had_cast seen t =
 			match follow t with
 			match follow t with
-			| TAnon a -> ODKWithStructure a
+			| TAnon a ->
+				ODKWithStructure a
 			| TAbstract (a,pl) as t
 			| TAbstract (a,pl) as t
 				when not (Meta.has Meta.CoreType a.a_meta)
 				when not (Meta.has Meta.CoreType a.a_meta)
 					&& not (List.exists (fun t' -> shallow_eq t t') seen) ->
 					&& not (List.exists (fun t' -> shallow_eq t t') seen) ->
 				let froms = get_abstract_froms ctx a pl in
 				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
 				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) *)
 					| [] -> ODKPlain (* If the abstract has no casts in the first place, we can assume plain typing (issue #10730) *)
 					| [t] -> t
 					| [t] -> t
@@ -801,12 +802,12 @@ and type_object_decl ctx fl with_type p =
 					a_status = ref Closed;
 					a_status = ref Closed;
 					a_fields = PMap.empty;
 					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)
 				ODKWithClass(c,tl)
 			| _ ->
 			| _ ->
 				ODKPlain
 				ODKPlain
 		in
 		in
-		loop [] t
+		loop false [] t
 	| _ ->
 	| _ ->
 		ODKPlain
 		ODKPlain
 	) in
 	) in
@@ -1296,14 +1297,14 @@ and type_local_function ctx kind f with_type p =
 				maybe_unify_ret tr
 				maybe_unify_ret tr
 			| TAbstract(a,tl) ->
 			| TAbstract(a,tl) ->
 				begin match get_abstract_froms ctx a tl with
 				begin match get_abstract_froms ctx a tl with
-					| [t2] ->
+					| [(_,t2)] ->
 						if not (List.exists (shallow_eq t) stack) then loop (t :: stack) t2
 						if not (List.exists (shallow_eq t) stack) then loop (t :: stack) t2
 					| l ->
 					| l ->
 						(* For cases like nested EitherType, we want a flat list of all possible candidates.
 						(* 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,
 						   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). *)
 						   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
 						let rec loop stack acc l = match l with
-							| t :: l ->
+							| (_,t) :: l ->
 								begin match follow t with
 								begin match follow t with
 								| TAbstract(a,tl) as t when not (List.exists (shallow_eq t) stack) ->
 								| TAbstract(a,tl) as t when not (List.exists (shallow_eq t) stack) ->
 									loop (t :: stack) acc (l @ get_abstract_froms ctx a tl)
 									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 ->
 				with Not_found ->
 					None)
 					None)
 			| TAbstract (a,pl) as t when not (List.exists (fun t' -> shallow_eq t t') seen) ->
 			| 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
 				(match types with
 				| [t] -> Some t
 				| [t] -> Some t
 				| _ -> None)
 				| _ -> None)

+ 6 - 2
src/typing/typerBase.ml

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