summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala17
-rw-r--r--src/compiler/scala/reflect/internal/Trees.scala1
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala51
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala91
5 files changed, 79 insertions, 83 deletions
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)