diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index d9af3cadfa47..087040665816 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -829,7 +829,7 @@ self => def mkNamed(args: List[Tree]) = if (isExpr) args map treeInfo.assignmentToMaybeNamedArg else args val arguments = right match { case Parens(args) => mkNamed(args) - case _ => List(right) + case _ => right :: Nil } if (isExpr) { if (treeInfo.isLeftAssoc(op)) { diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala index 3d614552ef5f..9cb02d75bf12 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala @@ -613,11 +613,11 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes { annotatedInline = info.annotatedInline, annotatedNoInline = info.annotatedNoInline) if (methodSym.isMixinConstructor) - List((staticMethodSignature, staticMethodInfo)) + (staticMethodSignature, staticMethodInfo) :: Nil else - List((signature, info), (staticMethodSignature, staticMethodInfo)) + (signature, info) :: (staticMethodSignature, staticMethodInfo) :: Nil } else - List((signature, info)) + (signature, info) :: Nil } }).toMap diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index bcfd50974d05..d30e37474b18 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -1089,7 +1089,8 @@ abstract class ClassfileParser { cls setInfo completer mod setInfo completer mod.moduleClass setInfo loaders.moduleClassLoader - List(cls, mod.moduleClass) foreach (_.associatedFile = file) + cls.associatedFile = file + mod.moduleClass.associatedFile = file (cls, mod) } diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 91661aeff13a..992a63de3d2e 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -458,7 +458,7 @@ abstract class Erasure extends InfoTransform class ComputeBridges(unit: CompilationUnit, root: Symbol) { class BridgesCursor(root: Symbol) extends overridingPairs.Cursor(root) { - override def parents = List(root.info.firstParent) + override def parents = root.info.firstParent :: Nil // Varargs bridges may need generic bridges due to the non-repeated part of the signature of the involved methods. // The vararg bridge is generated during refchecks (probably to simplify override checking), // but then the resulting varargs "bridge" method may itself need an actual erasure bridge. @@ -656,7 +656,7 @@ abstract class Erasure extends InfoTransform private def adaptMember(tree: Tree): Tree = { //Console.println("adaptMember: " + tree); tree match { - case Apply(ta @ TypeApply(sel @ Select(qual, name), List(targ)), List()) + case Apply(ta @ TypeApply(sel @ Select(qual, name), targ :: Nil), List()) if tree.symbol == Any_asInstanceOf => val qual1 = typedQualifier(qual, NOmode, ObjectTpe) // need to have an expected type, see #3037 // !!! Make pending/run/t5866b.scala work. The fix might be here and/or in unbox1. diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 1dd661064ab4..8432b9aa9232 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -633,7 +633,7 @@ trait Implicits { val itree2 = if (!isView) fallback else pt match { case Function1(arg1, arg2) => typed1( - atPos(itree0.pos)(Apply(itree1, List(Ident(nme.argument) setType approximate(arg1)))), + atPos(itree0.pos)(Apply(itree1, Ident(nme.argument).setType(approximate(arg1)) :: Nil)), EXPRmode, approximate(arg2) ) match { diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index fd77ce883b6a..f88a883afa93 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1859,7 +1859,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper if (noSerializable) Nil else { clazz.makeSerializable() - List(TypeTree(SerializableTpe) setPos clazz.pos.focus) + TypeTree(SerializableTpe).setPos(clazz.pos.focus) :: Nil } ) }) diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 81abe685d6c8..60a63def6798 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -2323,8 +2323,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => private def matchingSymbolInternal(site: Type, candidate: Symbol): Symbol = { def qualifies(sym: Symbol) = !sym.isTerm || ((site memberType this) matches (site memberType sym)) - //OPT cut down on #closures by special casing non-overloaded case - if (candidate.isOverloaded) candidate filter qualifies + //OPT Fast past for NoSymbol. Cut down on #closures by special casing non-overloaded case + if (candidate == NoSymbol) NoSymbol + else if (candidate.isOverloaded) candidate filter qualifies else if (qualifies(candidate)) candidate else NoSymbol } @@ -2374,15 +2375,16 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** Returns all symbols overridden by this symbol. */ final def allOverriddenSymbols: List[Symbol] = { - def loop(xs: List[Symbol]): List[Symbol] = xs match { - case Nil => Nil + @tailrec + def loop(xs: List[Symbol], result: List[Symbol]): List[Symbol] = xs match { + case Nil => result case x :: xs => overriddenSymbol(x) match { - case NoSymbol => loop(xs) - case sym => sym :: loop(xs) + case NoSymbol => loop(xs, result) + case sym => loop(xs, sym :: result) } } - if (isOverridingSymbol) loop(owner.ancestors) else Nil + if (isOverridingSymbol) loop(owner.ancestors, Nil) else Nil } /** Equivalent to allOverriddenSymbols.nonEmpty, but more efficient. */ diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala index 4a8540274b81..d312582dcbdc 100644 --- a/src/reflect/scala/reflect/internal/TreeGen.scala +++ b/src/reflect/scala/reflect/internal/TreeGen.scala @@ -231,7 +231,10 @@ abstract class TreeGen { val tree = Select(pkgQualifier, sym) if (pkgQualifier.tpe == null) tree - else tree setType (qual.tpe memberType sym) + else tree setType { + if (sym.rawowner == ObjectClass || sym.rawowner == AnyClass) sym.tpeHK.normalize // opt for asInstanceOf + else (qual.tpe memberType sym) + } } } diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index a5750519bdea..66334b16a05d 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -1087,7 +1087,7 @@ trait Types override def baseTypeSeq: BaseTypeSeq = supertype.baseTypeSeq override def baseTypeSeqDepth: Depth = supertype.baseTypeSeqDepth override def baseClasses: List[Symbol] = supertype.baseClasses - } + override def boundSyms: Set[Symbol] = emptySymbolSet} /** A base class for types that represent a single value * (single-types and this-types). @@ -2129,15 +2129,27 @@ trait Types //OPT specialize hashCode override final def computeHashCode = { import scala.util.hashing.MurmurHash3._ - val hasArgs = args ne Nil var h = productSeed h = mix(h, pre.hashCode) h = mix(h, sym.hashCode) - if (hasArgs) - finalizeHash(mix(h, args.hashCode()), 3) - else - finalizeHash(h, 2) + var length = 2 + var elems = args + while (elems ne Nil) { + h = mix(h, elems.head.hashCode()) + elems = elems.tail + length += 1 + } + finalizeHash(h, length) } + //OPT specialize equals + override final def equals(other: Any): Boolean = { + other match { + case otherTypeRef: TypeRef => + pre.equals(otherTypeRef.pre) && sym.eq(otherTypeRef.sym) && sameElementsEquals(args, otherTypeRef.args) + case _ => false + } + } + // interpret symbol's info in terms of the type's prefix and type args protected def relativeInfo: Type = appliedType(sym.info.asSeenFrom(pre, sym.owner), argsOrDummies) @@ -3605,7 +3617,10 @@ trait Types if (sym.isAliasType && sameLength(sym.info.typeParams, args) && !sym.lockOK) throw new RecoverableCyclicReference(sym) - TypeRef(pre, sym, args) + if ((args eq Nil) && (pre eq NoPrefix)) + sym.tpeHK // opt lean on TypeSymbol#tyconCache, rather than interning a type ref. + else + TypeRef(pre, sym, args) case _ => typeRef(pre, sym, args) } @@ -3786,7 +3801,7 @@ trait Types private var uniques: util.WeakHashSet[Type] = _ private var uniqueRunId = NoRunId - protected def unique[T <: Type](tp: T): T = { + protected def unique[T <: Type](tp: T): T = { if (Statistics.canEnable) Statistics.incCounter(rawTypeCount) if (uniqueRunId != currentRunId) { uniques = util.WeakHashSet[Type](initialUniquesCapacity) @@ -3901,7 +3916,7 @@ trait Types && isRawIfWithoutArgs(sym) ) - def singletonBounds(hi: Type) = TypeBounds.upper(intersectionType(List(hi, SingletonClass.tpe))) + def singletonBounds(hi: Type) = TypeBounds.upper(intersectionType(hi :: SingletonClass.tpe :: Nil)) /** * A more persistent version of `Type#memberType` which does not require @@ -4241,38 +4256,44 @@ trait Types */ protected[internal] def specializesSym(preLo: Type, symLo: Symbol, preHi: Type, symHi: Symbol, depth: Depth): Boolean = (symHi.isAliasType || symHi.isTerm || symHi.isAbstractType) && { - // only now that we know symHi is a viable candidate ^^^^^^^, do the expensive checks: ----V - require((symLo ne NoSymbol) && (symHi ne NoSymbol), ((preLo, symLo, preHi, symHi, depth))) - - val tpHi = preHi.memberInfo(symHi).substThis(preHi.typeSymbol, preLo) - - // Should we use memberType or memberInfo? - // memberType transforms (using `asSeenFrom`) `sym.tpe`, - // whereas memberInfo performs the same transform on `sym.info`. - // For term symbols, this ends up being the same thing (`sym.tpe == sym.info`). - // For type symbols, however, the `.info` of an abstract type member - // is defined by its bounds, whereas its `.tpe` is a `TypeRef` to that type symbol, - // so that `sym.tpe <:< sym.info`, but not the other way around. - // - // Thus, for the strongest (correct) result, - // we should use `memberType` on the low side. - // - // On the high side, we should use the result appropriate - // for the right side of the `<:<` above (`memberInfo`). - val tpLo = preLo.memberType(symLo) - - debuglog(s"specializesSymHi: $preHi . $symHi : $tpHi") - debuglog(s"specializesSymLo: $preLo . $symLo : $tpLo") - - if (symHi.isTerm) - (isSubType(tpLo, tpHi, depth) && - (!symHi.isStable || symLo.isStable) && // sub-member must remain stable - (!symLo.hasVolatileType || symHi.hasVolatileType || tpHi.isWildcard)) // sub-member must not introduce volatility - else if (symHi.isAbstractType) - ((tpHi.bounds containsType tpLo) && - kindsConform(symHi :: Nil, tpLo :: Nil, preLo, symLo.owner)) - else // we know `symHi.isAliasType` (see above) - tpLo =:= tpHi + val symHiInfo = symHi.info + if (symHi.isTerm && symHiInfo == WildcardType) { + // OPT fast path (avoiding tpLo.mmeberType) for wildcards which appear here frequently in the search for implicit views. + !symHi.isStable || symLo.isStable // sub-member must remain stable + } else { + // only now that we know symHi is a viable candidate, do the expensive checks: ----V + require((symLo ne NoSymbol) && (symHi ne NoSymbol), ((preLo, symLo, preHi, symHi, depth))) + + val tpHi = symHiInfo.asSeenFrom(preHi, symHi.owner).substThis(preHi.typeSymbol, preLo) + + // Should we use memberType or memberInfo? + // memberType transforms (using `asSeenFrom`) `sym.tpe`, + // whereas memberInfo performs the same transform on `sym.info`. + // For term symbols, this ends up being the same thing (`sym.tpe == sym.info`). + // For type symbols, however, the `.info` of an abstract type member + // is defined by its bounds, whereas its `.tpe` is a `TypeRef` to that type symbol, + // so that `sym.tpe <:< sym.info`, but not the other way around. + // + // Thus, for the strongest (correct) result, + // we should use `memberType` on the low side. + // + // On the high side, we should use the result appropriate + // for the right side of the `<:<` above (`memberInfo`). + val tpLo = preLo.memberType(symLo) + + debuglog(s"specializesSymHi: $preHi . $symHi : $tpHi") + debuglog(s"specializesSymLo: $preLo . $symLo : $tpLo") + + if (symHi.isTerm) + (isSubType(tpLo, tpHi, depth) && + (!symHi.isStable || symLo.isStable) && // sub-member must remain stable + (!symLo.hasVolatileType || symHi.hasVolatileType || tpHi.isWildcard)) // sub-member must not introduce volatility + else if (symHi.isAbstractType) + ((tpHi.bounds containsType tpLo) && + kindsConform(symHi :: Nil, tpLo :: Nil, preLo, symLo.owner)) + else // we know `symHi.isAliasType` (see above) + tpLo =:= tpHi + } } /** A function implementing `tp1` matches `tp2`. */ diff --git a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala index 7e1db292132b..93edab99b6a8 100644 --- a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala +++ b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala @@ -184,8 +184,7 @@ private[internal] trait GlbLubs { /** Eliminate from list of types all elements which are a supertype * of some other element of the list. */ private def elimSuper(ts: List[Type]): List[Type] = ts match { - case List() => List() - case List(t) => List(t) + case List() | List(_) => ts case t :: ts1 => val rest = elimSuper(ts1 filter (t1 => !(t <:< t1))) if (rest exists (t1 => t1 <:< t)) rest else t :: rest @@ -195,8 +194,8 @@ private[internal] trait GlbLubs { * of some other element of the list. */ private def elimSub(ts: List[Type], depth: Depth): List[Type] = { def elimSub0(ts: List[Type]): List[Type] = ts match { - case List() => List() - case List(t) => List(t) + case List() => ts + case List(t) => ts case t :: ts1 => val rest = elimSub0(ts1 filter (t1 => !isSubType(t1, t, depth.decr))) if (rest exists (t1 => isSubType(t, t1, depth.decr))) rest else t :: rest diff --git a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala index 61f6d89b19c6..37d05c08a7c2 100644 --- a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala +++ b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala @@ -124,9 +124,9 @@ trait TypeComparers { // combination of { tp1, tp2 } { is, is not } an AnnotatedType - this because the // logic of "annotationsConform" is arbitrary and unknown. private def isSameType1(tp1: Type, tp2: Type): Boolean = typeRelationPreCheck(tp1, tp2) match { - case state if state.isKnown => state.booleanValue - case _ if typeHasAnnotations(tp1) || typeHasAnnotations(tp2) => sameAnnotatedTypes(tp1, tp2) - case _ => isSameType2(tp1, tp2) + case state if state.isKnown => state.booleanValue + case _ if tp1.isInstanceOf[AnnotatedType] || tp2.isInstanceOf[AnnotatedType] => sameAnnotatedTypes(tp1, tp2) + case _ => isSameType2(tp1, tp2) } private def isSameHKTypes(tp1: Type, tp2: Type) = ( @@ -325,9 +325,9 @@ trait TypeComparers { } private def isSubType1(tp1: Type, tp2: Type, depth: Depth): Boolean = typeRelationPreCheck(tp1, tp2) match { - case state if state.isKnown => state.booleanValue - case _ if typeHasAnnotations(tp1) || typeHasAnnotations(tp2) => annotationsConform(tp1, tp2) && (tp1.withoutAnnotations <:< tp2.withoutAnnotations) - case _ => isSubType2(tp1, tp2, depth) + case state if state.isKnown => state.booleanValue + case _ if tp1.isInstanceOf[AnnotatedType] || tp2.isInstanceOf[AnnotatedType] => annotationsConform(tp1, tp2) && (tp1.withoutAnnotations <:< tp2.withoutAnnotations) + case _ => isSubType2(tp1, tp2, depth) } private def isPolySubType(tp1: PolyType, tp2: PolyType): Boolean = { diff --git a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala index d997a4db4dd4..bf0220e168e3 100644 --- a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala +++ b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala @@ -101,11 +101,16 @@ private[internal] trait TypeMaps { case tr @ TypeRef(pre, sym, args) => val pre1 = this(pre) val args1 = ( - if (trackVariance && args.nonEmpty && !variance.isInvariant && sym.typeParams.nonEmpty) - mapOverArgs(args, sym.typeParams) - else + if (trackVariance && args.nonEmpty && !variance.isInvariant) { + val tparams = sym.typeParams + if (tparams.isEmpty) + args mapConserve this + else + mapOverArgs(args, tparams) + } else { args mapConserve this - ) + } + ) if ((pre1 eq pre) && (args1 eq args)) tp else copyTypeRef(tp, pre1, tr.coevolveSym(pre1), args1) case ThisType(_) => tp diff --git a/src/reflect/scala/reflect/internal/util/Collections.scala b/src/reflect/scala/reflect/internal/util/Collections.scala index a743d8962afa..821f19095e73 100644 --- a/src/reflect/scala/reflect/internal/util/Collections.scala +++ b/src/reflect/scala/reflect/internal/util/Collections.scala @@ -61,6 +61,19 @@ trait Collections { head } + final def sameElementsEquals(thiss: List[AnyRef], that: List[AnyRef]): Boolean = { + // Probably immutable, so check reference identity first (it's quick anyway) + (thiss eq that) || { + var these = thiss + var those = that + while (!these.isEmpty && !those.isEmpty && these.head.equals(those.head)) { + these = these.tail + those = those.tail + } + these.isEmpty && those.isEmpty + } + } + final def collectFirst[A, B](as: List[A])(pf: PartialFunction[A, B]): Option[B] = { @tailrec def loop(rest: List[A]): Option[B] = rest match { diff --git a/src/reflect/scala/reflect/internal/util/WeakHashSet.scala b/src/reflect/scala/reflect/internal/util/WeakHashSet.scala index 412b14d3291a..422a43a365d5 100644 --- a/src/reflect/scala/reflect/internal/util/WeakHashSet.scala +++ b/src/reflect/scala/reflect/internal/util/WeakHashSet.scala @@ -156,7 +156,7 @@ final class WeakHashSet[A <: AnyRef](val initialCapacity: Int, val loadFactor: D case null => null.asInstanceOf[A] case _ => { val entryElem = entry.get - if (elem == entryElem) entryElem + if (elem.equals(entryElem)) entryElem else linkedListLoop(entry.tail) } } @@ -185,7 +185,7 @@ final class WeakHashSet[A <: AnyRef](val initialCapacity: Int, val loadFactor: D case null => add() case _ => { val entryElem = entry.get - if (elem == entryElem) entryElem + if (elem.equals(entryElem)) entryElem else linkedListLoop(entry.tail) } } @@ -211,9 +211,9 @@ final class WeakHashSet[A <: AnyRef](val initialCapacity: Int, val loadFactor: D @tailrec def linkedListLoop(entry: Entry[A]): Unit = entry match { - case null => add() - case _ if (elem == entry.get) => () - case _ => linkedListLoop(entry.tail) + case null => add() + case _ if elem.equals(entry.get) => () + case _ => linkedListLoop(entry.tail) } linkedListLoop(oldHead) @@ -238,7 +238,7 @@ final class WeakHashSet[A <: AnyRef](val initialCapacity: Int, val loadFactor: D @tailrec def linkedListLoop(prevEntry: Entry[A], entry: Entry[A]): Unit = entry match { case null => () - case _ if (elem == entry.get) => remove(bucket, prevEntry, entry) + case _ if elem.equals(entry.get) => remove(bucket, prevEntry, entry) case _ => linkedListLoop(entry, entry.tail) }