summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2013-01-01 22:42:55 -0800
committerPaul Phillips <paulp@improving.org>2013-01-09 12:11:14 -0800
commit5d66c124e3703ea37997638091663ef1d4011d4d (patch)
tree032b703ec652d75dd5842c6b78ea2d8880868730
parentfb98b7041cc7b4ca63f5888c1131e72a5dcc8411 (diff)
downloadscala-5d66c124e3703ea37997638091663ef1d4011d4d.tar.gz
scala-5d66c124e3703ea37997638091663ef1d4011d4d.tar.bz2
scala-5d66c124e3703ea37997638091663ef1d4011d4d.zip
Handle variance exclusions in a less ad hoc manner.
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala4
-rw-r--r--src/reflect/scala/reflect/internal/Variances.scala41
2 files changed, 29 insertions, 16 deletions
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 020b8bb4cc..c88f2c8616 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -6991,6 +6991,10 @@ trait Types extends api.Types { self: SymbolTable =>
case _ =>
1
}
+
+ def withUncheckedVariance(tp: Type): Type =
+ tp withAnnotation (AnnotationInfo marker uncheckedVarianceClass.tpe)
+
//OPT replaced with tailrecursive function to save on #closures
// was:
// var d = 0
diff --git a/src/reflect/scala/reflect/internal/Variances.scala b/src/reflect/scala/reflect/internal/Variances.scala
index 1628b4015b..df0a502b30 100644
--- a/src/reflect/scala/reflect/internal/Variances.scala
+++ b/src/reflect/scala/reflect/internal/Variances.scala
@@ -47,8 +47,6 @@ trait Variances {
// - it's a type parameter of tvar's owner.
def shouldFlip(sym: Symbol, tvar: Symbol) = (
sym.isParameter
- && !sym.owner.isConstructor
- && !sym.owner.isCaseApplyOrUnapply
&& !(tvar.isTypeParameterOrSkolem && sym.isTypeParameterOrSkolem && tvar.owner == sym.owner)
)
// return Bivariant if `sym` is local to a term
@@ -103,6 +101,12 @@ trait Variances {
decls foreach (sym => withVariance(if (sym.isAliasType) Invariant else variance)(this(sym.info)))
decls
}
+ private def resultTypeOnly(tp: Type) = tp match {
+ case mt: MethodType => !inRefinement
+ case pt: PolyType => true
+ case _ => false
+ }
+
/** For PolyTypes, type parameters are skipped because they are defined
* explicitly (their TypeDefs will be passed here.) For MethodTypes, the
* same is true of the parameters (ValDefs) unless we are inside a
@@ -110,12 +114,12 @@ trait Variances {
*/
def apply(tp: Type): Type = tp match {
case _ if isUncheckedVariance(tp) => tp
- case RefinedType(_, _) => withinRefinement(mapOver(tp))
- case ClassInfoType(parents, _, _) => parents foreach this ; tp
+ case _ if resultTypeOnly(tp) => this(tp.resultType)
case TypeRef(_, sym, _) if sym.isAliasType => this(tp.normalize)
case TypeRef(_, sym, _) if !sym.variance.isInvariant => checkVarianceOfSymbol(sym) ; mapOver(tp)
- case mt @ MethodType(_, result) => if (inRefinement) flipped(mt.paramTypes foreach this) ; this(result)
- case PolyType(_, result) => this(result)
+ case RefinedType(_, _) => withinRefinement(mapOver(tp))
+ case ClassInfoType(parents, _, _) => parents foreach this ; tp
+ case mt @ MethodType(_, result) => flipped(mt.paramTypes foreach this) ; this(result)
case _ => mapOver(tp)
}
def validateDefinition(base: Symbol) {
@@ -132,22 +136,27 @@ trait Variances {
}
override def traverse(tree: Tree) {
- def local = tree.symbol.hasLocalFlag
+ def sym = tree.symbol
+ // No variance check for object-private/protected methods/values.
+ // Or constructors, or case class factory or extractor.
+ def skip = (
+ sym.hasLocalFlag
+ || sym.owner.isConstructor
+ || sym.owner.isCaseApplyOrUnapply
+ )
tree match {
case ClassDef(_, _, _, _) | TypeDef(_, _, _, _) =>
- validateVariance(tree.symbol)
+ validateVariance(sym)
super.traverse(tree)
// ModuleDefs need not be considered because they have been eliminated already
+ case defn: ValOrDefDef if skip =>
+ log(s"Skipping variance check of $sym")
case ValDef(_, _, _, _) =>
- if (!local)
- validateVariance(tree.symbol)
+ validateVariance(sym)
case DefDef(_, _, tparams, vparamss, _, _) =>
- // No variance check for object-private/protected methods/values.
- if (!local) {
- validateVariance(tree.symbol)
- traverseTrees(tparams)
- traverseTreess(vparamss)
- }
+ validateVariance(sym)
+ traverseTrees(tparams)
+ traverseTreess(vparamss)
case Template(_, _, _) =>
super.traverse(tree)
case _ =>