summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/internal/Variances.scala
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2014-09-26 09:24:50 +1000
committerJason Zaugg <jzaugg@gmail.com>2016-08-18 11:18:47 +1000
commit036a9bbd0be2b71fc9d60954fd0b1b64c9a181af (patch)
tree714e23d5e4da45ae1fd6badb1f3d90a40dd426dd /src/reflect/scala/reflect/internal/Variances.scala
parent4e564efb04e508ccc0f479cf1a25331501927d88 (diff)
downloadscala-036a9bbd0be2b71fc9d60954fd0b1b64c9a181af.tar.gz
scala-036a9bbd0be2b71fc9d60954fd0b1b64c9a181af.tar.bz2
scala-036a9bbd0be2b71fc9d60954fd0b1b64c9a181af.zip
SI-8079 Only expand local aliases during variance checks
We've been flip-flopping on this one through the years, right now we issue an two errors for the enclosed test. After this commit, variance validation only expands aliases that are `{private,protected}[this]`. The rest need not be expanded, as we have already variance validated the RHS of the alias. It also removes a seemingly incorrect check in `isLocalOnly`. This also means that we can use `@uncheckedVariance` to create variant type aliases for Java interfaces. However, if such a type alias is declared private local, it *will* be expanded. That shouldn't be a problem, other than for the fact that we run through an as-seen-from that strips the `@uV` annotations in the type expansion. This has been recorded in a pending test.
Diffstat (limited to 'src/reflect/scala/reflect/internal/Variances.scala')
-rw-r--r--src/reflect/scala/reflect/internal/Variances.scala10
1 files changed, 6 insertions, 4 deletions
diff --git a/src/reflect/scala/reflect/internal/Variances.scala b/src/reflect/scala/reflect/internal/Variances.scala
index 69bade55f1..0b964e81d5 100644
--- a/src/reflect/scala/reflect/internal/Variances.scala
+++ b/src/reflect/scala/reflect/internal/Variances.scala
@@ -53,8 +53,7 @@ trait Variances {
// 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
+ (sym.isLocalToThis || sym.isSuperAccessor) // super accessors are implicitly local #4345
&& !escapedLocals(sym)
)
@@ -66,7 +65,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).
@@ -126,7 +125,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 +137,9 @@ trait Variances {
// than the result of the pattern match above, which normalizes types.
tp
}
+ private def shouldDealias(sym: Symbol): Boolean = {
+ sym.isAliasType && isLocalOnly(sym)
+ }
def validateDefinition(base: Symbol) {
val saved = this.base
this.base = base