summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-10-02 08:03:17 -0700
committerPaul Phillips <paulp@improving.org>2012-10-02 09:50:42 -0700
commit609b3b8b740447b212f0ee04c1e52d8c72b8dfc8 (patch)
tree8c21786f237aaad82a6d5a9c8efd14fe326d5ca6
parent68a3a1d73f7b82203edc9eb6314a9923010c2b7e (diff)
downloadscala-609b3b8b740447b212f0ee04c1e52d8c72b8dfc8.tar.gz
scala-609b3b8b740447b212f0ee04c1e52d8c72b8dfc8.tar.bz2
scala-609b3b8b740447b212f0ee04c1e52d8c72b8dfc8.zip
Hardening in appliedType and Subst*Map.
All driven by the knowledge gained from logging all the calls to tpe and appliedType and seeing what was coming through there. Some needless type creation is avoided in the maps, and appliedType will squawk to those who listen when it sees something out of order.
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala61
1 files changed, 35 insertions, 26 deletions
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 876ae53da0..e80cf6fde6 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -3603,16 +3603,16 @@ trait Types extends api.Types { self: SymbolTable =>
if (args.isEmpty) tycon //@M! `if (args.isEmpty) tycon' is crucial (otherwise we create new types in phases after typer and then they don't get adapted (??))
else tycon match {
case TypeRef(pre, sym @ (NothingClass|AnyClass), _) => copyTypeRef(tycon, pre, sym, Nil) //@M drop type args to Any/Nothing
- case TypeRef(pre, sym, _) => copyTypeRef(tycon, pre, sym, args)
+ case TypeRef(pre, sym, Nil) => copyTypeRef(tycon, pre, sym, args)
+ case TypeRef(pre, sym, bogons) => debugwarn(s"Dropping $bogons from $tycon in appliedType.") ; copyTypeRef(tycon, pre, sym, args)
case PolyType(tparams, restpe) => restpe.instantiateTypeParams(tparams, args)
case ExistentialType(tparams, restpe) => newExistentialType(tparams, appliedType(restpe, args))
case st: SingletonType => appliedType(st.widen, args) // @M TODO: what to do? see bug1
- case RefinedType(parents, decls) => RefinedType(parents map (appliedType(_, args)), decls) // MO to AM: please check
- case TypeBounds(lo, hi) => TypeBounds(appliedType(lo, args), appliedType(hi, args))
+ case RefinedType(parents, decls) => RefinedType(parents map (appliedType(_, args)), decls) // @PP: Can this be right?
+ case TypeBounds(lo, hi) => TypeBounds(appliedType(lo, args), appliedType(hi, args)) // @PP: Can this be right?
case tv@TypeVar(_, _) => tv.applyArgs(args)
case AnnotatedType(annots, underlying, self) => AnnotatedType(annots, appliedType(underlying, args), self)
- case ErrorType => tycon
- case WildcardType => tycon // needed for neg/t0226
+ case ErrorType | WildcardType => tycon
case _ => abort(debugString(tycon))
}
@@ -4513,16 +4513,18 @@ trait Types extends api.Types { self: SymbolTable =>
tp
}
- def apply(tp0: Type): Type = if (from.isEmpty) tp0 else {
- @tailrec def subst(tp: Type, sym: Symbol, from: List[Symbol], to: List[T]): Type =
- if (from.isEmpty) tp
- // else if (to.isEmpty) error("Unexpected substitution on '%s': from = %s but to == Nil".format(tp, from))
- else if (matches(from.head, sym)) toType(tp, to.head)
- else subst(tp, sym, from.tail, to.tail)
+ @tailrec private def subst(tp: Type, sym: Symbol, from: List[Symbol], to: List[T]): Type = (
+ if (from.isEmpty) tp
+ // else if (to.isEmpty) error("Unexpected substitution on '%s': from = %s but to == Nil".format(tp, from))
+ else if (matches(from.head, sym)) toType(tp, to.head)
+ else subst(tp, sym, from.tail, to.tail)
+ )
- val boundSyms = tp0.boundSyms
- val tp1 = if (boundSyms.nonEmpty && (boundSyms exists from.contains)) renameBoundSyms(tp0) else tp0
- val tp = mapOver(tp1)
+ def apply(tp0: Type): Type = if (from.isEmpty) tp0 else {
+ val boundSyms = tp0.boundSyms
+ val tp1 = if (boundSyms.nonEmpty && (boundSyms exists from.contains)) renameBoundSyms(tp0) else tp0
+ val tp = mapOver(tp1)
+ def substFor(sym: Symbol) = subst(tp, sym, from, to)
tp match {
// @M
@@ -4537,9 +4539,11 @@ trait Types extends api.Types { self: SymbolTable =>
// (must not recurse --> loops)
// 3) replacing m by List in m[Int] should yield List[Int], not just List
case TypeRef(NoPrefix, sym, args) =>
- appliedType(subst(tp, sym, from, to), args) // if args.isEmpty, appliedType is the identity
+ val tcon = substFor(sym)
+ if ((tp eq tcon) || args.isEmpty) tcon
+ else appliedType(tcon.typeConstructor, args)
case SingleType(NoPrefix, sym) =>
- subst(tp, sym, from, to)
+ substFor(sym)
case _ =>
tp
}
@@ -4554,25 +4558,29 @@ trait Types extends api.Types { self: SymbolTable =>
case TypeRef(pre, _, args) => copyTypeRef(fromtp, pre, sym, args)
case SingleType(pre, _) => singleType(pre, sym)
}
- override def apply(tp: Type): Type = if (from.isEmpty) tp else {
- @tailrec def subst(sym: Symbol, from: List[Symbol], to: List[Symbol]): Symbol =
- if (from.isEmpty) sym
- // else if (to.isEmpty) error("Unexpected substitution on '%s': from = %s but to == Nil".format(sym, from))
- else if (matches(from.head, sym)) to.head
- else subst(sym, from.tail, to.tail)
- tp match {
+ @tailrec private def subst(sym: Symbol, from: List[Symbol], to: List[Symbol]): Symbol = (
+ if (from.isEmpty) sym
+ // else if (to.isEmpty) error("Unexpected substitution on '%s': from = %s but to == Nil".format(sym, from))
+ else if (matches(from.head, sym)) to.head
+ else subst(sym, from.tail, to.tail)
+ )
+ private def substFor(sym: Symbol) = subst(sym, from, to)
+
+ override def apply(tp: Type): Type = (
+ if (from.isEmpty) tp
+ else tp match {
case TypeRef(pre, sym, args) if pre ne NoPrefix =>
- val newSym = subst(sym, from, to)
+ val newSym = substFor(sym)
// mapOver takes care of subst'ing in args
mapOver ( if (sym eq newSym) tp else copyTypeRef(tp, pre, newSym, args) )
// assert(newSym.typeParams.length == sym.typeParams.length, "typars mismatch in SubstSymMap: "+(sym, sym.typeParams, newSym, newSym.typeParams))
case SingleType(pre, sym) if pre ne NoPrefix =>
- val newSym = subst(sym, from, to)
+ val newSym = substFor(sym)
mapOver( if (sym eq newSym) tp else singleType(pre, newSym) )
case _ =>
super.apply(tp)
}
- }
+ )
override def mapOver(tree: Tree, giveup: ()=>Nothing): Tree = {
object trans extends TypeMapTransformer {
@@ -5955,6 +5963,7 @@ trait Types extends api.Types { self: SymbolTable =>
* than member `sym2` of `tp2`?
*/
private def specializesSym(tp1: Type, sym1: Symbol, tp2: Type, sym2: Symbol, depth: Int): Boolean = {
+ require((sym1 ne NoSymbol) && (sym2 ne NoSymbol), ((tp1, sym1, tp2, sym2, depth)))
val info1 = tp1.memberInfo(sym1)
val info2 = tp2.memberInfo(sym2).substThis(tp2.typeSymbol, tp1)
//System.out.println("specializes "+tp1+"."+sym1+":"+info1+sym1.locationString+" AND "+tp2+"."+sym2+":"+info2)//DEBUG