Skip to content

Commit

Permalink
Move escaping local logic into VarianceValidator.
Browse files Browse the repository at this point in the history
  • Loading branch information
paulp committed Jan 9, 2013
1 parent 882f8e6 commit 0693592
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 15 deletions.
16 changes: 4 additions & 12 deletions src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
Expand Up @@ -1449,18 +1449,10 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
checkMigration(sym, tree.pos)
checkCompileTimeOnly(sym, tree.pos)

if (sym eq NoSymbol) {
unit.warning(tree.pos, "Select node has NoSymbol! " + tree + " / " + tree.tpe)
}
else if (currentClass != sym.owner && sym.hasLocalFlag) {
var o = currentClass
var hidden = false
while (!hidden && o != sym.owner && o != sym.owner.moduleClass && !o.isPackage) {
hidden = o.isTerm || o.isPrivateLocal
o = o.owner
}
if (!hidden) varianceValidator.escapedLocals += sym
}
if (sym eq NoSymbol)
devWarning("Select node has NoSymbol! " + tree + " / " + tree.tpe)
else if (sym.hasLocalFlag)
varianceValidator.checkForEscape(sym, currentClass)

def checkSuper(mix: Name) =
// term should have been eliminated by super accessors
Expand Down
18 changes: 15 additions & 3 deletions src/reflect/scala/reflect/internal/Variances.scala
Expand Up @@ -8,6 +8,7 @@ package internal

import Variance._
import scala.collection.{ mutable, immutable }
import scala.annotation.tailrec

/** See comments at scala.reflect.internal.Variance.
*/
Expand All @@ -18,14 +19,25 @@ trait Variances {
* TODO - eliminate duplication with varianceInType
*/
class VarianceValidator extends Traverser {
val escapedLocals = mutable.HashSet[Symbol]()
private val escapedLocals = mutable.HashSet[Symbol]()

/** Is every symbol in the owner chain between `site` and the owner of `sym`
* either a term symbol or private[this]? If not, add `sym` to the set of
* esacped locals.
* @pre sym.hasLocalFlag
*/
@tailrec final def checkForEscape(sym: Symbol, site: Symbol) {
if (site == sym.owner || site == sym.owner.moduleClass || site.isPackage) () // done
else if (site.isTerm || site.isPrivateLocal) checkForEscape(sym, site.owner) // ok - recurse to owner
else escapedLocals += sym
}

protected def issueVarianceError(base: Symbol, sym: Symbol, required: Variance): Unit = ()

// Flip occurrences of type parameters and parameters, unless
// - it's a constructor, or case class factory or extractor
// - it's a type parameter of tvar's owner.
private def isFlipped(sym: Symbol, tvar: Symbol) = (
def shouldFlip(sym: Symbol, tvar: Symbol) = (
sym.isParameter
&& !sym.owner.isConstructor
&& !sym.owner.isCaseApplyOrUnapply
Expand Down Expand Up @@ -56,7 +68,7 @@ trait Variances {
*/
def relativeVariance(tvar: Symbol): Variance = {
def nextVariance(sym: Symbol, v: Variance): Variance = (
if (isFlipped(sym, tvar)) v.flip
if (shouldFlip(sym, tvar)) v.flip
else if (isLocalOnly(sym)) Bivariant
else if (!sym.isAliasType) v
else if (sym.isOverridingSymbol) Invariant
Expand Down

0 comments on commit 0693592

Please sign in to comment.