浏览代码

[display] browse for EDisplay when calls fail

closes #11422
Simon Krajewski 2 年之前
父节点
当前提交
9932f26a1f
共有 3 个文件被更改,包括 70 次插入10 次删除
  1. 13 0
      src/core/ast.ml
  2. 25 10
      src/typing/callUnification.ml
  3. 32 0
      tests/display/src/cases/Issue11422.hx

+ 13 - 0
src/core/ast.ml

@@ -863,6 +863,19 @@ let iter_expr loop (e,p) =
 		opt f.f_expr
 	| EVars vl -> List.iter (fun v -> opt v.ev_expr) vl
 
+let exists check e =
+	let rec loop (e,p) =
+		if check e then
+			raise Exit
+		else
+			iter_expr loop (e,p)
+	in
+	try
+		loop e;
+		false
+	with Exit ->
+		true
+
 let s_object_key_name name =  function
 	| DoubleQuotes -> "\"" ^ StringHelper.s_escape name ^ "\""
 	| NoQuotes -> name

+ 25 - 10
src/typing/callUnification.ml

@@ -350,14 +350,6 @@ let unify_field_call ctx fa el_typed el p inline =
 		in
 		loop candidates
 	in
-	let fail_fun () =
-		let tf = TFun(List.map (fun _ -> ("",false,t_dynamic)) el,t_dynamic) in
-		let call () =
-			let ef = mk (TField(fa.fa_on,FieldAccess.apply_fa fa.fa_field fa.fa_host)) tf fa.fa_pos in
-			mk (TCall(ef,[])) t_dynamic p
-		in
-		make_field_call_candidate [] t_dynamic [] tf fa.fa_field call
-	in
 	let maybe_check_access cf =
 		(* type_field doesn't check access for overloads, so let's check it here *)
 		begin match co with
@@ -367,13 +359,34 @@ let unify_field_call ctx fa el_typed el p inline =
 			()
 		end;
 	in
+	(* There's always a chance that we never even came across the EDisplay in an argument, so let's look for it (issue #11422). *)
+	let check_display_args () =
+		if ctx.is_display_file then begin
+			let rec loop el = match el with
+				| [] ->
+					()
+				| e :: el ->
+					if Ast.exists (function EDisplay _ -> true | _ -> false) e then
+						ignore(type_expr ctx e WithType.value)
+					else
+						loop el
+			in
+			loop el
+		end;
+	in
 	match candidates with
 	| [cf] ->
 		if overload_kind = OverloadProper then maybe_check_access cf;
 		begin try
 			commit_delayed_display (attempt_call cf false)
 		with Error _ when Common.ignore_error ctx.com ->
-			fail_fun();
+			check_display_args();
+			let tf = TFun(List.map (fun _ -> ("",false,t_dynamic)) el,t_dynamic) in
+			let call () =
+				let ef = mk (TField(fa.fa_on,FieldAccess.apply_fa fa.fa_field fa.fa_host)) tf fa.fa_pos in
+				mk (TCall(ef,[])) t_dynamic p
+			in
+			make_field_call_candidate [] t_dynamic [] tf fa.fa_field call
 		end
 	| _ ->
 		let candidates,failures = attempt_calls candidates in
@@ -385,6 +398,7 @@ let unify_field_call ctx fa el_typed el p inline =
 				) delayed_display;
 				cf,err
 			) failures in
+			check_display_args();
 			let failures = remove_duplicates (fun (_,e1) (_,e2) -> (MessageReporting.print_error e1) <> (MessageReporting.print_error e2)) failures in
 			begin match failures with
 			| [_,err] ->
@@ -408,7 +422,8 @@ let unify_field_call ctx fa el_typed el p inline =
 			end
 		in
 		if overload_kind = OverloadProper then begin match Overloads.Resolution.reduce_compatible candidates with
-			| [] -> fail()
+			| [] ->
+				fail()
 			| [fcc] ->
 				maybe_check_access fcc.fc_field;
 				commit_delayed_display fcc

+ 32 - 0
tests/display/src/cases/Issue11422.hx

@@ -0,0 +1,32 @@
+package cases;
+
+class Issue11422 extends DisplayTestCase {
+	/**
+		class Main {
+			static function main() {
+				var string = "";
+				foo(0.0, s{-1-});
+			}
+
+			static function foo(a:Int, name:String):Void {}
+		}
+	**/
+	function test() {
+		eq(true, hasToplevel(toplevel(pos(1)), "local", "string"));
+	}
+
+	/**
+		class Main {
+			static function main() {
+				var string = "";
+				foo(0.0, s{-1-});
+			}
+
+			overload static function foo(a:Int, name:String):Void {}
+			overload static function foo(a:Bool, name:String):Void {}
+		}
+	**/
+	function testOverload() {
+		eq(true, hasToplevel(toplevel(pos(1)), "local", "string"));
+	}
+}