@@ -50,11 +50,9 @@ trait Variances {
5050 sym.isParameter
5151 && ! (tvar.isTypeParameterOrSkolem && sym.isTypeParameterOrSkolem && tvar.owner == sym.owner)
5252 )
53- // return Bivariant if `sym` is local to a term
54- // or is private[this] or protected[this]
55- def isLocalOnly (sym : Symbol ) = ! sym.owner.isClass || (
56- sym.isTerm // ?? shouldn't this be sym.owner.isTerm according to the comments above?
57- && (sym.isLocalToThis || sym.isSuperAccessor) // super accessors are implicitly local #4345
53+ // Is `sym` is local to a term or is private[this] or protected[this]?
54+ def isExemptFromVariance (sym : Symbol ): Boolean = ! sym.owner.isClass || (
55+ (sym.isLocalToThis || sym.isSuperAccessor) // super accessors are implicitly local #4345
5856 && ! escapedLocals(sym)
5957 )
6058
@@ -66,15 +64,15 @@ trait Variances {
6664 * Initially the state is covariant, but it might change along the search.
6765 *
6866 * A local alias type is treated as Bivariant;
69- * this is OK because we always expand aliases for variance checking.
67+ * this is OK because such aliases are expanded for variance checking.
7068 * However, for an alias which might be externally visible, we must assume Invariant,
7169 * because there may be references to the type parameter that are not checked,
7270 * leading to unsoundness (see SI-6566).
7371 */
7472 def relativeVariance (tvar : Symbol ): Variance = {
7573 def nextVariance (sym : Symbol , v : Variance ): Variance = (
7674 if (shouldFlip(sym, tvar)) v.flip
77- else if (isLocalOnly (sym)) Bivariant
75+ else if (isExemptFromVariance (sym)) Bivariant
7876 else if (sym.isAliasType) (
7977 // Unsound pre-2.11 behavior preserved under -Xsource:2.10
8078 if (settings.isScala211 || sym.isOverridingSymbol) Invariant
@@ -126,7 +124,7 @@ trait Variances {
126124 tp match {
127125 case _ if isUncheckedVariance(tp) =>
128126 case _ if resultTypeOnly(tp) => this (tp.resultType)
129- case TypeRef (_, sym, _) if sym.isAliasType => this (tp.normalize)
127+ case TypeRef (_, sym, _) if shouldDealias( sym) => this (tp.normalize)
130128 case TypeRef (_, sym, _) if ! sym.variance.isInvariant => checkVarianceOfSymbol(sym) ; mapOver(tp)
131129 case RefinedType (_, _) => withinRefinement(mapOver(tp))
132130 case ClassInfoType (parents, _, _) => parents foreach this
@@ -138,6 +136,12 @@ trait Variances {
138136 // than the result of the pattern match above, which normalizes types.
139137 tp
140138 }
139+ private def shouldDealias (sym : Symbol ): Boolean = {
140+ // The RHS of (private|protected)[this] type aliases are excluded from variance checks. This is
141+ // implemented in relativeVariance.
142+ // As such, we need to expand references to them to retain soundness. Example: neg/t8079a.scala
143+ sym.isAliasType && isExemptFromVariance(sym)
144+ }
141145 def validateDefinition (base : Symbol ) {
142146 val saved = this .base
143147 this .base = base
0 commit comments