소스 검색

only consider overloads with correct first arg type for "using"

Simon Krajewski 13 년 전
부모
커밋
151f571998
1개의 변경된 파일17개의 추가작업 그리고 8개의 파일을 삭제
  1. 17 8
      typer.ml

+ 17 - 8
typer.ml

@@ -156,12 +156,21 @@ let can_access cs ct cf stat =
 	in
 	cf.cf_public || loop ct
 
-let remove_first_arg cf =
-	let remove t = match t with
-		| TFun(_ :: args,ret) -> TFun(args,ret)
-		| _ -> t
-	in
-	{ cf with cf_overloads = List.map (fun cf -> { cf with cf_type = remove cf.cf_type}) cf.cf_overloads; cf_type = remove cf.cf_type}
+(* removes the first argument of the class field's function type and all its overloads *)
+let prepare_using_field cf = match cf.cf_type with
+	| TFun((_,_,tf) :: args,ret) ->
+		let rec loop acc overloads = match overloads with
+			| ({cf_type = TFun((_,_,tfo) :: args,ret)} as cfo) :: l ->
+				let tfo = apply_params cfo.cf_params (List.map snd cf.cf_params) tfo in
+				(* ignore overloads which have a different first argument *)
+				if Type.type_iseq tf tfo then loop ({cfo with cf_type = TFun(args,ret)} :: acc) l else loop acc l
+			| _ :: l ->
+				loop acc l
+			| [] ->
+				acc
+		in
+		{cf with cf_overloads = loop [] cf.cf_overloads; cf_type = TFun(args,ret)}
+	| _ -> cf
 
 (* ---------------------------------------------------------------------- *)
 (* PASS 3 : type expression & check structure *)
@@ -2132,7 +2141,7 @@ and type_expr ctx ?(need_val=true) (e,p) =
 							if not (can_access ctx.curclass c f true) || follow e.etype == t_dynamic && follow t != t_dynamic then
 								()
 							else begin
-								let f = remove_first_arg f in
+								let f = prepare_using_field f in
 								let f = { f with cf_params = []; cf_public = true } in
 								acc := PMap.add f.cf_name f (!acc)
 							end
@@ -2236,7 +2245,7 @@ and build_call ctx acc el twith p =
 		) in
 		make_call ctx (mk (TField (ethis,f.cf_name)) t p) params (match tfunc with TFun(_,r) -> r | _ -> assert false) p
 	| AKUsing (et,cl,ef,eparam) ->
-		let ef = remove_first_arg ef in
+		let ef = prepare_using_field ef in
 		(match et.eexpr with
 		| TField (ec,_) ->
 			let acc = type_field ctx ec ef.cf_name p MCall in