From 5df51cc5a6ead1f9d68d1e988cda3a1698daf708 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Fri, 4 Nov 2011 05:54:01 +0000 Subject: Some modest optimizations and beauty treatments. No review. --- src/compiler/scala/reflect/internal/Symbols.scala | 17 ++-- src/compiler/scala/reflect/internal/Trees.scala | 1 - src/compiler/scala/reflect/internal/Types.scala | 51 ++++++------ .../scala/tools/nsc/typechecker/Implicits.scala | 2 +- .../scala/tools/nsc/typechecker/Typers.scala | 91 +++++++++++----------- 5 files changed, 79 insertions(+), 83 deletions(-) (limited to 'src') diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala index e848f0eeda..fc3fea0fd4 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/scala/reflect/internal/Symbols.scala @@ -2426,17 +2426,16 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def originalEnclosingMethod = this } - def cloneSymbols[T <: Symbol](syms: List[T]): List[T] = { - val syms1 = syms map (_.cloneSymbol.asInstanceOf[T]) - for (sym1 <- syms1) sym1.setInfo(sym1.info.substSym(syms, syms1)) - syms1 + private def cloneAndSubstInfos[T <: Symbol](syms: List[T])(f: T => Symbol): List[T] = { + val syms1 = syms map (s => f(s).asInstanceOf[T]) + syms1 map (sym1 => sym1 setInfo sym1.info.substSym(syms, syms1)) } - def cloneSymbols[T <: Symbol](syms: List[T], owner: Symbol): List[T] = { - val syms1 = syms map (_.cloneSymbol(owner).asInstanceOf[T]) - for (sym1 <- syms1) sym1.setInfo(sym1.info.substSym(syms, syms1)) - syms1 - } + def cloneSymbols[T <: Symbol](syms: List[T]): List[T] = + cloneAndSubstInfos(syms)(_.cloneSymbol) + + def cloneSymbols[T <: Symbol](syms: List[T], owner: Symbol): List[T] = + cloneAndSubstInfos(syms)(_ cloneSymbol owner) /** An exception for cyclic references of symbol definitions */ case class CyclicReference(sym: Symbol, info: Type) diff --git a/src/compiler/scala/reflect/internal/Trees.scala b/src/compiler/scala/reflect/internal/Trees.scala index 75b012f72e..3adba8b66d 100644 --- a/src/compiler/scala/reflect/internal/Trees.scala +++ b/src/compiler/scala/reflect/internal/Trees.scala @@ -340,7 +340,6 @@ trait Trees extends api.Trees { self: SymbolTable => class TreeTypeSubstituter(val from: List[Symbol], val to: List[Type]) extends Traverser { val typeSubst = new SubstTypeMap(from, to) - def fromContains = typeSubst.fromContains def isEmpty = from.isEmpty && to.isEmpty override def traverse(tree: Tree) { diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala index c542c818c1..6fef545602 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/compiler/scala/reflect/internal/Types.scala @@ -2100,7 +2100,7 @@ A type's typeSymbol should never be inspected directly. override def paramTypes = params map (_.tpe) - override def boundSyms = immutable.Set[Symbol](params ++ resultType.boundSyms: _*) + override def boundSyms = resultType.boundSyms ++ params override def resultType(actuals: List[Type]) = if (isTrivial || phase.erasedTypes) resultType @@ -3480,15 +3480,10 @@ A type's typeSymbol should never be inspected directly. variance = v result ne sym.info } - if (!change) origSyms // fast path in case nothing changes due to map - else { // map is not the identity --> do cloning properly - val clonedSyms = origSyms map (_.cloneSymbol) - val clonedInfos = clonedSyms map (_.info.substSym(origSyms, clonedSyms)) - val transformedInfos = clonedInfos mapConserve (this) - - (clonedSyms, transformedInfos).zipped foreach (_ setInfo _) - clonedSyms - } + // map is not the identity --> do cloning properly + if (change) cloneSymbols(origSyms) map (s => s setInfo this(s.info)) + // fast path in case nothing changes due to map + else origSyms } def mapOver(annot: AnnotationInfo): AnnotationInfo = { @@ -3776,7 +3771,6 @@ A type's typeSymbol should never be inspected directly. /** A base class to compute all substitutions */ abstract class SubstMap[T](from: List[Symbol], to: List[T]) extends TypeMap { - val fromContains = (x: Symbol) => from.contains(x) //from.toSet <-- traversing short lists seems to be faster than allocating sets assert(sameLength(from, to), "Unsound substitution from "+ from +" to "+ to) /** Are `sym` and `sym1` the same? Can be tuned by subclasses. */ @@ -3807,7 +3801,7 @@ A type's typeSymbol should never be inspected directly. else subst(tp, sym, from.tail, to.tail) val boundSyms = tp0.boundSyms - val tp1 = if (boundSyms exists fromContains) renameBoundSyms(tp0) else tp0 + val tp1 = if (boundSyms exists from.contains) renameBoundSyms(tp0) else tp0 val tp = mapOver(tp1) tp match { @@ -3859,11 +3853,10 @@ A type's typeSymbol should never be inspected directly. override def mapOver(tree: Tree, giveup: ()=>Nothing): Tree = { object trans extends TypeMapTransformer { - def termMapsTo(sym: Symbol) = - if (fromContains(sym)) - Some(to(from.indexOf(sym))) - else - None + def termMapsTo(sym: Symbol) = from indexOf sym match { + case -1 => None + case idx => Some(to(idx)) + } override def transform(tree: Tree) = tree match { @@ -3892,21 +3885,23 @@ A type's typeSymbol should never be inspected directly. extends SubstMap(from, to) { protected def toType(fromtp: Type, tp: Type) = tp - override def mapOver(tree: Tree, giveup: ()=>Nothing): Tree = { + override def mapOver(tree: Tree, giveup: () => Nothing): Tree = { object trans extends TypeMapTransformer { - override def transform(tree: Tree) = - tree match { - case Ident(name) if fromContains(tree.symbol) => - val totpe = to(from.indexOf(tree.symbol)) - if (!totpe.isStable) giveup() - else Ident(name).setPos(tree.pos).setSymbol(tree.symbol).setType(totpe) - - case _ => super.transform(tree) - } + override def transform(tree: Tree) = tree match { + case Ident(name) => + from indexOf tree.symbol match { + case -1 => super.transform(tree) + case idx => + val totpe = to(idx) + if (totpe.isStable) tree.duplicate setType totpe + else giveup() + } + case _ => + super.transform(tree) + } } trans.transform(tree) } - } /** A map to implement the `substThis` method. */ diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index fedf0a9104..75535968fd 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -66,7 +66,7 @@ trait Implicits { val result = new ImplicitSearch(tree, pt, isView, context.makeImplicit(reportAmbiguous)).bestImplicit printInference("[inferImplicit] result: " + result) - context.undetparams = context.undetparams filterNot result.subst.fromContains + context.undetparams = context.undetparams filterNot result.subst.from.contains stopTimer(implicitNanos, start) stopCounter(rawTypeImpl, rawTypeStart) diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 9a1062432a..ad71f8c21a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1027,30 +1027,39 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } } + private def isAdaptableWithView(qual: Tree) = { + val qtpe = qual.tpe.widen + ( !isPastTyper + && qual.isTerm + && ((qual.symbol eq null) || !qual.symbol.isTerm || qual.symbol.isValue) + && !qtpe.isError + && qtpe.typeSymbol != NullClass + && qtpe.typeSymbol != NothingClass + && qtpe != WildcardType + && !qual.isInstanceOf[ApplyImplicitView] // don't chain views + && context.implicitsEnabled + // Elaborating `context.implicitsEnabled`: + // don't try to adapt a top-level type that's the subject of an implicit search + // this happens because, if isView, typedImplicit tries to apply the "current" implicit value to + // a value that needs to be coerced, so we check whether the implicit value has an `apply` method. + // (If we allow this, we get divergence, e.g., starting at `conforms` during ant quick.bin) + // Note: implicit arguments are still inferred (this kind of "chaining" is allowed) + ) + } + def adaptToMember(qual: Tree, searchTemplate: Type): Tree = { - var qtpe = qual.tpe.widen - if (qual.isTerm && - ((qual.symbol eq null) || !qual.symbol.isTerm || qual.symbol.isValue) && - !isPastTyper && !qtpe.isError && - qtpe.typeSymbol != NullClass && qtpe.typeSymbol != NothingClass && qtpe != WildcardType && - !qual.isInstanceOf[ApplyImplicitView] && // don't chain views - context.implicitsEnabled) { // don't try to adapt a top-level type that's the subject of an implicit search - // this happens because, if isView, typedImplicit tries to apply the "current" implicit value to - // a value that needs to be coerced, so we check whether the implicit value has an `apply` method - // (if we allow this, we get divergence, e.g., starting at `conforms` during ant quick.bin) - // note: implicit arguments are still inferred (this kind of "chaining" is allowed) - if (qtpe.normalize.isInstanceOf[ExistentialType]) { - qtpe = qtpe.normalize.skolemizeExistential(context.owner, qual) // open the existential - qual setType qtpe + if (isAdaptableWithView(qual)) { + qual.tpe.widen.normalize match { + case et: ExistentialType => + qual setType et.skolemizeExistential(context.owner, qual) // open the existential + case _ => + } + inferView(qual, qual.tpe, searchTemplate, true) match { + case EmptyTree => qual + case coercion => typedQualifier(atPos(qual.pos)(new ApplyImplicitView(coercion, List(qual)))) } - val coercion = inferView(qual, qual.tpe, searchTemplate, true) - if (coercion != EmptyTree) - typedQualifier(atPos(qual.pos)(new ApplyImplicitView(coercion, List(qual)))) - else - qual - } else { - qual } + else qual } /** Try to apply an implicit conversion to `qual` to that it contains @@ -1569,29 +1578,24 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { if (!superClazz.isJavaDefined) { val superParamAccessors = superClazz.constrParamAccessors if (sameLength(superParamAccessors, superArgs)) { - (superParamAccessors, superArgs).zipped map { (superAcc, superArg) => - superArg match { - case Ident(name) => - if (vparamss.exists(_.exists(_.symbol == superArg.symbol))) { - var alias = superAcc.initialize.alias - if (alias == NoSymbol) - alias = superAcc.getter(superAcc.owner) - if (alias != NoSymbol && - superClazz.info.nonPrivateMember(alias.name) != alias) - alias = NoSymbol - if (alias != NoSymbol) { - var ownAcc = clazz.info.decl(name).suchThat(_.isParamAccessor) - if ((ownAcc hasFlag ACCESSOR) && !ownAcc.isDeferred) - ownAcc = ownAcc.accessed - if (!ownAcc.isVariable && !alias.accessed.isVariable) { - debuglog("" + ownAcc + " has alias "+alias + alias.locationString) //debug - ownAcc.asInstanceOf[TermSymbol].setAlias(alias) - } - } + for ((superAcc, superArg @ Ident(name)) <- superParamAccessors zip superArgs) { + if (vparamss.exists(_.exists(_.symbol == superArg.symbol))) { + var alias = superAcc.initialize.alias + if (alias == NoSymbol) + alias = superAcc.getter(superAcc.owner) + if (alias != NoSymbol && + superClazz.info.nonPrivateMember(alias.name) != alias) + alias = NoSymbol + if (alias != NoSymbol) { + var ownAcc = clazz.info.decl(name).suchThat(_.isParamAccessor) + if ((ownAcc hasFlag ACCESSOR) && !ownAcc.isDeferred) + ownAcc = ownAcc.accessed + if (!ownAcc.isVariable && !alias.accessed.isVariable) { + debuglog("" + ownAcc + " has alias "+alias.fullLocationString) //debug + ownAcc.asInstanceOf[TermSymbol].setAlias(alias) } - case _ => + } } - () } } } @@ -1601,7 +1605,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { /** Check if a structurally defined method violates implementation restrictions. * A method cannot be called if it is a non-private member of a refinement type * and if its parameter's types are any of: - * - this.type + * - the self-type of the refinement * - a type member of the refinement * - an abstract type declared outside of the refinement. */ @@ -1730,7 +1734,6 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } } } - if (meth.isStructuralRefinementMember) checkMethodStructuralCompatible(meth) -- cgit v1.2.3