Skip to content

Commit 08087d8

Browse files
authored
Merge pull request #2934 from dotty-staging/change-variances
Change variances in TypeMaps and Accumulators
2 parents 951b53e + 8683f66 commit 08087d8

File tree

3 files changed

+29
-7
lines changed

3 files changed

+29
-7
lines changed

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

+15-4
Original file line numberDiff line numberDiff line change
@@ -3713,8 +3713,19 @@ object Types {
37133713
tp match {
37143714
case tp: NamedType =>
37153715
if (stopAtStatic && tp.symbol.isStatic) tp
3716-
else derivedSelect(tp, this(tp.prefix))
3717-
3716+
else {
3717+
val saved = variance
3718+
variance = variance max 0
3719+
// A prefix is never contravariant. Even if say `p.A` is used in a contravariant
3720+
// context, we cannot assume contravariance for `p` because `p`'s lower
3721+
// bound might not have a binding for `A` (e.g. the lower bound could be `Nothing`).
3722+
// By contrast, covariance does translate to the prefix, since we have that
3723+
// if `p <: q` then `p.A <: q.A`, and well-formedness requires that `A` is a member
3724+
// of `p`'s upper bound.
3725+
val prefix1 = this(tp.prefix)
3726+
variance = saved
3727+
derivedSelect(tp, prefix1)
3728+
}
37183729
case _: ThisType
37193730
| _: BoundType
37203731
| NoPrefix => tp
@@ -3913,9 +3924,9 @@ object Types {
39133924

39143925
protected var variance = 1
39153926

3916-
protected def applyToPrefix(x: T, tp: NamedType) = {
3927+
protected final def applyToPrefix(x: T, tp: NamedType) = {
39173928
val saved = variance
3918-
variance = 0
3929+
variance = variance max 0 // see remark on NamedType case in TypeMap
39193930
val result = this(x, tp.prefix)
39203931
variance = saved
39213932
result

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

-2
Original file line numberDiff line numberDiff line change
@@ -319,8 +319,6 @@ object Inferencing {
319319
case _ =>
320320
foldOver(vmap, t)
321321
}
322-
override def applyToPrefix(vmap: VarianceMap, t: NamedType) =
323-
apply(vmap, t.prefix)
324322
}
325323

326324
/** Include in `vmap` type variables occurring in the constraints of type variables

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

+14-1
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,20 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
268268
if (qualifies(defDenot)) {
269269
val found =
270270
if (isSelfDenot(defDenot)) curOwner.enclosingClass.thisType
271-
else curOwner.thisType.select(name, defDenot)
271+
else {
272+
val effectiveOwner =
273+
if (curOwner.isTerm && defDenot.symbol.isType)
274+
// Don't mix NoPrefix and thisType prefixes, since type comparer
275+
// would not detect types to be compatible. Note: If we replace the
276+
// 2nd condition by `defDenot.symbol.maybeOwner.isType` we get lots
277+
// of failures in the `tastyBootstrap` test. Trying to compile these
278+
// files in isolation works though.
279+
// TODO: Investigate why that happens.
280+
defDenot.symbol.owner
281+
else
282+
curOwner
283+
effectiveOwner.thisType.select(name, defDenot)
284+
}
272285
if (!(curOwner is Package) || isDefinedInCurrentUnit(defDenot))
273286
result = checkNewOrShadowed(found, definition) // no need to go further out, we found highest prec entry
274287
else {

0 commit comments

Comments
 (0)