aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorodersky <odersky@gmail.com>2017-04-13 12:28:17 +0200
committerGitHub <noreply@github.com>2017-04-13 12:28:17 +0200
commit6b041ee7b5df98a84c3fbf31b8392fe77152529d (patch)
treeac7856bb41ae216d5aa2972d3e26b02badc9292f
parentb8ed254e38480eb8892eccd897d525d977d9e6a7 (diff)
parentaaff621f552e6824db4f7c1d73d9e8941e088d96 (diff)
downloaddotty-6b041ee7b5df98a84c3fbf31b8392fe77152529d.zip
dotty-6b041ee7b5df98a84c3fbf31b8392fe77152529d.tar.gz
dotty-6b041ee7b5df98a84c3fbf31b8392fe77152529d.tar.bz2
Merge pull request #2209 from dotty-staging/fix-#2152
Fix #2152: Instantiate dependent result type parameters
-rw-r--r--compiler/src/dotty/tools/dotc/core/NameKinds.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/core/TypeOps.scala7
-rw-r--r--compiler/src/dotty/tools/dotc/core/Types.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala17
-rw-r--r--tests/pos/i2152.scala7
5 files changed, 24 insertions, 11 deletions
diff --git a/compiler/src/dotty/tools/dotc/core/NameKinds.scala b/compiler/src/dotty/tools/dotc/core/NameKinds.scala
index 0f08e47..81ac3a0 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 9593bfe..4a1c3d0 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._
@@ -158,7 +159,11 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
case tp1 => tp1
}
case tp: TypeParamRef =>
- typerState.constraint.typeVarOfParam(tp) orElse tp
+ if (tp.paramName.is(DepParamName)) {
+ val bounds = ctx.typeComparer.bounds(tp)
+ if (bounds.lo.isRef(defn.NothingClass)) bounds.hi else bounds.lo
+ }
+ else typerState.constraint.typeVarOfParam(tp) orElse tp
case _: ThisType | _: BoundType | NoPrefix =>
tp
case tp: RefinedType =>
diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala
index c8c1886..955a5a1 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 398a7a1..5d82403 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 0000000..2171a48
--- /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))
+}