瀏覽代碼

[typer] rework unify_anons

Simon Krajewski 1 年之前
父節點
當前提交
58e9e5245b
共有 1 個文件被更改,包括 64 次插入37 次删除
  1. 64 37
      src/core/tUnification.ml

+ 64 - 37
src/core/tUnification.ml

@@ -338,6 +338,13 @@ let fast_eq_check type_param_check a b =
 		c1 == c2 && List.for_all2 type_param_check l1 l2
 		c1 == c2 && List.for_all2 type_param_check l1 l2
 	| TAbstract (a1,l1), TAbstract (a2,l2) ->
 	| TAbstract (a1,l1), TAbstract (a2,l2) ->
 		a1 == a2 && List.for_all2 type_param_check l1 l2
 		a1 == a2 && List.for_all2 type_param_check l1 l2
+	| TAnon an1,TAnon an2 ->
+		begin match !(an1.a_status),!(an2.a_status) with
+			| ClassStatics c, ClassStatics c2 -> c == c2
+			| EnumStatics e, EnumStatics e2 -> e == e2
+			| AbstractStatics a, AbstractStatics a2 -> a == a2
+			| _ -> false
+		end
 	| _ , _ ->
 	| _ , _ ->
 		false
 		false
 
 
@@ -386,9 +393,6 @@ let rec shallow_eq a b =
 					loop (List.sort sort_compare fields1) (List.sort sort_compare fields2)
 					loop (List.sort sort_compare fields1) (List.sort sort_compare fields2)
 				in
 				in
 				(match !(a2.a_status), !(a1.a_status) with
 				(match !(a2.a_status), !(a1.a_status) with
-				| ClassStatics c, ClassStatics 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
 				| Extend tl1, Extend tl2 -> fields_eq() && List.for_all2 shallow_eq tl1 tl2
 				| Closed, Closed -> fields_eq()
 				| Closed, Closed -> fields_eq()
 				| Const, Const -> fields_eq()
 				| Const, Const -> fields_eq()
@@ -565,6 +569,10 @@ let rec type_eq uctx a b =
 			| AbstractStatics a -> (match !(a1.a_status) with AbstractStatics a2 when a == a2 -> () | _ -> error [])
 			| AbstractStatics a -> (match !(a1.a_status) with AbstractStatics a2 when a == a2 -> () | _ -> error [])
 			| _ -> ()
 			| _ -> ()
 			);
 			);
+			let fields = match !(a1.a_status) with
+				| ClassStatics c -> c.cl_statics
+				| _ -> a1.a_fields
+			in
 			PMap.iter (fun n f1 ->
 			PMap.iter (fun n f1 ->
 				try
 				try
 					let f2 = PMap.find n a2.a_fields in
 					let f2 = PMap.find n a2.a_fields in
@@ -575,9 +583,9 @@ let rec type_eq uctx a b =
 				with
 				with
 					Not_found ->
 					Not_found ->
 						error [has_no_field b n];
 						error [has_no_field b n];
-			) a1.a_fields;
+			) fields;
 			PMap.iter (fun n f2 ->
 			PMap.iter (fun n f2 ->
-				if not (PMap.mem n a1.a_fields) then begin
+				if not (PMap.mem n fields) then begin
 					error [has_no_field a n];
 					error [has_no_field a n];
 				end;
 				end;
 			) a2.a_fields;
 			) a2.a_fields;
@@ -897,39 +905,58 @@ let rec unify (uctx : unification_context) a b =
 		error [cannot_unify a b]
 		error [cannot_unify a b]
 
 
 and unify_anons uctx a b a1 a2 =
 and unify_anons uctx a b a1 a2 =
-	(try
-		PMap.iter (fun n f2 ->
+	let unify_field a1_fields f2 =
+		let n = f2.cf_name in
+		let f1 = PMap.find n a1_fields in
+		if not (unify_kind f1.cf_kind f2.cf_kind) then
+			error [invalid_kind n f1.cf_kind f2.cf_kind];
+		if (has_class_field_flag f2 CfPublic) && not (has_class_field_flag f1 CfPublic) then
+			error [invalid_visibility n];
 		try
 		try
-			let f1 = PMap.find n a1.a_fields in
-			if not (unify_kind f1.cf_kind f2.cf_kind) then
-				error [invalid_kind n f1.cf_kind f2.cf_kind];
-			if (has_class_field_flag f2 CfPublic) && not (has_class_field_flag f1 CfPublic) then error [invalid_visibility n];
-			try
-				let f1_type =
-					if fast_eq f1.cf_type f2.cf_type then f1.cf_type
-					else field_type f1
-				in
-				unify_with_access uctx f1 f1_type f2;
-				(match !(a1.a_status) with
-				| ClassStatics c when not (Meta.has Meta.MaybeUsed f1.cf_meta) -> f1.cf_meta <- (Meta.MaybeUsed,[],f1.cf_pos) :: f1.cf_meta
-				| _ -> ());
-			with
-				Unify_error l -> error (invalid_field n :: l)
-		with
-			Not_found ->
-				match !(a1.a_status) with
-				| Const when Meta.has Meta.Optional f2.cf_meta ->
-					a1.a_fields <- PMap.add f2.cf_name f2 a1.a_fields
-				| _ ->
-					error [has_no_field a n];
-		) a2.a_fields;
-		(match !(a2.a_status) with
-		| ClassStatics c -> (match !(a1.a_status) with ClassStatics c2 when c == c2 -> () | _ -> error [])
-		| EnumStatics e -> (match !(a1.a_status) with EnumStatics e2 when e == e2 -> () | _ -> error [])
-		| AbstractStatics a -> (match !(a1.a_status) with AbstractStatics a2 when a == a2 -> () | _ -> error [])
-		| Const | Extend _ | Closed -> ())
-	with
-		Unify_error l -> error (cannot_unify a b :: l))
+			let f1_type =
+				if fast_eq f1.cf_type f2.cf_type then f1.cf_type
+				else field_type f1
+			in
+			unify_with_access uctx f1 f1_type f2;
+			f1
+		with Unify_error l ->
+				error (invalid_field n :: l)
+	in
+	let unify_fields a1_fields f_good f_bad =
+		try
+			PMap.iter (fun _ f2 ->
+				try
+					f_good (unify_field a1_fields f2)
+				with Not_found ->
+					if not (f_bad f2) then
+						error [has_no_field a f2.cf_name]
+			) a2.a_fields
+		with Unify_error l ->
+			error (cannot_unify a b :: l)
+	in
+	begin match !(a1.a_status),!(a2.a_status) with
+		| ClassStatics c1,ClassStatics c2 when c1 == c2 ->
+			()
+		| EnumStatics en1,EnumStatics en2 when en1 == en2 ->
+			()
+		| AbstractStatics a1,AbstractStatics a2 when a1 == a2 ->
+			()
+		| Const,_ ->
+			unify_fields a1.a_fields (fun _ -> ()) (fun f2 ->
+				if Meta.has Meta.Optional f2.cf_meta then begin
+					a1.a_fields <- PMap.add f2.cf_name f2 a1.a_fields;
+					true
+				end else
+					false
+			)
+		| ClassStatics c1,_ ->
+			unify_fields c1.cl_statics (fun f1 ->
+				if not (Meta.has Meta.MaybeUsed f1.cf_meta) then
+					f1.cf_meta <- (Meta.MaybeUsed,[],f1.cf_pos) :: f1.cf_meta
+			) (fun _ -> false)
+		| _ ->
+			unify_fields a1.a_fields (fun _ -> ()) (fun _ -> false)
+	end
 
 
 and does_func_unify f =
 and does_func_unify f =
 	try f(); true with Unify_error _ -> false
 	try f(); true with Unify_error _ -> false