Browse Source

[typer] align static extension on constrained monomorphs

closes #9554
Simon Krajewski 5 years ago
parent
commit
a2e1309648

+ 17 - 1
src/context/display/displayFields.ml

@@ -120,7 +120,23 @@ let collect ctx e_ast e dk with_type p =
 	in
 	in
 	let rec loop items t =
 	let rec loop items t =
 		let is_new_item items name = not (PMap.mem name items) in
 		let is_new_item items name = not (PMap.mem name items) in
-		match follow_and_close t with
+		match follow t with
+		| TMono m ->
+			begin match Monomorph.classify_constraints m with
+			| CStructural(fields,is_open) ->
+				if not is_open then begin
+					Monomorph.close m;
+					begin match m.tm_type with
+					| None -> items
+					| Some t -> loop items t
+					end
+				end else
+					loop items (mk_anon ~fields (ref Closed))
+			| CTypes tl ->
+				items
+			| CUnknown ->
+				items
+			end
 		| TInst ({cl_kind = KTypeParameter tl},_) ->
 		| TInst ({cl_kind = KTypeParameter tl},_) ->
 			(* Type parameters can access the fields of their constraints *)
 			(* Type parameters can access the fields of their constraints *)
 			List.fold_left (fun acc t -> loop acc t) items tl
 			List.fold_left (fun acc t -> loop acc t) items tl

+ 5 - 2
src/typing/fields.ml

@@ -244,7 +244,7 @@ let rec using_field ctx mode e i p =
 	if mode = MSet then raise Not_found;
 	if mode = MSet then raise Not_found;
 	(* do not try to find using fields if the type is a monomorph, which could lead to side-effects *)
 	(* do not try to find using fields if the type is a monomorph, which could lead to side-effects *)
 	let is_dynamic = match follow e.etype with
 	let is_dynamic = match follow e.etype with
-		| TMono _ -> raise Not_found
+		| TMono {tm_constraints = []} -> raise Not_found
 		| t -> t == t_dynamic
 		| t -> t == t_dynamic
 	in
 	in
 	let check_constant_struct = ref false in
 	let check_constant_struct = ref false in
@@ -479,7 +479,10 @@ let rec type_field cfg ctx e i p mode =
 				access f
 				access f
 			with Not_found ->
 			with Not_found ->
 				if not is_open then
 				if not is_open then
-					no_field()
+					try
+						using_field ctx mode e i p
+					with Not_found ->
+						no_field()
 				else begin
 				else begin
 					let f = mk_field() in
 					let f = mk_field() in
 					Monomorph.add_constraint r (MField f);
 					Monomorph.add_constraint r (MField f);

+ 26 - 0
tests/display/src/cases/Issue9554.hx

@@ -0,0 +1,26 @@
+package cases;
+
+class Issue9554 extends DisplayTestCase {
+	/**
+		using Main;
+
+		class Main {
+			static public function main() {
+				infer({foo: 12});
+			}
+
+			static function infer(a) {
+				a.foo = 12;
+				a.{-1-}
+			}
+
+			static function staticExtension(a:{foo:Int}) {}
+		}
+
+	**/
+	function testCatch_noTypeHint() {
+		var fields = fields(pos(1));
+		eq(1, fields.length);
+		eq(true, hasField(fields, "foo", "Int", "var"));
+	}
+}

+ 17 - 0
tests/unit/src/unit/issues/Issue9554.hx

@@ -0,0 +1,17 @@
+package unit.issues;
+
+using unit.issues.Issue9554;
+
+class Issue9554 extends unit.Test {
+	public function test() {
+		var obj = merge({foo: 12}, {bar: "bar"});
+		obj.staticExtension();
+		utest.Assert.pass();
+	}
+
+	static function merge<A:{}, B:{}, C:A & B>(a:A, b:B):C {
+		return null;
+	}
+
+	static function staticExtension(a:{foo:Int, bar:String}) {}
+}