Quellcode durchsuchen

properly deal with ClassStatics in unification and field typing

also convert unify_anons to something human-readable
Simon Krajewski vor 1 Jahr
Ursprung
Commit
fa7f4728f2
2 geänderte Dateien mit 73 neuen und 51 gelöschten Zeilen
  1. 52 33
      src/core/tUnification.ml
  2. 21 18
      src/typing/fields.ml

+ 52 - 33
src/core/tUnification.ml

@@ -577,6 +577,10 @@ let rec type_eq uctx a b =
 			| 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 ->
 				try
 					let f2 = PMap.find n a2.a_fields in
@@ -587,9 +591,9 @@ let rec type_eq uctx a b =
 				with
 					Not_found ->
 						error [has_no_field b n];
-			) a1.a_fields;
+			) fields;
 			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];
 				end;
 			) a2.a_fields;
@@ -909,39 +913,54 @@ let rec unify (uctx : unification_context) a b =
 		error [cannot_unify a b]
 
 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 ~strict:uctx.strict_field_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 = PMap.find n a1.a_fields in
-			if not (unify_kind ~strict:uctx.strict_field_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)
+			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
-			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))
+			Unify_error l -> error (invalid_field n :: l)
+	in
+	let unify_fields a1_fields f_good f_bad =
+		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
+	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 =
 	try f(); true with Unify_error _ -> false

+ 21 - 18
src/typing/fields.ml

@@ -329,29 +329,32 @@ let type_field cfg ctx e i p mode (with_type : WithType.t) =
 				type_field_by_interfaces e c
 			)
 		| TAnon a ->
-			(try
-				let f = PMap.find i a.a_fields in
-				if has_class_field_flag f CfImpl && not (has_class_field_flag f CfEnum) then display_error ctx.com "Cannot access non-static abstract field statically" pfield;
-				match !(a.a_status) with
+			begin match !(a.a_status) with
+				| ClassStatics c ->
+					begin try
+						let cf = PMap.find i c.cl_statics in
+						field_access cf (FHStatic c)
+					with Not_found ->
+						begin match c.cl_kind with
+						| KAbstractImpl a ->
+							type_field_by_forward_static (fun() ->
+								let mt = try module_type_of_type a.a_this with Exit -> raise Not_found in
+								let et = type_module_type ctx mt p in
+								type_field_by_e type_field_by_type et
+							) a
+						| _ ->
+							raise Not_found
+						end
+					end
 				| EnumStatics en ->
-					let c = try PMap.find f.cf_name en.e_constrs with Not_found -> die "" __LOC__ in
+					let c = PMap.find i en.e_constrs in
 					let fmode = FEnum (en,c) in
 					let t = enum_field_type ctx en c p in
 					AKExpr (mk (TField (e,fmode)) t p)
-				| ClassStatics c ->
-					field_access f (FHStatic c)
 				| _ ->
-					field_access f FHAnon
-			with Not_found ->
-				match !(a.a_status) with
-				| ClassStatics { cl_kind = KAbstractImpl a } ->
-					type_field_by_forward_static (fun() ->
-						let mt = try module_type_of_type a.a_this with Exit -> raise Not_found in
-						let et = type_module_type ctx mt p in
-						type_field_by_e type_field_by_type et
-					) a
-				| _ -> raise Not_found
-			)
+					let cf = PMap.find i a.a_fields in
+					field_access cf FHAnon
+			end;
 		| TMono r ->
 			let mk_field () = {
 				(mk_field i (mk_mono()) p null_pos) with