diff options
author | Adriaan Moors <adriaan.moors@epfl.ch> | 2011-10-20 22:29:04 +0000 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@epfl.ch> | 2011-10-20 22:29:04 +0000 |
commit | d5b81b6cb1f3880a791118609c2d308c34c075f2 (patch) | |
tree | e67554e7045d8edf600b9da76bca743e6b296ee4 | |
parent | 8704ed2fc92e3d82287317fe34126c5d4d84e10c (diff) | |
download | scala-d5b81b6cb1f3880a791118609c2d308c34c075f2.tar.gz scala-d5b81b6cb1f3880a791118609c2d308c34c075f2.tar.bz2 scala-d5b81b6cb1f3880a791118609c2d308c34c075f2.zip |
misc fixes while working on virtualizing patter...
misc fixes while working on virtualizing pattern matching not directly
related to pattern matching, though
review by extempore
10 files changed, 29 insertions, 23 deletions
diff --git a/src/compiler/scala/reflect/internal/NameManglers.scala b/src/compiler/scala/reflect/internal/NameManglers.scala index 9ff2232840..01a93c0ada 100644 --- a/src/compiler/scala/reflect/internal/NameManglers.scala +++ b/src/compiler/scala/reflect/internal/NameManglers.scala @@ -72,7 +72,6 @@ trait NameManglers { val LOCALDUMMY_PREFIX = "<local " // owner of local blocks val PROTECTED_PREFIX = "protected$" val PROTECTED_SET_PREFIX = PROTECTED_PREFIX + "set" - val SELECTOR_DUMMY = "<unapply-selector>" val SETTER_SUFFIX = encode("_=") val SINGLETON_SUFFIX = ".type" val SUPER_PREFIX_STRING = "super$" diff --git a/src/compiler/scala/reflect/internal/StdNames.scala b/src/compiler/scala/reflect/internal/StdNames.scala index 254c2e3b7e..a59a9040bc 100644 --- a/src/compiler/scala/reflect/internal/StdNames.scala +++ b/src/compiler/scala/reflect/internal/StdNames.scala @@ -187,6 +187,7 @@ trait StdNames extends /*reflect.generic.StdNames with*/ NameManglers { self: Sy val SPECIALIZED_INSTANCE: NameType = "specInstance$" val STAR: NameType = "*" val THIS: NameType = "_$this" + val SELECTOR_DUMMY: NameType = "<unapply-selector>" final val Nil: NameType = "Nil" final val Predef: NameType = "Predef" diff --git a/src/compiler/scala/reflect/internal/Trees.scala b/src/compiler/scala/reflect/internal/Trees.scala index 88eb79c9d8..c469834ac8 100644 --- a/src/compiler/scala/reflect/internal/Trees.scala +++ b/src/compiler/scala/reflect/internal/Trees.scala @@ -279,7 +279,7 @@ trait Trees extends api.Trees { self: SymbolTable => override def traverse(t: Tree) { if (t != EmptyTree && t.pos == NoPosition) { t.setPos(pos) - super.traverse(t) + super.traverse(t) // TODO: bug? shouldn't the traverse be outside of the if? } } } @@ -320,12 +320,15 @@ trait Trees extends api.Trees { self: SymbolTable => "subst[%s, %s](%s)".format(fromStr, toStr, (from, to).zipped map (_ + " -> " + _) mkString ", ") } + // NOTE: if symbols in `from` occur multiple times in the `tree` passed to `transform`, + // the resulting Tree will be a graph, not a tree... this breaks all sorts of stuff, + // notably concerning the mutable aspects of Trees (such as setting their .tpe) class TreeSubstituter(from: List[Symbol], to: List[Tree]) extends Transformer { override def transform(tree: Tree): Tree = tree match { case Ident(_) => def subst(from: List[Symbol], to: List[Tree]): Tree = if (from.isEmpty) tree - else if (tree.symbol == from.head) to.head + else if (tree.symbol == from.head) to.head.shallowDuplicate // TODO: does it ever make sense *not* to perform a shallowDuplicate on `to.head`? else subst(from.tail, to.tail); subst(from, to) case _ => diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala index a0bd994a97..aaf4ae5561 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/compiler/scala/reflect/internal/Types.scala @@ -2568,6 +2568,7 @@ A type's typeSymbol should never be inspected directly. // would be pointless. In this case, each check we perform causes us to lose specificity: in // the end the best we'll do is the least specific type we tested against, since the typevar // does not see these checks as "probes" but as requirements to fulfill. + // TODO: the `suspended` flag can be used to poke around with leaving a trace // // So the strategy used here is to test first the type, then the direct parents, and finally // to fall back on the individual base types. This warrants eventual re-examination. diff --git a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala index 60e761048b..8add556741 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala @@ -68,7 +68,7 @@ trait TreeDSL { /** Note - calling ANY_== in the matcher caused primitives to get boxed * for the comparison, whereas looking up nme.EQ does not. See #3570 for * an example of how target.tpe can be non-null, yet it claims not to have - * a mmeber called nme.EQ. Not sure if that should happen, but we can be + * a member called nme.EQ. Not sure if that should happen, but we can be * robust by dragging in Any regardless. */ def MEMBER_== (other: Tree) = { diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index cc87ea7e06..aaae703d06 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -476,7 +476,8 @@ abstract class Erasure extends AddInterfaces else BLOCK(tree, UNIT) case x => assert(x != ArrayClass) - Apply(unboxMethod(pt.typeSymbol), tree) setType pt + // don't `setType pt` the Apply tree, as the Apply's fun won't be typechecked if the Apply tree already has a type + Apply(unboxMethod(pt.typeSymbol), tree) }) } diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 0181c80bff..c7d3b331a6 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -1135,7 +1135,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { */ private def postTransform(tree: Tree): Tree = { val sym = tree.symbol - + // assert(tree.tpe ne null, tree.getClass +" : "+ tree +" in "+ localTyper.context.tree) // change every node type that refers to an implementation class to its // corresponding interface, unless the node's symbol is an implementation class. if (tree.tpe.typeSymbol.isImplClass && ((sym eq null) || !sym.isImplClass)) diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index f6fc6cedd2..7debe23a89 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -640,21 +640,22 @@ trait Infer { * type parameters that are inferred as `scala.Nothing` and that are not covariant in <code>restpe</code> are taken to be undetermined */ def adjustTypeArgs(tparams: List[Symbol], tvars: List[TypeVar], targs: List[Type], restpe: Type = WildcardType): AdjustedTypeArgs.Result = { - @inline def notCovariantIn(tparam: Symbol, restpe: Type) = - (varianceInType(restpe)(tparam) & COVARIANT) == 0 // tparam occurred non-covariantly (in invariant or contravariant position) + @inline def keep(targ: Type, tparam: Symbol) = ( + targ.typeSymbol != NothingClass // definitely not retracting, it's not Nothing! + || (!restpe.isWildcard && (varianceInType(restpe)(tparam) & COVARIANT) != 0)) // occured covariantly --> don't retract + + @inline def adjusted(targ: Type, tvar: TypeVar) = + if (targ.typeSymbol == RepeatedParamClass) + targ.baseType(SeqClass) + else if (targ.typeSymbol == JavaRepeatedParamClass) + targ.baseType(ArrayClass) + else if (targ.typeSymbol.isModuleClass || (opt.experimental && tvar.constr.avoidWiden)) + targ // this infers Foo.type instead of "object Foo" (see also widenIfNecessary) + else + targ.widen - (tparams, tvars, targs).zipped.map{ (tparam, tvar, targ) => - if (targ.typeSymbol == NothingClass && - (restpe.isWildcard || notCovariantIn(tparam, restpe))) { - tparam -> None - } else { - tparam -> Some( - if (targ.typeSymbol == RepeatedParamClass) targ.baseType(SeqClass) - else if (targ.typeSymbol == JavaRepeatedParamClass) targ.baseType(ArrayClass) - else if (targ.typeSymbol.isModuleClass || (opt.experimental && tvar.constr.avoidWiden)) targ // this infers Foo.type instead of "object Foo" (see also widenIfNecessary) - else targ.widen - ) - } + (tparams, tvars, targs).zipped.map { (tparam, tvar, targ) => + tparam -> (if(keep(targ, tparam)) Some(adjusted(targ, tvar)) else None) }(collection.breakOut) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 097def8390..b68b4d708e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -511,8 +511,8 @@ trait Typers extends Modes with Adaptations { private def makeAccessible(tree: Tree, sym: Symbol, pre: Type, site: Tree): (Tree, Type) = if (isInPackageObject(sym, pre.typeSymbol)) { if (pre.typeSymbol == ScalaPackageClass && sym.isTerm) { - // short cut some aliases. It seems that without that pattern matching - // fails to notice exhaustiveness and to generate good code when + // short cut some aliases. It seems pattern matching needs this + // to notice exhaustiveness and to generate good code when // List extractors are mixed with :: patterns. See Test5 in lists.scala. def dealias(sym: Symbol) = (atPos(tree.pos) {gen.mkAttributedRef(sym)}, sym.owner.thisType) diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index 1d3239a176..018cbdefd7 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -111,7 +111,7 @@ object Predef extends LowPriorityImplicits { // Minor variations on identity functions def identity[A](x: A): A = x // @see `conforms` for the implicit version - def implicitly[T](implicit e: T) = e // for summoning implicit values from the nether world + @inline def implicitly[T](implicit e: T) = e // for summoning implicit values from the nether world -- TODO: when dependent method types are on by default, give this result type `e.type`, so that inliner has better chance of knowing which method to inline in calls like `implicitly[MatchingStrategy[Option]].zero` @inline def locally[T](x: T): T = x // to communicate intent and avoid unmoored statements // Apparently needed for the xml library |