summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/internal/Variances.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/reflect/scala/reflect/internal/Variances.scala')
-rw-r--r--src/reflect/scala/reflect/internal/Variances.scala28
1 files changed, 17 insertions, 11 deletions
diff --git a/src/reflect/scala/reflect/internal/Variances.scala b/src/reflect/scala/reflect/internal/Variances.scala
index af04f47e0e..98b4e881af 100644
--- a/src/reflect/scala/reflect/internal/Variances.scala
+++ b/src/reflect/scala/reflect/internal/Variances.scala
@@ -8,7 +8,7 @@ package reflect
package internal
import Variance._
-import scala.collection.{ mutable, immutable }
+import scala.collection.mutable
import scala.annotation.tailrec
/** See comments at scala.reflect.internal.Variance.
@@ -50,11 +50,9 @@ trait Variances {
sym.isParameter
&& !(tvar.isTypeParameterOrSkolem && sym.isTypeParameterOrSkolem && tvar.owner == sym.owner)
)
- // return Bivariant if `sym` is local to a term
- // or is private[this] or protected[this]
- def isLocalOnly(sym: Symbol) = !sym.owner.isClass || (
- sym.isTerm // ?? shouldn't this be sym.owner.isTerm according to the comments above?
- && (sym.isLocalToThis || sym.isSuperAccessor) // super accessors are implicitly local #4345
+ // Is `sym` is local to a term or is private[this] or protected[this]?
+ def isExemptFromVariance(sym: Symbol): Boolean = !sym.owner.isClass || (
+ (sym.isLocalToThis || sym.isSuperAccessor) // super accessors are implicitly local #4345
&& !escapedLocals(sym)
)
@@ -66,7 +64,7 @@ trait Variances {
* Initially the state is covariant, but it might change along the search.
*
* A local alias type is treated as Bivariant;
- * this is OK because we always expand aliases for variance checking.
+ * this is OK because such aliases are expanded for variance checking.
* However, for an alias which might be externally visible, we must assume Invariant,
* because there may be references to the type parameter that are not checked,
* leading to unsoundness (see SI-6566).
@@ -74,12 +72,12 @@ trait Variances {
def relativeVariance(tvar: Symbol): Variance = {
def nextVariance(sym: Symbol, v: Variance): Variance = (
if (shouldFlip(sym, tvar)) v.flip
- else if (isLocalOnly(sym)) Bivariant
+ else if (isExemptFromVariance(sym)) Bivariant
else if (sym.isAliasType) (
// Unsound pre-2.11 behavior preserved under -Xsource:2.10
if (settings.isScala211 || sym.isOverridingSymbol) Invariant
else {
- currentRun.reporting.deprecationWarning(sym.pos, s"Construct depends on unsound variance analysis and will not compile in scala 2.11 and beyond")
+ currentRun.reporting.deprecationWarning(sym.pos, "Construct depends on unsound variance analysis and will not compile in scala 2.11 and beyond", "2.11.0")
Bivariant
}
)
@@ -126,7 +124,7 @@ trait Variances {
tp match {
case _ if isUncheckedVariance(tp) =>
case _ if resultTypeOnly(tp) => this(tp.resultType)
- case TypeRef(_, sym, _) if sym.isAliasType => this(tp.normalize)
+ case TypeRef(_, sym, _) if shouldDealias(sym) => this(tp.normalize)
case TypeRef(_, sym, _) if !sym.variance.isInvariant => checkVarianceOfSymbol(sym) ; mapOver(tp)
case RefinedType(_, _) => withinRefinement(mapOver(tp))
case ClassInfoType(parents, _, _) => parents foreach this
@@ -138,6 +136,12 @@ trait Variances {
// than the result of the pattern match above, which normalizes types.
tp
}
+ private def shouldDealias(sym: Symbol): Boolean = {
+ // The RHS of (private|protected)[this] type aliases are excluded from variance checks. This is
+ // implemented in relativeVariance.
+ // As such, we need to expand references to them to retain soundness. Example: neg/t8079a.scala
+ sym.isAliasType && isExemptFromVariance(sym)
+ }
def validateDefinition(base: Symbol) {
val saved = this.base
this.base = base
@@ -167,7 +171,9 @@ trait Variances {
case ClassDef(_, _, _, _) | TypeDef(_, _, _, _) =>
validateVariance(sym)
super.traverse(tree)
- // ModuleDefs need not be considered because they have been eliminated already
+ case ModuleDef(_, _, _) =>
+ validateVariance(sym.moduleClass)
+ super.traverse(tree)
case ValDef(_, _, _, _) =>
validateVariance(sym)
case DefDef(_, _, tparams, vparamss, _, _) =>