Skip to content

Commit 9b730ab

Browse files
committed
Implementing stricter rule for callee type inference
1 parent 7dda4cb commit 9b730ab

File tree

1 file changed

+15
-13
lines changed

1 file changed

+15
-13
lines changed

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1857,19 +1857,24 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
18571857
case Typed(arg1, _) if untpd.isWildcardStarArg(arg) => refersTo(arg1, param)
18581858
case _ => false
18591859

1860+
def containsParamRef(tree: untpd.Tree, params: List[untpd.ValDef]): Boolean =
1861+
import dotty.tools.dotc.ast.untpd.existsSubTree
1862+
tree.existsSubTree {
1863+
case Ident(name) => params.exists(_.name == name)
1864+
case _ => false
1865+
}
1866+
18601867
/** If parameter `param` appears exactly once as an argument in `args`,
18611868
* the singleton list consisting of its position in `args`, otherwise `Nil`.
18621869
*/
1863-
def paramIndices(param: untpd.ValDef, args: List[untpd.Tree]): List[Int] = {
1864-
def loop(args: List[untpd.Tree], start: Int): List[Int] = args match {
1870+
def paramIndices(param: untpd.ValDef, args: List[untpd.Tree]): List[Int] =
1871+
def loop(args: List[untpd.Tree], start: Int): List[Int] = args match
18651872
case arg :: args1 =>
18661873
val others = loop(args1, start + 1)
18671874
if (refersTo(arg, param)) start :: others else others
18681875
case _ => Nil
1869-
}
18701876
val allIndices = loop(args, 0)
1871-
if (allIndices.length == 1) allIndices else Nil
1872-
}
1877+
if allIndices.length == 1 then allIndices else Nil
18731878

18741879
/** A map from parameter names to unique positions where the parameter
18751880
* appears in the argument list of an application.
@@ -1905,25 +1910,22 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
19051910
fnBody = untpd.TypedSplice(ident1)
19061911
tp.select(nme.apply)
19071912
else NoType
1908-
case app @ Apply(expr, args) =>
1913+
case app @ Apply(expr, args) if !containsParamRef(expr, params) =>
19091914
paramIndex = {
19101915
for (param <- params; idx <- paramIndices(param, args))
19111916
yield param.name -> idx
19121917
}.toMap
1918+
// println(i"paramIndex = $paramIndex, paramIndex.size = ${paramIndex.size}, params.length = ${params.length}")
19131919
if (paramIndex.size == params.length)
19141920
expr match
19151921
case untpd.TypedSplice(expr1) =>
19161922
expr1.tpe
19171923
case _ =>
19181924
val outerCtx = ctx
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*))
1925+
val nestedCtx = outerCtx.fresh.setNewTyperState()
19251926
inContext(nestedCtx) {
1926-
val protoArgs = args.map(_.withType(WildcardType))
1927+
// create a placeholder tree for each prototype argument
1928+
val protoArgs = args.map(arg => untpd.TypedSplice(TypeTree(WildcardType).withSpan(arg.span)))
19271929
val callProto = FunProto(protoArgs, WildcardType)(this, app.applyKind)
19281930
val expr1 = typedExpr(expr, callProto)
19291931
if nestedCtx.reporter.hasErrors then NoType

0 commit comments

Comments
 (0)