Explorar el Código

change fast_eq_anon into shallow_eq for broader checks
fixes #8704

Aleksandr Kuzmenko hace 6 años
padre
commit
e1f6f1292a

+ 39 - 41
src/core/type.ml

@@ -1793,47 +1793,45 @@ let rec fast_eq_mono ml a b =
 	| _ , _ ->
 		false
 
-let rec fast_eq_anon ?(mono_equals_dynamic=false) a b =
-	if fast_eq_check (fast_eq_anon ~mono_equals_dynamic) a b then
-		true
-	else match a , b with
-	(*
-		`mono_equals_dynamic` is here because of https://github.com/HaxeFoundation/haxe/issues/8588#issuecomment-520138371
-		Generally unbound monomorphs should not be considered equal to anything,
-		because it's unknown, which types they would be bound to.
-	*)
-	| t, TMono { contents = None } when t == t_dynamic -> mono_equals_dynamic
-	| TMono { contents = None }, t when t == t_dynamic -> mono_equals_dynamic
-	| TMono { contents = Some t1 }, TMono { contents = Some t2 } ->
-		fast_eq_anon t1 t2
-	| TAnon a1, TAnon a2 ->
-		let fields_eq() =
-			let rec loop fields1 fields2 =
-				match fields1, fields2 with
-				| [], [] -> true
-				| _, [] | [], _ -> false
-				| f1 :: rest1, f2 :: rest2 ->
-					f1.cf_name = f2.cf_name
-					&& (try fast_eq_anon f1.cf_type f2.cf_type with Not_found -> false)
-					&& loop rest1 rest2
-			in
-			let fields1 = PMap.fold (fun field fields -> field :: fields) a1.a_fields []
-			and fields2 = PMap.fold (fun field fields -> field :: fields) a2.a_fields []
-			and sort_compare f1 f2 = compare f1.cf_name f2.cf_name in
-			loop (List.sort sort_compare fields1) (List.sort sort_compare fields2)
-		in
-		(match !(a2.a_status), !(a1.a_status) with
-		| Statics c, Statics c2 -> c == c2
-		| EnumStatics e, EnumStatics e2 -> e == e2
-		| AbstractStatics a, AbstractStatics a2 -> a == a2
-		| Extend tl1, Extend tl2 -> fields_eq() && List.for_all2 fast_eq_anon tl1 tl2
-		| Closed, Closed -> fields_eq()
-		| Opened, Opened -> fields_eq()
-		| Const, Const -> fields_eq()
-		| _ -> false
-		)
-	| _ , _ ->
-		false
+let rec shallow_eq a b =
+	a == b
+	|| begin
+		let a = follow a
+		and b = follow b in
+		fast_eq_check shallow_eq a b
+		|| match a , b with
+			| t, TMono { contents = None } when t == t_dynamic -> true
+			| TMono { contents = None }, t when t == t_dynamic -> true
+			| TMono { contents = None }, TMono { contents = None } -> true
+			| TAnon a1, TAnon a2 ->
+				let fields_eq() =
+					let rec loop fields1 fields2 =
+						match fields1, fields2 with
+						| [], [] -> true
+						| _, [] | [], _ -> false
+						| f1 :: rest1, f2 :: rest2 ->
+							f1.cf_name = f2.cf_name
+							&& (try shallow_eq f1.cf_type f2.cf_type with Not_found -> false)
+							&& loop rest1 rest2
+					in
+					let fields1 = PMap.fold (fun field fields -> field :: fields) a1.a_fields []
+					and fields2 = PMap.fold (fun field fields -> field :: fields) a2.a_fields []
+					and sort_compare f1 f2 = compare f1.cf_name f2.cf_name in
+					loop (List.sort sort_compare fields1) (List.sort sort_compare fields2)
+				in
+				(match !(a2.a_status), !(a1.a_status) with
+				| Statics c, Statics c2 -> c == c2
+				| EnumStatics e, EnumStatics e2 -> e == e2
+				| AbstractStatics a, AbstractStatics a2 -> a == a2
+				| Extend tl1, Extend tl2 -> fields_eq() && List.for_all2 shallow_eq tl1 tl2
+				| Closed, Closed -> fields_eq()
+				| Opened, Opened -> fields_eq()
+				| Const, Const -> fields_eq()
+				| _ -> false
+				)
+			| _ , _ ->
+				false
+	end
 
 (* perform unification with subtyping.
    the first type is always the most down in the class hierarchy

+ 3 - 3
src/typing/typer.ml

@@ -110,7 +110,7 @@ let maybe_type_against_enum ctx f with_type iscall p =
 				| TAbstract (a,pl) when not (Meta.has Meta.CoreType a.a_meta) ->
 					begin match get_abstract_froms a pl with
 						| [t2] ->
-							if (List.exists (fast_eq_anon ~mono_equals_dynamic:true t) stack) then raise Exit;
+							if (List.exists (shallow_eq t) stack) then raise Exit;
 							loop (t :: stack) t2
 						| _ -> raise Exit
 					end
@@ -1623,7 +1623,7 @@ and type_object_decl ctx fl with_type p =
 			| TAnon a -> ODKWithStructure a
 			| TAbstract (a,pl) as t
 				when not (Meta.has Meta.CoreType a.a_meta)
-					&& not (List.exists (fun t' -> fast_eq_anon ~mono_equals_dynamic:true t t') seen) ->
+					&& not (List.exists (fun t' -> shallow_eq t t') seen) ->
 				let froms = get_abstract_froms a pl
 				and fold = fun acc t' -> match loop (t :: seen) t' with ODKPlain -> acc | t -> t :: acc in
 				(match List.fold_left fold [] froms with
@@ -2112,7 +2112,7 @@ and type_array_decl ctx el with_type p =
 					Some (get_iterable_param t)
 				with Not_found ->
 					None)
-			| TAbstract (a,pl) as t when not (List.exists (fun t' -> fast_eq_anon ~mono_equals_dynamic:true t (follow 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

+ 10 - 0
tests/misc/projects/Issue8704/Main.hx

@@ -0,0 +1,10 @@
+class Main {
+	public static function main() {
+		Under.from({});
+	}
+}
+
+abstract Under<T>(T) {
+	@:from public static function from<T>(v):Under<T>
+		return v;
+}

+ 1 - 0
tests/misc/projects/Issue8704/compile-fail.hxml

@@ -0,0 +1 @@
+-main Main

+ 2 - 0
tests/misc/projects/Issue8704/compile-fail.hxml.stderr

@@ -0,0 +1,2 @@
+Main.hx:3: characters 14-16 : { } should be Under<Unknown<0>>
+Main.hx:3: characters 14-16 : For function argument 'v'