Skip to content

Commit 68d6696

Browse files
authored
Merge pull request scala#6140 from milessabin/topic/si-10528
Use solved type vars to improve bounds of undetermined vars
2 parents f5d5435 + dd31672 commit 68d6696

File tree

4 files changed

+55
-0
lines changed

4 files changed

+55
-0
lines changed

src/compiler/scala/tools/nsc/typechecker/Implicits.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,7 @@ trait Implicits {
737737
// we must be conservative in leaving type params in undetparams
738738
// prototype == WildcardType: want to remove all inferred Nothings
739739
val AdjustedTypeArgs(okParams, okArgs) = adjustTypeArgs(undetParams, tvars, targs)
740+
enhanceBounds(okParams, okArgs, undetParams)
740741

741742
val subst: TreeTypeSubstituter =
742743
if (okParams.isEmpty) EmptyTreeTypeSubstituter

src/compiler/scala/tools/nsc/typechecker/Infer.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,17 @@ trait Infer extends Checkable {
712712
argtpes
713713
}
714714

715+
// This is primarily a duplicte of enhanceBounds in typedAppliedTypeTree
716+
// modified to use updateInfo rather than setInfo to avoid wiping out
717+
// type history.
718+
def enhanceBounds(okparams: List[Symbol], okargs: List[Type], undets: List[Symbol]): Unit =
719+
undets.foreach { undet =>
720+
val bounds = undet.info.bounds
721+
val substBounds = bounds.subst(okparams, okargs)
722+
if(bounds ne substBounds)
723+
undet.updateInfo(substBounds)
724+
}
725+
715726
private def isApplicableToMethod(undetparams: List[Symbol], mt: MethodType, argtpes0: List[Type], pt: Type): Boolean = {
716727
val formals = formalTypes(mt.paramTypes, argtpes0.length, removeByName = false)
717728
def missingArgs = missingParams[Type](argtpes0, mt.params, x => Some(x) collect { case NamedType(n, _) => n })
@@ -728,6 +739,7 @@ trait Infer extends Checkable {
728739
def tryInstantiating(args: List[Type]) = falseIfNoInstance {
729740
val restpe = mt resultType args
730741
val AdjustedTypeArgs.Undets(okparams, okargs, leftUndet) = methTypeArgs(EmptyTree, undetparams, formals, restpe, args, pt)
742+
enhanceBounds(okparams, okargs, leftUndet)
731743
val restpeInst = restpe.instantiateTypeParams(okparams, okargs)
732744
// #2665: must use weak conformance, not regular one (follow the monomorphic case above)
733745
exprTypeArgs(leftUndet, restpeInst, pt, useWeaklyCompatible = true) match {
@@ -936,11 +948,14 @@ trait Infer extends Checkable {
936948
List()
937949
} else {
938950
val AdjustedTypeArgs.Undets(okParams, okArgs, leftUndet) = adjustTypeArgs(tparams, tvars, targsStrict)
951+
enhanceBounds(okParams, okArgs, leftUndet)
952+
939953
def solved_s = map2(okParams, okArgs)((p, a) => s"$p=$a") mkString ","
940954
def undet_s = leftUndet match {
941955
case Nil => ""
942956
case ps => ps.mkString(", undet=", ",", "")
943957
}
958+
944959
printTyping(tree, s"infer solved $solved_s$undet_s")
945960
substExpr(tree, okParams, okArgs, pt)
946961
leftUndet
@@ -982,6 +997,7 @@ trait Infer extends Checkable {
982997

983998
val AdjustedTypeArgs.AllArgsAndUndets(okparams, okargs, allargs, leftUndet) =
984999
methTypeArgs(fn, undetparams, formals, restpe, argtpes, pt)
1000+
enhanceBounds(okparams, okargs, leftUndet)
9851001

9861002
if (checkBounds(fn, NoPrefix, NoSymbol, undetparams, allargs, "inferred ")) {
9871003
val treeSubst = new TreeTypeSubstituter(okparams, okargs)

src/compiler/scala/tools/nsc/typechecker/Typers.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5188,6 +5188,9 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
51885188
val asym = arg.symbol
51895189
def abounds = asym.info.bounds
51905190
def tbounds = tparam.info.bounds
5191+
// TODO investigate whether this should be merged with the near duplicate in Inferencer
5192+
// and whether or not we should avoid using setInfo here as well to avoid potentially
5193+
// trampling on type history.
51915194
def enhanceBounds(): Unit = {
51925195
val TypeBounds(lo0, hi0) = abounds
51935196
val TypeBounds(lo1, hi1) = tbounds.subst(tparams, argtypes)

test/files/pos/t10528.scala

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
object Test {
2+
trait Holder[A]
3+
trait NilHolder[A] extends Holder[A]
4+
5+
trait Solve[A, H <: Holder[A]] {
6+
type Output <: Holder[A]
7+
}
8+
type SolveAux[A, H <: Holder[A], O <: Holder[A]] = Solve[A, H] {type Output = O}
9+
10+
implicit def nilSolve[A] = new Solve[A, NilHolder[A]] {
11+
override type Output = NilHolder[A]
12+
}
13+
14+
trait WrapSolve[A, H <: Holder[A]] {
15+
type Output <: Holder[A]
16+
}
17+
18+
implicit def wrapAux[A, H <: Holder[A], O <: Holder[A]](implicit one : SolveAux[A, H, O]) =
19+
new WrapSolve[A, H] {
20+
override type Output = O
21+
}
22+
23+
val wrapped = implicitly[WrapSolve[String, NilHolder[String]]]
24+
}
25+
26+
object Test2 {
27+
class Inv[T]
28+
class Foo[T, U <: Inv[T]]
29+
30+
implicit def foo[T]: Foo[T, Inv[T]] = new Foo[T, Inv[T]]
31+
32+
def bar[T, U <: Inv[T]](implicit foo: Foo[T, U]): Inv[T] = new Inv[T]
33+
34+
val baz: Inv[Int] = bar
35+
}

0 commit comments

Comments
 (0)