Skip to content

Commit 6b041ee

Browse files
authored
Merge pull request #2209 from dotty-staging/fix-#2152
Fix #2152: Instantiate dependent result type parameters
2 parents b8ed254 + aaff621 commit 6b041ee

File tree

5 files changed

+24
-11
lines changed

5 files changed

+24
-11
lines changed

compiler/src/dotty/tools/dotc/core/NameKinds.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ object NameKinds {
209209
val InlineAccessorName = new UniqueNameKind("$_inlineAccessor_$")
210210
val TempResultName = new UniqueNameKind("ev$")
211211
val EvidenceParamName = new UniqueNameKind("evidence$")
212-
val DepParamName = new UniqueNameKind("<param>")
212+
val DepParamName = new UniqueNameKind("(param)")
213213
val LazyImplicitName = new UniqueNameKind("$_lazy_implicit_$")
214214
val LazyLocalName = new UniqueNameKind("$lzy")
215215
val LazyLocalInitName = new UniqueNameKind("$lzyINIT")

compiler/src/dotty/tools/dotc/core/TypeOps.scala

+6-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import SymDenotations._, Denotations.SingleDenotation
77
import config.Printers.typr
88
import util.Positions._
99
import NameOps._
10+
import NameKinds.DepParamName
1011
import Decorators._
1112
import StdNames._
1213
import Annotations._
@@ -158,7 +159,11 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
158159
case tp1 => tp1
159160
}
160161
case tp: TypeParamRef =>
161-
typerState.constraint.typeVarOfParam(tp) orElse tp
162+
if (tp.paramName.is(DepParamName)) {
163+
val bounds = ctx.typeComparer.bounds(tp)
164+
if (bounds.lo.isRef(defn.NothingClass)) bounds.hi else bounds.lo
165+
}
166+
else typerState.constraint.typeVarOfParam(tp) orElse tp
162167
case _: ThisType | _: BoundType | NoPrefix =>
163168
tp
164169
case tp: RefinedType =>

compiler/src/dotty/tools/dotc/core/Types.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -3509,7 +3509,7 @@ object Types {
35093509

35103510
def apply(tp: Type): Type
35113511

3512-
protected var variance = 1
3512+
protected[core] var variance = 1
35133513

35143514
protected def derivedSelect(tp: NamedType, pre: Type): Type =
35153515
tp.derivedSelect(pre)

compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala

+9-8
Original file line numberDiff line numberDiff line change
@@ -377,9 +377,10 @@ object ProtoTypes {
377377
* Also, if `owningTree` is non-empty, add a type variable for each parameter.
378378
* @return The added type lambda, and the list of created type variables.
379379
*/
380-
def constrained(tl: TypeLambda, owningTree: untpd.Tree)(implicit ctx: Context): (TypeLambda, List[TypeTree]) = {
380+
def constrained(tl: TypeLambda, owningTree: untpd.Tree, alwaysAddTypeVars: Boolean = false)(implicit ctx: Context): (TypeLambda, List[TypeTree]) = {
381381
val state = ctx.typerState
382-
assert(!(ctx.typerState.isCommittable && owningTree.isEmpty),
382+
val addTypeVars = alwaysAddTypeVars || !owningTree.isEmpty
383+
assert(!(ctx.typerState.isCommittable && !addTypeVars),
383384
s"inconsistent: no typevars were added to committable constraint ${state.constraint}")
384385

385386
def newTypeVars(tl: TypeLambda): List[TypeTree] =
@@ -392,21 +393,21 @@ object ProtoTypes {
392393
val added =
393394
if (state.constraint contains tl) tl.newLikeThis(tl.paramNames, tl.paramInfos, tl.resultType)
394395
else tl
395-
val tvars = if (owningTree.isEmpty) Nil else newTypeVars(added)
396+
val tvars = if (addTypeVars) newTypeVars(added) else Nil
396397
ctx.typeComparer.addToConstraint(added, tvars.tpes.asInstanceOf[List[TypeVar]])
397398
(added, tvars)
398399
}
399400

400401
/** Same as `constrained(tl, EmptyTree)`, but returns just the created type lambda */
401402
def constrained(tl: TypeLambda)(implicit ctx: Context): TypeLambda = constrained(tl, EmptyTree)._1
402403

403-
/** Create a new TypeParamRef that represents a dependent method parameter singleton */
404-
def newDepTypeParamRef(tp: Type)(implicit ctx: Context): TypeParamRef = {
404+
/** Create a new TypeVar that represents a dependent method parameter singleton */
405+
def newDepTypeVar(tp: Type)(implicit ctx: Context): TypeVar = {
405406
val poly = PolyType(DepParamName.fresh().toTypeName :: Nil)(
406407
pt => TypeBounds.upper(AndType(tp, defn.SingletonType)) :: Nil,
407408
pt => defn.AnyType)
408-
ctx.typeComparer.addToConstraint(poly, Nil)
409-
TypeParamRef(poly, 0)
409+
constrained(poly, untpd.EmptyTree, alwaysAddTypeVars = true)
410+
._2.head.tpe.asInstanceOf[TypeVar]
410411
}
411412

412413
/** The result type of `mt`, where all references to parameters of `mt` are
@@ -415,7 +416,7 @@ object ProtoTypes {
415416
def resultTypeApprox(mt: MethodType)(implicit ctx: Context): Type =
416417
if (mt.isDependent) {
417418
def replacement(tp: Type) =
418-
if (ctx.mode.is(Mode.TypevarsMissContext)) WildcardType else newDepTypeParamRef(tp)
419+
if (ctx.mode.is(Mode.TypevarsMissContext)) WildcardType else newDepTypeVar(tp)
419420
mt.resultType.substParams(mt, mt.paramInfos.map(replacement))
420421
}
421422
else mt.resultType

tests/pos/i2152.scala

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class Contra[-D](task: AnyRef)
2+
object Test {
3+
def narrow(task: AnyRef): Contra[task.type] = new Contra(task)
4+
def ident[Before](elems: Contra[Before]): Contra[Before] = elems
5+
val foo = null
6+
ident(narrow(foo))
7+
}

0 commit comments

Comments
 (0)