@@ -1916,7 +1916,12 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
19161916 expr1.tpe
19171917 case _ =>
19181918 val outerCtx = ctx
1919- val nestedCtx = outerCtx.fresh.setNewTyperState()
1919+ // Create placeholder symbols for function parameters to shadow outer bindings.
1920+ // This ensures that when typing `expr`, references in it won't incorrectly
1921+ // resolve to outer scope variables with the same names as the parameters.
1922+ val paramSyms = params.map(p =>
1923+ newSymbol(ctx.owner, p.name, Flags .Param , WildcardType , coord = p.span))
1924+ val nestedCtx = outerCtx.fresh.setNewTyperState().setScope(newScopeWith(paramSyms* ))
19201925 inContext(nestedCtx) {
19211926 val protoArgs = args.map(_.withType(WildcardType ))
19221927 val callProto = FunProto (protoArgs, WildcardType )(this , app.applyKind)
@@ -1933,19 +1938,20 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
19331938 NoType
19341939 }
19351940
1936- /** Try to instantiate one type variable bounded by function types that appear
1941+ /** Find one instantiatable type variable bounded by function types that appear
19371942 * deeply inside `tp`, including union or intersection types.
19381943 */
1939- def tryToInstantiateDeeply (tp : Type ): Boolean = tp.dealias match
1944+ def instantiatableTypeVar (tp : Type ): Type = tp.dealias match
19401945 case tp : AndOrType =>
1941- tryToInstantiateDeeply(tp.tp1)
1942- || tryToInstantiateDeeply(tp.tp2)
1946+ val t1 = instantiatableTypeVar(tp.tp1)
1947+ if t1.exists then t1
1948+ else instantiatableTypeVar(tp.tp2)
19431949 case tp : FlexibleType =>
1944- tryToInstantiateDeeply (tp.hi)
1950+ instantiatableTypeVar (tp.hi)
19451951 case tp : TypeVar if isConstrainedByFunctionType(tp) =>
19461952 // Only instantiate if the type variable is constrained by function types
1947- isFullyDefined(tp, ForceDegree .flipBottom)
1948- case _ => false
1953+ tp
1954+ case _ => NoType
19491955
19501956 def isConstrainedByFunctionType (tvar : TypeVar ): Boolean =
19511957 val origin = tvar.origin
@@ -1961,16 +1967,18 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
19611967 case _ => false
19621968 containsFunctionType(bounds.lo) || containsFunctionType(bounds.hi)
19631969
1964- if untpd.isFunctionWithUnknownParamType(tree) && ! calleeType.exists then
1970+ if untpd.isFunctionWithUnknownParamType(tree) then
19651971 // Try to instantiate `pt` when possible.
19661972 // * If `pt` is a type variable, we try to instantiate it directly.
19671973 // * If `pt` is a more complex type, we try to instantiate it deeply by searching
19681974 // a nested type variable bounded by a function type to help infer parameter types.
19691975 // If it does not work the error will be reported later in `inferredParam`,
19701976 // when we try to infer the parameter type.
1971- pt match
1972- case pt : TypeVar => isFullyDefined(pt, ForceDegree .flipBottom)
1973- case _ => tryToInstantiateDeeply(pt)
1977+ // Note: we only check the `calleeType` if there is a TypeVar to instantiate to
1978+ // prioritize inferring from the callee.
1979+ val tp = if pt.isInstanceOf [TypeVar ] then pt else instantiatableTypeVar(pt)
1980+ if tp.exists && ! calleeType.exists then
1981+ isFullyDefined(tp, ForceDegree .flipBottom)
19741982
19751983 val (protoFormals, resultTpt) = decomposeProtoFunction(pt, params.length, tree.srcPos)
19761984
0 commit comments