From dbebcd509e4013ce02655a2687b27d0967b3650e Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Wed, 19 Dec 2012 07:32:19 -0800 Subject: SI-6846, regression in type constructor inference. In 658ba1b4e6 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. --- .../scala/tools/nsc/typechecker/Infer.scala | 6 +++-- src/reflect/scala/reflect/internal/Types.scala | 19 +++++++-------- test/files/pos/t6846.scala | 28 ++++++++++++++++++++++ 3 files changed, 40 insertions(+), 13 deletions(-) create mode 100644 test/files/pos/t6846.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index a43dbae1fa..7188290688 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -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) diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 7a63699259..c121c6020e 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -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 diff --git a/test/files/pos/t6846.scala b/test/files/pos/t6846.scala new file mode 100644 index 0000000000..009566493f --- /dev/null +++ b/test/files/pos/t6846.scala @@ -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] +} -- cgit v1.2.3