Skip to content

Commit

Permalink
SI-6846, regression in type constructor inference.
Browse files Browse the repository at this point in the history
In 658ba1b some inference was gained and some was lost.
In this commit we regain what was lost and gain even more.
Dealiasing and widening should be fully handled now, as
illustrated by the test case.
  • Loading branch information
paulp authored and adriaanm committed Dec 28, 2012
1 parent 3bf5118 commit dbebcd5
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 13 deletions.
6 changes: 4 additions & 2 deletions src/compiler/scala/tools/nsc/typechecker/Infer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1122,15 +1122,17 @@ trait Infer extends Checkable {
*/
def inferExprInstance(tree: Tree, tparams: List[Symbol], pt: Type = WildcardType, treeTp0: Type = null, keepNothings: Boolean = true, useWeaklyCompatible: Boolean = false): List[Symbol] = {
val treeTp = if(treeTp0 eq null) tree.tpe else treeTp0 // can't refer to tree in default for treeTp0
val (targs, tvars) = exprTypeArgs(tparams, treeTp, pt, useWeaklyCompatible)
printInference(
ptBlock("inferExprInstance",
"tree" -> tree,
"tree.tpe"-> tree.tpe,
"tparams" -> tparams,
"pt" -> pt
"pt" -> pt,
"targs" -> targs,
"tvars" -> tvars
)
)
val (targs, tvars) = exprTypeArgs(tparams, treeTp, pt, useWeaklyCompatible)

if (keepNothings || (targs eq null)) { //@M: adjustTypeArgs fails if targs==null, neg/t0226
substExpr(tree, tparams, targs, pt)
Expand Down
19 changes: 8 additions & 11 deletions src/reflect/scala/reflect/internal/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3144,23 +3144,20 @@ trait Types extends api.Types { self: SymbolTable =>
* Checks subtyping of higher-order type vars, and uses variances as defined in the
* type parameter we're trying to infer (the result will be sanity-checked later).
*/
def unifyFull(tpe: Type) = {
// The alias/widen variations are often no-ops.
val tpes = (
if (isLowerBound) List(tpe, tpe.widen, tpe.dealias, tpe.widen.dealias).distinct
else List(tpe)
)
tpes exists { tp =>
val lhs = if (isLowerBound) tp.typeArgs else typeArgs
val rhs = if (isLowerBound) typeArgs else tp.typeArgs

sameLength(lhs, rhs) && {
def unifyFull(tpe: Type): Boolean = {
def unifySpecific(tp: Type) = {
sameLength(typeArgs, tp.typeArgs) && {
val lhs = if (isLowerBound) tp.typeArgs else typeArgs
val rhs = if (isLowerBound) typeArgs else tp.typeArgs
// this is a higher-kinded type var with same arity as tp.
// side effect: adds the type constructor itself as a bound
addBound(tp.typeConstructor)
isSubArgs(lhs, rhs, params, AnyDepth)
}
}
// The type with which we can successfully unify can be hidden
// behind singleton types and type aliases.
tpe.dealiasWidenChain exists unifySpecific
}

// There's a <: test taking place right now, where tp is a concrete type and this is a typevar
Expand Down
28 changes: 28 additions & 0 deletions test/files/pos/t6846.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
object Test {
class Arb[_]
implicit def foo[M[_], A]: Arb[M[A]] = null
foo: Arb[List[Int]]
type ListInt = List[Int]
foo: Arb[ListInt]
}

object Test2 {
import scala.collection.immutable.List

class Carb[_]
implicit def narrow[N, M[_], A](x: Carb[M[A]])(implicit ev: N <:< M[A]): Carb[N] = null
implicit def bar[M[_], A]: Carb[M[A]] = null

type ListInt = List[Int]

val x: List[Int] = List(1)
val y: ListInt = List(1)

type ListSingletonX = x.type
type ListSingletonY = y.type

bar: Carb[List[Int]]
bar: Carb[ListInt]
bar: Carb[ListSingletonX]
bar: Carb[ListSingletonY]
}

0 comments on commit dbebcd5

Please sign in to comment.