diff options
-rw-r--r-- | compiler/src/dotty/tools/dotc/core/NameKinds.scala | 2 | ||||
-rw-r--r-- | compiler/src/dotty/tools/dotc/core/TypeOps.scala | 4 | ||||
-rw-r--r-- | compiler/src/dotty/tools/dotc/core/Types.scala | 2 | ||||
-rw-r--r-- | compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala | 17 | ||||
-rw-r--r-- | tests/pos/i2152.scala | 7 |
5 files changed, 22 insertions, 10 deletions
diff --git a/compiler/src/dotty/tools/dotc/core/NameKinds.scala b/compiler/src/dotty/tools/dotc/core/NameKinds.scala index 0f08e4701..81ac3a02f 100644 --- a/compiler/src/dotty/tools/dotc/core/NameKinds.scala +++ b/compiler/src/dotty/tools/dotc/core/NameKinds.scala @@ -209,7 +209,7 @@ object NameKinds { val InlineAccessorName = new UniqueNameKind("$_inlineAccessor_$") val TempResultName = new UniqueNameKind("ev$") val EvidenceParamName = new UniqueNameKind("evidence$") - val DepParamName = new UniqueNameKind("<param>") + val DepParamName = new UniqueNameKind("(param)") val LazyImplicitName = new UniqueNameKind("$_lazy_implicit_$") val LazyLocalName = new UniqueNameKind("$lzy") val LazyLocalInitName = new UniqueNameKind("$lzyINIT") diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index 9593bfe93..0de823e97 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -7,6 +7,7 @@ import SymDenotations._, Denotations.SingleDenotation import config.Printers.typr import util.Positions._ import NameOps._ +import NameKinds.DepParamName import Decorators._ import StdNames._ import Annotations._ @@ -169,6 +170,9 @@ trait TypeOps { this: Context => // TODO: Make standalone object. simplify(l, theMap) & simplify(r, theMap) case OrType(l, r) => simplify(l, theMap) | simplify(r, theMap) + case tp: TypeVar if tp.origin.paramName.is(DepParamName) => + val effectiveVariance = if (theMap == null) 1 else theMap.variance + tp.instanceOpt orElse tp.instantiate(fromBelow = effectiveVariance != -1) case _ => (if (theMap != null) theMap else new SimplifyMap).mapOver(tp) } diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index c8c1886cc..955a5a11c 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -3509,7 +3509,7 @@ object Types { def apply(tp: Type): Type - protected var variance = 1 + protected[core] var variance = 1 protected def derivedSelect(tp: NamedType, pre: Type): Type = tp.derivedSelect(pre) diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index 398a7a17e..5d8240362 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -377,9 +377,10 @@ object ProtoTypes { * Also, if `owningTree` is non-empty, add a type variable for each parameter. * @return The added type lambda, and the list of created type variables. */ - def constrained(tl: TypeLambda, owningTree: untpd.Tree)(implicit ctx: Context): (TypeLambda, List[TypeTree]) = { + def constrained(tl: TypeLambda, owningTree: untpd.Tree, alwaysAddTypeVars: Boolean = false)(implicit ctx: Context): (TypeLambda, List[TypeTree]) = { val state = ctx.typerState - assert(!(ctx.typerState.isCommittable && owningTree.isEmpty), + val addTypeVars = alwaysAddTypeVars || !owningTree.isEmpty + assert(!(ctx.typerState.isCommittable && !addTypeVars), s"inconsistent: no typevars were added to committable constraint ${state.constraint}") def newTypeVars(tl: TypeLambda): List[TypeTree] = @@ -392,7 +393,7 @@ object ProtoTypes { val added = if (state.constraint contains tl) tl.newLikeThis(tl.paramNames, tl.paramInfos, tl.resultType) else tl - val tvars = if (owningTree.isEmpty) Nil else newTypeVars(added) + val tvars = if (addTypeVars) newTypeVars(added) else Nil ctx.typeComparer.addToConstraint(added, tvars.tpes.asInstanceOf[List[TypeVar]]) (added, tvars) } @@ -400,13 +401,13 @@ object ProtoTypes { /** Same as `constrained(tl, EmptyTree)`, but returns just the created type lambda */ def constrained(tl: TypeLambda)(implicit ctx: Context): TypeLambda = constrained(tl, EmptyTree)._1 - /** Create a new TypeParamRef that represents a dependent method parameter singleton */ - def newDepTypeParamRef(tp: Type)(implicit ctx: Context): TypeParamRef = { + /** Create a new TypeVar that represents a dependent method parameter singleton */ + def newDepTypeVar(tp: Type)(implicit ctx: Context): TypeVar = { val poly = PolyType(DepParamName.fresh().toTypeName :: Nil)( pt => TypeBounds.upper(AndType(tp, defn.SingletonType)) :: Nil, pt => defn.AnyType) - ctx.typeComparer.addToConstraint(poly, Nil) - TypeParamRef(poly, 0) + constrained(poly, untpd.EmptyTree, alwaysAddTypeVars = true) + ._2.head.tpe.asInstanceOf[TypeVar] } /** The result type of `mt`, where all references to parameters of `mt` are @@ -415,7 +416,7 @@ object ProtoTypes { def resultTypeApprox(mt: MethodType)(implicit ctx: Context): Type = if (mt.isDependent) { def replacement(tp: Type) = - if (ctx.mode.is(Mode.TypevarsMissContext)) WildcardType else newDepTypeParamRef(tp) + if (ctx.mode.is(Mode.TypevarsMissContext)) WildcardType else newDepTypeVar(tp) mt.resultType.substParams(mt, mt.paramInfos.map(replacement)) } else mt.resultType diff --git a/tests/pos/i2152.scala b/tests/pos/i2152.scala new file mode 100644 index 000000000..2171a487e --- /dev/null +++ b/tests/pos/i2152.scala @@ -0,0 +1,7 @@ +class Contra[-D](task: AnyRef) +object Test { + def narrow(task: AnyRef): Contra[task.type] = new Contra(task) + def ident[Before](elems: Contra[Before]): Contra[Before] = elems + val foo = null + ident(narrow(foo)) +} |