Browse Source

[typer] delay generic expansion until overloads are resolved

see #10119
Simon Krajewski 4 years ago
parent
commit
68224b2173
3 changed files with 17 additions and 17 deletions
  1. 3 2
      src/context/typecore.ml
  2. 10 10
      src/typing/callUnification.ml
  3. 4 5
      src/typing/generic.ml

+ 3 - 2
src/context/typecore.ml

@@ -173,7 +173,8 @@ type field_access = {
 	(* The expression on which the field is accessed. For abstracts, this is a type expression
 	   to the implementation class. *)
 	fa_on     : texpr;
-	(* The field being accessed. *)
+	(* The field being accessed. Note that in case of overloads, this might refer to the main field which
+	   hosts other overloads in its cf_overloads. *)
 	fa_field  : tclass_field;
 	(* The host of the field. *)
 	fa_host   : field_host;
@@ -205,7 +206,7 @@ let unify_min_ref : (typer -> texpr list -> t) ref = ref (fun _ _ -> die "" __LO
 let unify_min_for_type_source_ref : (typer -> texpr list -> WithType.with_type_source option -> t) ref = ref (fun _ _ _ -> die "" __LOC__)
 let analyzer_run_on_expr_ref : (Common.context -> texpr -> texpr) ref = ref (fun _ _ -> die "" __LOC__)
 let cast_or_unify_raise_ref : (typer -> ?uctx:unification_context option -> Type.t -> texpr -> pos -> texpr) ref = ref (fun _ ?uctx _ _ _ -> assert false)
-let type_generic_function_ref : (typer -> field_access -> texpr list -> expr list -> WithType.t -> pos -> texpr) ref = ref (fun _ _ _ _ _ _ -> assert false)
+let type_generic_function_ref : (typer -> field_access -> (unit -> texpr) field_call_candidate -> WithType.t -> pos -> texpr) ref = ref (fun _ _ _ _ _ -> assert false)
 
 let pass_name = function
 	| PBuildModule -> "build-module"

+ 10 - 10
src/typing/callUnification.ml

@@ -437,11 +437,15 @@ object(self)
 
 	method private make_field_call (fa : field_access) (el_typed : texpr list) (el : expr list) =
 		let fcc = unify_field_call ctx fa el_typed el p fa.fa_inline in
-		if has_class_field_flag fcc.fc_field CfAbstract then begin match fa.fa_on.eexpr with
-			| TConst TSuper -> display_error ctx (Printf.sprintf "abstract method %s cannot be accessed directly" fcc.fc_field.cf_name) p;
-			| _ -> ()
-		end;
-		fcc.fc_data()
+		if has_class_field_flag fcc.fc_field CfGeneric then begin
+			!type_generic_function_ref ctx fa fcc with_type p
+		end else begin
+			if has_class_field_flag fcc.fc_field CfAbstract then begin match fa.fa_on.eexpr with
+				| TConst TSuper -> display_error ctx (Printf.sprintf "abstract method %s cannot be accessed directly" fcc.fc_field.cf_name) p;
+				| _ -> ()
+			end;
+			fcc.fc_data()
+		end
 
 	method private macro_call (ethis : texpr) (cf : tclass_field) (el : expr list) =
 		if ctx.macro_depth > 300 then error "Stack overflow" p;
@@ -577,7 +581,6 @@ object(self)
 
 	   This function inspects the nature of the field being called and dispatches the call accordingly:
 
-	   * If the field is `@:generic`, call `type_generic_function`.
 	   * If the field is a non-macro method, call it via `make_field_call`.
 	   * If the field is a property, resolve the accessor (depending on `mode`) and recurse onto it.
 	   * Otherwise, call the field as a normal expression via `expr_call`.
@@ -586,10 +589,7 @@ object(self)
 		match fa.fa_field.cf_kind with
 		| Method (MethNormal | MethInline | MethDynamic) ->
 			check_assign();
-			 if has_class_field_flag fa.fa_field CfGeneric then begin
-				!type_generic_function_ref ctx fa el_typed el with_type p
-			end else
-				self#make_field_call fa el_typed el
+			self#make_field_call fa el_typed el
 		| Method MethMacro ->
 			begin match el_typed with
 			| [] ->

+ 4 - 5
src/typing/generic.ml

@@ -341,16 +341,15 @@ let rec build_generic ctx c p tl =
 		TInst (cg,[])
 	end
 
-let type_generic_function ctx fa el_typed el with_type p =
+let type_generic_function ctx fa fcc with_type p =
 	let c,stat = match fa.fa_host with
 		| FHInstance(c,tl) -> c,false
 		| FHStatic c -> c,true
 		| FHAbstract(a,tl,c) -> c,true
 		| _ -> die "" __LOC__
 	in
-	let cf = fa.fa_field in
+	let cf = fcc.fc_field in
 	if cf.cf_params = [] then error "Function has no type parameters and cannot be generic" p;
-	let fcc = CallUnification.unify_field_call ctx fa el_typed el p false in
 	begin match with_type with
 		| WithType.WithType(t,_) -> unify ctx fcc.fc_ret t p
 		| _ -> ()
@@ -446,8 +445,8 @@ let type_generic_function ctx fa el_typed el with_type p =
 				{fa with fa_field = cf2}
 			end
 		in
-		let e = FieldAccess.get_field_expr fa FCall in
-		make_call ctx e el fcc.fc_ret p
+		let dispatch = new CallUnification.call_dispatcher ctx (MCall []) with_type p in
+		dispatch#field_call fa el []
 	with Generic_Exception (msg,p) ->
 		error msg p)