Skip to content

Commit 6d87bf5

Browse files
committed
Replace singleton bounds before doing implicit search
Before searching for implicit arguments, if a the constraint contains a type parameter ``` P >: A <: B ``` where `P` occurs in the searched-for type and `A =:= B`, change the constraint to ``` P := B ``` instead. This improves the implicit search by making the searched-for type have fewer uninstantiated type variables.
1 parent d78b8c0 commit 6d87bf5

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

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

+25
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,31 @@ object Inferencing {
138138
}
139139
}
140140

141+
/** For all type parameters occurring in `tp`:
142+
* If the bounds of `tp` in the current constraint are equal wrt =:=,
143+
* instantiate the type parameter to the lower bound's approximation
144+
* (approximation because of possible F-bounds).
145+
*/
146+
def replaceSingletons(tp: Type)(implicit ctx: Context): Unit = {
147+
val tr = new TypeTraverser {
148+
def traverse(tp: Type): Unit = {
149+
tp match {
150+
case param: TypeParamRef =>
151+
val constraint = ctx.typerState.constraint
152+
if (constraint.contains(param) &&
153+
(constraint.fullUpperBound(param) frozen_<:< constraint.fullLowerBound(param))) {
154+
typr.println(i"replace singleton $param := ${constraint.fullLowerBound(param)}")
155+
ctx.typerState.constraint = constraint.replace(param,
156+
ctx.typeComparer.approximation(param, fromBelow = true))
157+
}
158+
case _ =>
159+
}
160+
traverseChildren(tp)
161+
}
162+
}
163+
tr.traverse(tp)
164+
}
165+
141166
/** If `tree` has a type lambda type, infer its type parameters by comparing with expected type `pt` */
142167
def inferTypeParams(tree: Tree, pt: Type)(implicit ctx: Context): Tree = tree.tpe match {
143168
case tl: TypeLambda =>

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -2587,7 +2587,11 @@ class Typer extends Namer
25872587
def adaptNoArgsImplicitMethod(wtp: MethodType): Tree = {
25882588
assert(wtp.isImplicitMethod)
25892589
val tvarsToInstantiate = tvarsInParams(tree, locked).distinct
2590-
wtp.paramInfos.foreach(instantiateSelected(_, tvarsToInstantiate))
2590+
def instantiate(tp: Type): Unit = {
2591+
instantiateSelected(tp, tvarsToInstantiate)
2592+
replaceSingletons(tp)
2593+
}
2594+
wtp.paramInfos.foreach(instantiate)
25912595
val constr = ctx.typerState.constraint
25922596

25932597
def dummyArg(tp: Type) = untpd.Ident(nme.???).withTypeUnchecked(tp)

0 commit comments

Comments
 (0)