File tree 3 files changed +29
-7
lines changed
compiler/src/dotty/tools/dotc
3 files changed +29
-7
lines changed Original file line number Diff line number Diff line change @@ -3713,8 +3713,19 @@ object Types {
3713
3713
tp match {
3714
3714
case tp : NamedType =>
3715
3715
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
+ }
3718
3729
case _ : ThisType
3719
3730
| _ : BoundType
3720
3731
| NoPrefix => tp
@@ -3913,9 +3924,9 @@ object Types {
3913
3924
3914
3925
protected var variance = 1
3915
3926
3916
- protected def applyToPrefix (x : T , tp : NamedType ) = {
3927
+ protected final def applyToPrefix (x : T , tp : NamedType ) = {
3917
3928
val saved = variance
3918
- variance = 0
3929
+ variance = variance max 0 // see remark on NamedType case in TypeMap
3919
3930
val result = this (x, tp.prefix)
3920
3931
variance = saved
3921
3932
result
Original file line number Diff line number Diff line change @@ -319,8 +319,6 @@ object Inferencing {
319
319
case _ =>
320
320
foldOver(vmap, t)
321
321
}
322
- override def applyToPrefix (vmap : VarianceMap , t : NamedType ) =
323
- apply(vmap, t.prefix)
324
322
}
325
323
326
324
/** Include in `vmap` type variables occurring in the constraints of type variables
Original file line number Diff line number Diff line change @@ -268,7 +268,20 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
268
268
if (qualifies(defDenot)) {
269
269
val found =
270
270
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
+ }
272
285
if (! (curOwner is Package ) || isDefinedInCurrentUnit(defDenot))
273
286
result = checkNewOrShadowed(found, definition) // no need to go further out, we found highest prec entry
274
287
else {
You can’t perform that action at this time.
0 commit comments