diff options
Diffstat (limited to 'src/compiler')
35 files changed, 139 insertions, 123 deletions
diff --git a/src/compiler/scala/reflect/macros/compiler/DefaultMacroCompiler.scala b/src/compiler/scala/reflect/macros/compiler/DefaultMacroCompiler.scala index a13a778b2f..b8384851da 100644 --- a/src/compiler/scala/reflect/macros/compiler/DefaultMacroCompiler.scala +++ b/src/compiler/scala/reflect/macros/compiler/DefaultMacroCompiler.scala @@ -12,7 +12,7 @@ abstract class DefaultMacroCompiler extends Resolvers import treeInfo._ import definitions._ val runDefinitions = currentRun.runDefinitions - import runDefinitions.{Predef_???, _} + import runDefinitions.Predef_??? val typer: global.analyzer.Typer val context = typer.context diff --git a/src/compiler/scala/reflect/macros/compiler/Errors.scala b/src/compiler/scala/reflect/macros/compiler/Errors.scala index cc4508e696..98fd091e9c 100644 --- a/src/compiler/scala/reflect/macros/compiler/Errors.scala +++ b/src/compiler/scala/reflect/macros/compiler/Errors.scala @@ -11,7 +11,6 @@ trait Errors extends Traces { import analyzer._ import definitions._ import treeInfo._ - import typer.TyperErrorGen._ import typer.infer.InferErrorGen._ import runDefinitions._ def globalSettings = global.settings diff --git a/src/compiler/scala/reflect/macros/compiler/Resolvers.scala b/src/compiler/scala/reflect/macros/compiler/Resolvers.scala index 4484c234aa..d3f49390ea 100644 --- a/src/compiler/scala/reflect/macros/compiler/Resolvers.scala +++ b/src/compiler/scala/reflect/macros/compiler/Resolvers.scala @@ -1,18 +1,12 @@ package scala.reflect.macros package compiler -import scala.reflect.internal.Flags._ -import scala.reflect.macros.TypecheckException - trait Resolvers { self: DefaultMacroCompiler => import global._ import analyzer._ - import definitions._ import treeInfo._ - import gen._ - import runDefinitions._ trait Resolver { self: MacroImplRefCompiler => diff --git a/src/compiler/scala/reflect/macros/compiler/Validators.scala b/src/compiler/scala/reflect/macros/compiler/Validators.scala index a146818ae3..fc932f2b18 100644 --- a/src/compiler/scala/reflect/macros/compiler/Validators.scala +++ b/src/compiler/scala/reflect/macros/compiler/Validators.scala @@ -9,7 +9,7 @@ trait Validators { import global._ import analyzer._ import definitions._ - import runDefinitions.{Predef_???, _} + import runDefinitions.Predef_??? trait Validator { self: MacroImplRefCompiler => diff --git a/src/compiler/scala/reflect/macros/util/Helpers.scala b/src/compiler/scala/reflect/macros/util/Helpers.scala index bddc42d1f9..961c41dab5 100644 --- a/src/compiler/scala/reflect/macros/util/Helpers.scala +++ b/src/compiler/scala/reflect/macros/util/Helpers.scala @@ -54,14 +54,10 @@ trait Helpers { * * @see Metalevels.scala for more information and examples about metalevels */ - def increaseMetalevel(pre: Type, tp: Type): Type = { - val runDefinitions = currentRun.runDefinitions - import runDefinitions._ - + def increaseMetalevel(pre: Type, tp: Type): Type = transparentShallowTransform(RepeatedParamClass, tp) { case tp => typeRef(pre, MacroContextExprClass, List(tp)) } - } /** Transforms c.Expr[T] types into c.Tree and leaves the rest unchanged. */ diff --git a/src/compiler/scala/reflect/quasiquotes/Parsers.scala b/src/compiler/scala/reflect/quasiquotes/Parsers.scala index 007bac27da..97ec7dbfc3 100644 --- a/src/compiler/scala/reflect/quasiquotes/Parsers.scala +++ b/src/compiler/scala/reflect/quasiquotes/Parsers.scala @@ -90,7 +90,7 @@ trait Parsers { self: Quasiquotes => case _ => super.makePatDef(mods, pat, rhs) } } - import treeBuilder.{global => _, unit => _, _} + import treeBuilder.{global => _, unit => _} // q"def foo($x)" override def param(owner: Name, implicitmod: Int, caseParam: Boolean): ValDef = diff --git a/src/compiler/scala/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/reflect/quasiquotes/Reifiers.scala index 07becdc3c6..cc98717c4e 100644 --- a/src/compiler/scala/reflect/quasiquotes/Reifiers.scala +++ b/src/compiler/scala/reflect/quasiquotes/Reifiers.scala @@ -8,7 +8,6 @@ import scala.reflect.internal.Flags._ trait Reifiers { self: Quasiquotes => import global._ import global.build._ - import global.treeInfo._ import global.definitions._ import Rank._ import universeTypes._ diff --git a/src/compiler/scala/reflect/reify/Reifier.scala b/src/compiler/scala/reflect/reify/Reifier.scala index b1cc797389..a3e0f02dcc 100644 --- a/src/compiler/scala/reflect/reify/Reifier.scala +++ b/src/compiler/scala/reflect/reify/Reifier.scala @@ -21,7 +21,6 @@ abstract class Reifier extends States import global._ import definitions._ private val runDefinitions = currentRun.runDefinitions - import runDefinitions._ val typer: global.analyzer.Typer val universe: Tree diff --git a/src/compiler/scala/reflect/reify/codegen/GenUtils.scala b/src/compiler/scala/reflect/reify/codegen/GenUtils.scala index 4512b2cb6f..de9fec0df5 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenUtils.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenUtils.scala @@ -5,10 +5,6 @@ trait GenUtils { self: Reifier => import global._ - import treeInfo._ - import definitions._ - private val runDefinitions = currentRun.runDefinitions - import runDefinitions._ def reifyList(xs: List[Any]): Tree = mkList(xs map reify) diff --git a/src/compiler/scala/tools/nsc/CompilationUnits.scala b/src/compiler/scala/tools/nsc/CompilationUnits.scala index 0a356ed7b6..1a6843a249 100644 --- a/src/compiler/scala/tools/nsc/CompilationUnits.scala +++ b/src/compiler/scala/tools/nsc/CompilationUnits.scala @@ -8,7 +8,6 @@ package scala.tools.nsc import scala.reflect.internal.util.{ SourceFile, NoSourceFile, FreshNameCreator } import scala.collection.mutable import scala.collection.mutable.{ LinkedHashSet, ListBuffer } -import scala.tools.nsc.reporters.Reporter trait CompilationUnits { global: Global => diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 452081cff1..9cc9712b44 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -9,17 +9,16 @@ package nsc import java.io.{ File, FileOutputStream, PrintWriter, IOException, FileNotFoundException } import java.nio.charset.{ Charset, CharsetDecoder, IllegalCharsetNameException, UnsupportedCharsetException } -import java.util.UUID._ import scala.compat.Platform.currentTime import scala.collection.{ mutable, immutable } import io.{ SourceReader, AbstractFile, Path } import reporters.{ Reporter, ConsoleReporter } -import util.{ ClassPath, MergedClassPath, StatisticsInfo, returning, stackTraceString } +import util.{ ClassPath, StatisticsInfo, returning, stackTraceString } import scala.reflect.ClassTag import scala.reflect.internal.util.{ OffsetPosition, SourceFile, NoSourceFile, BatchSourceFile, ScriptSourceFile } import scala.reflect.internal.pickling.{ PickleBuffer, PickleFormat } import scala.reflect.io.VirtualFile -import symtab.{ Flags, SymbolTable, SymbolLoaders, SymbolTrackers } +import symtab.{ Flags, SymbolTable, SymbolTrackers } import symtab.classfile.Pickler import plugins.Plugins import ast._ @@ -28,7 +27,7 @@ import typechecker._ import transform.patmat.PatternMatching import transform._ import backend.icode.{ ICodes, GenICode, ICodeCheckers } -import backend.{ ScalaPrimitives, Platform, JavaPlatform } +import backend.{ ScalaPrimitives, JavaPlatform } import backend.jvm.GenBCode import backend.jvm.GenASM import backend.opt.{ Inliners, InlineExceptionHandlers, ConstantOptimization, ClosureElimination, DeadCodeElimination } @@ -1232,13 +1231,12 @@ class Global(var currentSettings: Settings, var reporter: Reporter) /** does this run compile given class, module, or case factory? */ // NOTE: Early initialized members temporarily typechecked before the enclosing class, see typedPrimaryConstrBody! - // Here we work around that wrinkle by claiming that a top-level, early-initialized member is compiled in + // Here we work around that wrinkle by claiming that a early-initialized member is compiled in // *every* run. This approximation works because this method is exclusively called with `this` == `currentRun`. def compiles(sym: Symbol): Boolean = if (sym == NoSymbol) false else if (symSource.isDefinedAt(sym)) true - else if (sym.isTopLevel && sym.isEarlyInitialized) true - else if (!sym.isTopLevel) compiles(sym.enclosingTopLevelClass) + else if (!sym.isTopLevel) compiles(sym.enclosingTopLevelClassOrDummy) else if (sym.isModuleClass) compiles(sym.sourceModule) else false diff --git a/src/compiler/scala/tools/nsc/Parsing.scala b/src/compiler/scala/tools/nsc/Parsing.scala index 4dd3c3f378..9e5999ce4f 100644 --- a/src/compiler/scala/tools/nsc/Parsing.scala +++ b/src/compiler/scala/tools/nsc/Parsing.scala @@ -7,7 +7,6 @@ package scala package tools.nsc import scala.reflect.internal.Positions -import scala.tools.nsc.reporters.Reporter /** Similar to Reporting: gather global functionality specific to parsing. */ diff --git a/src/compiler/scala/tools/nsc/Reporting.scala b/src/compiler/scala/tools/nsc/Reporting.scala index c9782de7c8..4d7e9e753f 100644 --- a/src/compiler/scala/tools/nsc/Reporting.scala +++ b/src/compiler/scala/tools/nsc/Reporting.scala @@ -7,7 +7,6 @@ package scala package tools package nsc -import reporters.{ Reporter, ConsoleReporter } import scala.collection.{ mutable, immutable } import scala.reflect.internal.util.StringOps.countElementsAsString diff --git a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala index f9551697d2..ad1975ef23 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala @@ -300,14 +300,16 @@ trait BasicBlocks { if (!closed) instructionList = instructionList map (x => map.getOrElse(x, x)) else - instrs.zipWithIndex collect { - case (oldInstr, i) if map contains oldInstr => - // SI-6288 clone important here because `replaceInstruction` assigns - // a position to `newInstr`. Without this, a single instruction can - // be added twice, and the position last position assigned clobbers - // all previous positions in other usages. - val newInstr = map(oldInstr).clone() - code.touched |= replaceInstruction(i, newInstr) + instrs.iterator.zipWithIndex foreach { + case (oldInstr, i) => + if (map contains oldInstr) { + // SI-6288 clone important here because `replaceInstruction` assigns + // a position to `newInstr`. Without this, a single instruction can + // be added twice, and the position last position assigned clobbers + // all previous positions in other usages. + val newInstr = map(oldInstr).clone() + code.touched |= replaceInstruction(i, newInstr) + } } ////////////////////// Emit ////////////////////// diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala index 4285858bf8..328ec8a033 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala @@ -6,7 +6,6 @@ package scala.tools.nsc.backend.jvm import scala.tools.nsc.Global -import PartialFunction._ /** * This trait contains code shared between GenBCode and GenASM that depends on types defined in @@ -19,7 +18,7 @@ final class BCodeAsmCommon[G <: Global](val global: G) { val ExcludedForwarderFlags = { import scala.tools.nsc.symtab.Flags._ // Should include DEFERRED but this breaks findMember. - ( SPECIALIZED | LIFTED | PROTECTED | STATIC | EXPANDEDNAME | BridgeAndPrivateFlags | MACRO ) + SPECIALIZED | LIFTED | PROTECTED | STATIC | EXPANDEDNAME | BridgeAndPrivateFlags | MACRO } /** @@ -30,10 +29,10 @@ final class BCodeAsmCommon[G <: Global](val global: G) { */ def isAnonymousOrLocalClass(classSym: Symbol): Boolean = { assert(classSym.isClass, s"not a class: $classSym") - val res = (classSym.isAnonymousClass || !classSym.originalOwner.isClass) - // lambda classes are always top-level classes. - if (res) assert(!classSym.isDelambdafyFunction) - res + // Here used to be an `assert(!classSym.isDelambdafyFunction)`: delambdafy lambda classes are + // always top-level. However, SI-8900 shows an example where the weak name-based implementation + // of isDelambdafyFunction failed (for a function declared in a package named "lambda"). + classSym.isAnonymousClass || !classSym.originalOwner.isClass } /** @@ -147,9 +146,16 @@ final class BCodeAsmCommon[G <: Global](val global: G) { annot.args.isEmpty } - def isRuntimeVisible(annot: AnnotationInfo): Boolean = - annot.atp.typeSymbol.getAnnotation(AnnotationRetentionAttr) - .exists(_.assocs.contains((nme.value -> LiteralAnnotArg(Constant(AnnotationRetentionPolicyRuntimeValue))))) + def isRuntimeVisible(annot: AnnotationInfo): Boolean = { + annot.atp.typeSymbol.getAnnotation(AnnotationRetentionAttr) match { + case Some(retentionAnnot) => + retentionAnnot.assocs.contains(nme.value -> LiteralAnnotArg(Constant(AnnotationRetentionPolicyRuntimeValue))) + case _ => + // SI-8926: if the annotation class symbol doesn't have a @RetentionPolicy annotation, the + // annotation is emitted with visibility `RUNTIME` + true + } + } private def retentionPolicyOf(annot: AnnotationInfo): Symbol = annot.atp.typeSymbol.getAnnotation(AnnotationRetentionAttr).map(_.assocs).map(assoc => diff --git a/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala b/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala index 1fadcb8920..c6e699373b 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala @@ -7,7 +7,6 @@ package scala package tools.nsc package backend.opt -import scala.tools.nsc.backend.icode.analysis.LubException import scala.annotation.tailrec /** diff --git a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala index 23611bb629..b4987e1240 100644 --- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala @@ -229,7 +229,8 @@ class MutableSettings(val errorFn: String => Unit) def OutputSetting(outputDirs: OutputDirs, default: String) = add(new OutputSetting(outputDirs, default)) def PhasesSetting(name: String, descr: String, default: String = "") = add(new PhasesSetting(name, descr, default)) def StringSetting(name: String, arg: String, descr: String, default: String) = add(new StringSetting(name, arg, descr, default)) - def ScalaVersionSetting(name: String, arg: String, descr: String, default: ScalaVersion) = add(new ScalaVersionSetting(name, arg, descr, default)) + def ScalaVersionSetting(name: String, arg: String, descr: String, initial: ScalaVersion, default: Option[ScalaVersion] = None) = + add(new ScalaVersionSetting(name, arg, descr, initial, default)) def PathSetting(name: String, descr: String, default: String): PathSetting = { val prepend = StringSetting(name + "/p", "", "", "").internalOnly() val append = StringSetting(name + "/a", "", "", "").internalOnly() @@ -506,28 +507,35 @@ class MutableSettings(val errorFn: String => Unit) withHelpSyntax(name + " <" + arg + ">") } - /** A setting represented by a Scala version, (`default` unless set) */ + /** A setting represented by a Scala version. + * The `initial` value is used if the setting is not specified. + * The `default` value is used if the option is specified without argument (e.g., `-Xmigration`). + */ class ScalaVersionSetting private[nsc]( name: String, val arg: String, descr: String, - default: ScalaVersion) + initial: ScalaVersion, + default: Option[ScalaVersion]) extends Setting(name, descr) { type T = ScalaVersion - protected var v: T = NoScalaVersion + protected var v: T = initial + // This method is invoked if there are no colonated args. In this case the default value is + // used. No arguments are consumed. override def tryToSet(args: List[String]) = { - value = default + default match { + case Some(d) => value = d + case None => errorFn(s"$name requires an argument, the syntax is $helpSyntax") + } Some(args) } override def tryToSetColon(args: List[String]) = args match { - case Nil => value = default; Some(Nil) - case x :: xs => value = ScalaVersion(x, errorFn) ; Some(xs) + case x :: xs => value = ScalaVersion(x, errorFn); Some(xs) + case nil => Some(nil) } - override def tryToSetFromPropertyValue(s: String) = tryToSet(List(s)) - def unparse: List[String] = if (value == NoScalaVersion) Nil else List(s"${name}:${value.unparse}") withHelpSyntax(s"${name}:<${arg}>") diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 850534f2cc..c59d56d8f8 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -92,7 +92,8 @@ trait ScalaSettings extends AbsScalaSettings * The previous "-source" option is intended to be used mainly * though this helper. */ - lazy val isScala211: Boolean = (source.value >= ScalaVersion("2.11.0")) + def isScala211: Boolean = source.value >= ScalaVersion("2.11.0") + def isScala212: Boolean = source.value >= ScalaVersion("2.12.0") /** * -X "Advanced" settings @@ -111,7 +112,7 @@ trait ScalaSettings extends AbsScalaSettings val logFreeTerms = BooleanSetting ("-Xlog-free-terms", "Print a message when reification creates a free term.") val logFreeTypes = BooleanSetting ("-Xlog-free-types", "Print a message when reification resorts to generating a free type.") val maxClassfileName = IntSetting ("-Xmax-classfile-name", "Maximum filename length for generated classes", 255, Some((72, 255)), _ => None) - val Xmigration = ScalaVersionSetting ("-Xmigration", "version", "Warn about constructs whose behavior may have changed since version.", AnyScalaVersion) + val Xmigration = ScalaVersionSetting ("-Xmigration", "version", "Warn about constructs whose behavior may have changed since version.", initial = NoScalaVersion, default = Some(AnyScalaVersion)) val nouescape = BooleanSetting ("-Xno-uescape", "Disable handling of \\u unicode escapes.") val Xnojline = BooleanSetting ("-Xnojline", "Do not use JLine for editing.") val Xverify = BooleanSetting ("-Xverify", "Verify generic signatures in generated bytecode (asm backend only.)") @@ -133,7 +134,7 @@ trait ScalaSettings extends AbsScalaSettings val showPhases = BooleanSetting ("-Xshow-phases", "Print a synopsis of compiler phases.") val sourceReader = StringSetting ("-Xsource-reader", "classname", "Specify a custom method for reading source files.", "") val strictInference = BooleanSetting ("-Xstrict-inference", "Don't infer known-unsound types") - val source = ScalaVersionSetting ("-Xsource", "version", "Treat compiler input as Scala source for the specified version, see SI-8126.", ScalaVersion("2.11")) withPostSetHook ( _ => isScala211) + val source = ScalaVersionSetting ("-Xsource", "version", "Treat compiler input as Scala source for the specified version, see SI-8126.", initial = ScalaVersion("2.11")) val XnoPatmatAnalysis = BooleanSetting ("-Xno-patmat-analysis", "Don't perform exhaustivity/unreachability analysis. Also, ignore @switch annotation.") val XfullLubs = BooleanSetting ("-Xfull-lubs", "Retains pre 2.10 behavior of less aggressive truncation of least upper bounds.") diff --git a/src/compiler/scala/tools/nsc/settings/ScalaVersion.scala b/src/compiler/scala/tools/nsc/settings/ScalaVersion.scala index 4f45043c5e..43bdad5882 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaVersion.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaVersion.scala @@ -34,7 +34,7 @@ case object NoScalaVersion extends ScalaVersion { * to segregate builds */ case class SpecificScalaVersion(major: Int, minor: Int, rev: Int, build: ScalaBuild) extends ScalaVersion { - def unparse = s"${major}.${minor}.${rev}.${build.unparse}" + def unparse = s"${major}.${minor}.${rev}${build.unparse}" def compare(that: ScalaVersion): Int = that match { case SpecificScalaVersion(thatMajor, thatMinor, thatRev, thatBuild) => diff --git a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala index 835d338ab3..f7b1021ea2 100644 --- a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala +++ b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala @@ -30,7 +30,6 @@ import scala.collection.mutable.LinkedHashMap abstract class Delambdafy extends Transform with TypingTransformers with ast.TreeDSL with TypeAdaptingTransformer { import global._ import definitions._ - import CODE._ val analyzer: global.analyzer.type = global.analyzer diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 3d8b2f02f3..db639d0868 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -98,7 +98,7 @@ abstract class Erasure extends AddInterfaces val len = sig.length val copy: Array[Char] = sig.toCharArray var changed = false - while (i < sig.length) { + while (i < len) { val ch = copy(i) if (ch == '.' && last != '>') { copy(i) = '$' @@ -410,7 +410,6 @@ abstract class Erasure extends AddInterfaces def fulldef(sym: Symbol) = if (sym == NoSymbol) sym.toString else s"$sym: ${sym.tpe} in ${sym.owner}" - var noclash = true val clashErrors = mutable.Buffer[(Position, String)]() def clashError(what: String) = { val pos = if (member.owner == root) member.pos else root.pos diff --git a/src/compiler/scala/tools/nsc/transform/Flatten.scala b/src/compiler/scala/tools/nsc/transform/Flatten.scala index fa53ef48b5..4662ef6224 100644 --- a/src/compiler/scala/tools/nsc/transform/Flatten.scala +++ b/src/compiler/scala/tools/nsc/transform/Flatten.scala @@ -77,8 +77,11 @@ abstract class Flatten extends InfoTransform { if (sym.isTerm && !sym.isStaticModule) { decls1 enter sym if (sym.isModule) { - // Nested, non-static moduls are transformed to methods. - assert(sym.isMethod, s"Non-static $sym should have the lateMETHOD flag from RefChecks") + // In theory, we could assert(sym.isMethod), because nested, non-static moduls are + // transformed to methods (lateMETHOD flag added in RefChecks). But this requires + // forcing sym.info (see comment on isModuleNotMethod), which forces stub symbols + // too eagerly (SI-8907). + // Note that module classes are not entered into the 'decls' of the ClassInfoType // of the outer class, only the module symbols are. So the current loop does // not visit module classes. Therefore we set the LIFTED flag here for module diff --git a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala index bbd11efa7e..c1c025ad48 100644 --- a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala +++ b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala @@ -6,7 +6,6 @@ package scala.tools.nsc package transform -import symtab.Flags._ import scala.reflect.internal.SymbolPairs /** A class that yields a kind of iterator (`Cursor`), diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index 908aa69310..9c81e31ad9 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -861,11 +861,6 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { debuglog("%s expands to %s in %s".format(sym, specMember.name.decode, pp(env))) info(specMember) = NormalizedMember(sym) newOverload(sym, specMember, env) - // if this is a class, we insert the normalized member in scope, - // if this is a method, there's no attached scope for it (EmptyScope) - val decls = owner.info.decls - if (decls != EmptyScope) - decls.enter(specMember) specMember } } @@ -1504,20 +1499,13 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { val residualTargs = symbol.info.typeParams zip baseTargs collect { case (tvar, targ) if !env.contains(tvar) || !isPrimitiveValueClass(env(tvar).typeSymbol) => targ } - // See SI-5583. Don't know why it happens now if it didn't before. - if (specMember.info.typeParams.isEmpty && residualTargs.nonEmpty) { - devWarning("Type args to be applied, but symbol says no parameters: " + ((specMember.defString, residualTargs))) - baseTree - } - else { - ifDebug(assert(residualTargs.length == specMember.info.typeParams.length, - "residual: %s, tparams: %s, env: %s".format(residualTargs, specMember.info.typeParams, env)) - ) + ifDebug(assert(residualTargs.length == specMember.info.typeParams.length, + "residual: %s, tparams: %s, env: %s".format(residualTargs, specMember.info.typeParams, env)) + ) - val tree1 = gen.mkTypeApply(specTree, residualTargs) - debuglog("rewrote " + tree + " to " + tree1) - localTyper.typedOperator(atPos(tree.pos)(tree1)) // being polymorphic, it must be a method - } + val tree1 = gen.mkTypeApply(specTree, residualTargs) + debuglog("rewrote " + tree + " to " + tree1) + localTyper.typedOperator(atPos(tree.pos)(tree1)) // being polymorphic, it must be a method } curTree = tree diff --git a/src/compiler/scala/tools/nsc/transform/Statics.scala b/src/compiler/scala/tools/nsc/transform/Statics.scala index e2508b8d08..4673be6de7 100644 --- a/src/compiler/scala/tools/nsc/transform/Statics.scala +++ b/src/compiler/scala/tools/nsc/transform/Statics.scala @@ -1,9 +1,6 @@ package scala.tools.nsc package transform -import symtab._ -import Flags._ - import collection.mutable.Buffer abstract class Statics extends Transform with ast.TreeDSL { diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala index ef534f70fd..16ea3ea90f 100644 --- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala +++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala @@ -129,6 +129,13 @@ abstract class TailCalls extends Transform { } override def toString = s"${method.name} tparams=$tparams tailPos=$tailPos label=$label label info=${label.info}" + final def noTailContext() = clonedTailContext(false) + final def yesTailContext() = clonedTailContext(true) + protected def clonedTailContext(tailPos: Boolean): TailContext = this match { + case _ if this.tailPos == tailPos => this + case clone: ClonedTailContext => clone.that.clonedTailContext(tailPos) + case _ => new ClonedTailContext(this, tailPos) + } } object EmptyTailContext extends TailContext { @@ -174,7 +181,7 @@ abstract class TailCalls extends Transform { } def containsRecursiveCall(t: Tree) = t exists isRecursiveCall } - class ClonedTailContext(that: TailContext, override val tailPos: Boolean) extends TailContext { + class ClonedTailContext(val that: TailContext, override val tailPos: Boolean) extends TailContext { def method = that.method def tparams = that.tparams def methodPos = that.methodPos @@ -183,9 +190,6 @@ abstract class TailCalls extends Transform { } private var ctx: TailContext = EmptyTailContext - private def noTailContext() = new ClonedTailContext(ctx, tailPos = false) - private def yesTailContext() = new ClonedTailContext(ctx, tailPos = true) - override def transformUnit(unit: CompilationUnit): Unit = { try { @@ -206,16 +210,16 @@ abstract class TailCalls extends Transform { finally this.ctx = saved } - def yesTailTransform(tree: Tree): Tree = transform(tree, yesTailContext()) - def noTailTransform(tree: Tree): Tree = transform(tree, noTailContext()) + def yesTailTransform(tree: Tree): Tree = transform(tree, ctx.yesTailContext()) + def noTailTransform(tree: Tree): Tree = transform(tree, ctx.noTailContext()) def noTailTransforms(trees: List[Tree]) = { - val nctx = noTailContext() - trees map (t => transform(t, nctx)) + val nctx = ctx.noTailContext() + trees mapConserve (t => transform(t, nctx)) } override def transform(tree: Tree): Tree = { /* A possibly polymorphic apply to be considered for tail call transformation. */ - def rewriteApply(target: Tree, fun: Tree, targs: List[Tree], args: List[Tree]) = { + def rewriteApply(target: Tree, fun: Tree, targs: List[Tree], args: List[Tree], mustTransformArgs: Boolean = true) = { val receiver: Tree = fun match { case Select(qual, _) => qual case _ => EmptyTree @@ -223,7 +227,7 @@ abstract class TailCalls extends Transform { def receiverIsSame = ctx.enclosingType.widen =:= receiver.tpe.widen def receiverIsSuper = ctx.enclosingType.widen <:< receiver.tpe.widen def isRecursiveCall = (ctx.method eq fun.symbol) && ctx.tailPos - def transformArgs = noTailTransforms(args) + def transformArgs = if (mustTransformArgs) noTailTransforms(args) else args def matchesTypeArgs = ctx.tparams sameElements (targs map (_.tpe.typeSymbol)) /* Records failure reason in Context for reporting. @@ -265,6 +269,10 @@ abstract class TailCalls extends Transform { !(sym.hasAccessorFlag || sym.isConstructor) } + // intentionally shadowing imports from definitions for performance + val runDefinitions = currentRun.runDefinitions + import runDefinitions.{Boolean_or, Boolean_and} + tree match { case ValDef(_, _, _, _) => if (tree.symbol.isLazy && tree.symbol.hasAnnotation(TailrecClass)) @@ -312,8 +320,13 @@ abstract class TailCalls extends Transform { // the assumption is once we encounter a case, the remainder of the block will consist of cases // the prologue may be empty, usually it is the valdef that stores the scrut val (prologue, cases) = stats span (s => !s.isInstanceOf[LabelDef]) + val transformedPrologue = noTailTransforms(prologue) + val transformedCases = transformTrees(cases) + val transformedStats = + if ((prologue eq transformedPrologue) && (cases eq transformedCases)) stats // allow reuse of `tree` if the subtransform was an identity + else transformedPrologue ++ transformedCases treeCopy.Block(tree, - noTailTransforms(prologue) ++ transformTrees(cases), + transformedStats, transform(expr) ) @@ -380,7 +393,7 @@ abstract class TailCalls extends Transform { if (res ne arg) treeCopy.Apply(tree, fun, res :: Nil) else - rewriteApply(fun, fun, Nil, args) + rewriteApply(fun, fun, Nil, args, mustTransformArgs = false) case Apply(fun, args) => rewriteApply(fun, fun, Nil, args) @@ -421,6 +434,10 @@ abstract class TailCalls extends Transform { def traverseNoTail(tree: Tree) = traverse(tree, maybeTailNew = false) def traverseTreesNoTail(trees: List[Tree]) = trees foreach traverseNoTail + // intentionally shadowing imports from definitions for performance + private val runDefinitions = currentRun.runDefinitions + import runDefinitions.{Boolean_or, Boolean_and} + override def traverse(tree: Tree) = tree match { // we're looking for label(x){x} in tail position, since that means `a` is in tail position in a call `label(a)` case LabelDef(_, List(arg), body@Ident(_)) if arg.symbol == body.symbol => diff --git a/src/compiler/scala/tools/nsc/transform/TypeAdaptingTransformer.scala b/src/compiler/scala/tools/nsc/transform/TypeAdaptingTransformer.scala index f83b6f857e..3b23306386 100644 --- a/src/compiler/scala/tools/nsc/transform/TypeAdaptingTransformer.scala +++ b/src/compiler/scala/tools/nsc/transform/TypeAdaptingTransformer.scala @@ -1,7 +1,6 @@ package scala.tools.nsc package transform -import scala.reflect.internal._ import scala.tools.nsc.ast.TreeDSL import scala.tools.nsc.Global diff --git a/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala b/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala index 79f5e3bee8..8924394b72 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala @@ -73,9 +73,7 @@ trait ScalacPatternExpanders { * Unfortunately the MethodType does not carry the information of whether * it was unapplySeq, so we have to funnel that information in separately. */ - def unapplyMethodTypes(method: Type, isSeq: Boolean): Extractor = { - val whole = firstParamType(method) - val result = method.finalResultType + def unapplyMethodTypes(whole: Type, result: Type, isSeq: Boolean): Extractor = { val expanded = ( if (result =:= BooleanTpe) Nil else typeOfMemberNamedGet(result) match { @@ -124,11 +122,11 @@ trait ScalacPatternExpanders { case _ => sel } val patterns = newPatterns(args) - val isSeq = sel.symbol.name == nme.unapplySeq val isUnapply = sel.symbol.name == nme.unapply + val extractor = sel.symbol.name match { - case nme.unapply => unapplyMethodTypes(fn.tpe, isSeq = false) - case nme.unapplySeq => unapplyMethodTypes(fn.tpe, isSeq = true) + case nme.unapply => unapplyMethodTypes(firstParamType(fn.tpe), sel.tpe, isSeq = false) + case nme.unapplySeq => unapplyMethodTypes(firstParamType(fn.tpe), sel.tpe, isSeq = true) case _ => applyMethodTypes(fn.tpe) } diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala index ba183fe3e6..0aa62d771e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala +++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala @@ -212,7 +212,9 @@ trait MethodSynthesis { List(cd, mdef) case _ => // Shouldn't happen, but let's give ourselves a reasonable error when it does - abort("No synthetics for " + meth + ": synthetics contains " + context.unit.synthetics.keys.mkString(", ")) + context.error(cd.pos, s"Internal error: Symbol for synthetic factory method not found among ${context.unit.synthetics.keys.mkString(", ")}") + // Soldier on for the sake of the presentation compiler + List(cd) } case _ => stat :: Nil @@ -355,8 +357,9 @@ trait MethodSynthesis { def derivedSym: Symbol = { // Only methods will do! Don't want to pick up any stray // companion objects of the same name. - val result = enclClass.info decl name suchThat (x => x.isMethod && x.isSynthetic) - assert(result != NoSymbol, "not found: "+name+" in "+enclClass+" "+enclClass.info.decls) + val result = enclClass.info decl name filter (x => x.isMethod && x.isSynthetic) + if (result == NoSymbol || result.isOverloaded) + context.error(tree.pos, s"Internal error: Unable to find the synthetic factory method corresponding to implicit class $name in $enclClass / ${enclClass.info.decls}") result } def derivedTree: DefDef = diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index e876d4a6af..a1de5e303b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -296,7 +296,7 @@ trait Namers extends MethodSynthesis { } tree.symbol match { case NoSymbol => try dispatch() catch typeErrorHandler(tree, this.context) - case sym => enterExistingSym(sym) + case sym => enterExistingSym(sym, tree) } } @@ -413,6 +413,7 @@ trait Namers extends MethodSynthesis { if (isRedefinition) { updatePosFlags(existing, tree.pos, tree.mods.flags) setPrivateWithin(tree, existing) + clearRenamedCaseAccessors(existing) existing } else assignAndEnterSymbol(tree) setFlag inConstructorFlag @@ -736,7 +737,9 @@ trait Namers extends MethodSynthesis { } // Hooks which are overridden in the presentation compiler - def enterExistingSym(sym: Symbol): Context = this.context + def enterExistingSym(sym: Symbol, tree: Tree): Context = { + this.context + } def enterIfNotThere(sym: Symbol) { } def enterSyntheticSym(tree: Tree): Symbol = { diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index bedca88974..1daff02c23 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -54,6 +54,9 @@ trait SyntheticMethods extends ast.TreeDSL { /** Does not force the info of `caseclazz` */ final def caseAccessorName(caseclazz: Symbol, paramName: TermName) = (renamedCaseAccessors get caseclazz).fold(paramName)(_(paramName)) + final def clearRenamedCaseAccessors(caseclazz: Symbol): Unit = { + renamedCaseAccessors -= caseclazz + } /** Add the synthetic methods to case classes. */ diff --git a/src/compiler/scala/tools/nsc/typechecker/Tags.scala b/src/compiler/scala/tools/nsc/typechecker/Tags.scala index 90ec3a89b8..57dc74d2a0 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Tags.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Tags.scala @@ -11,7 +11,6 @@ trait Tags { self: Typer => private val runDefinitions = currentRun.runDefinitions - import runDefinitions._ private def resolveTag(pos: Position, taggedTp: Type, allowMaterialization: Boolean) = enteringTyper { def wrapper (tree: => Tree): Tree = if (allowMaterialization) (context.withMacrosEnabled[Tree](tree)) else (context.withMacrosDisabled[Tree](tree)) @@ -66,7 +65,7 @@ trait Tags { // if someone requests a type tag, but scala-reflect.jar isn't on the library classpath, then bail if (pre == NoType && ApiUniverseClass == NoSymbol) EmptyTree else { - val tagSym = if (concrete) TypeTagClass else WeakTypeTagClass + val tagSym = if (concrete) runDefinitions.TypeTagClass else runDefinitions.WeakTypeTagClass val tagTp = if (pre == NoType) TypeRef(ApiUniverseClass.toTypeConstructor, tagSym, List(tp)) else singleType(pre, pre member tagSym.name) val taggedTp = appliedType(tagTp, List(tp)) resolveTag(pos, taggedTp, allowMaterialization) diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala index 1dac27639c..0f90c6a478 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala @@ -607,7 +607,7 @@ trait TypeDiagnostics { if (!c.owner.exists || c.owner.isClass || c.owner.isMethod || (c.owner.isType && !c.owner.isParameter)) c else enclClassOrMethodOrTypeMember(c.outer) - val tt = tparams.filter(_.name != typeNames.WILDCARD).foreach { tp => + tparams.filter(_.name != typeNames.WILDCARD).foreach { tp => // we don't care about type params shadowing other type params in the same declaration enclClassOrMethodOrTypeMember(context).outer.lookupSymbol(tp.name, s => s != tp.symbol && s.hasRawInfo && reallyExists(s)) match { case LookupSucceeded(_, sym2) => context.warning(tp.pos, diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index aae2d24b32..70acb03584 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1516,7 +1516,9 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper val cbody1 = treeCopy.Block(cbody, preSuperStats, superCall1) val clazz = context.owner assert(clazz != NoSymbol, templ) - val cscope = context.outer.makeNewScope(ctor, context.outer.owner) + val dummy = context.outer.owner.newLocalDummy(templ.pos) + val cscope = context.outer.makeNewScope(ctor, dummy) + if (dummy.isTopLevel) currentRun.symSource(dummy) = currentUnit.source.file val cbody2 = { // called both during completion AND typing. val typer1 = newTyper(cscope) // XXX: see about using the class's symbol.... diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala index cc2d9141ce..fc1f45e358 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala @@ -142,17 +142,30 @@ trait Unapplies extends ast.TreeDSL { /** The unapply method corresponding to a case class */ def caseModuleUnapplyMeth(cdef: ClassDef): DefDef = { - val tparams = constrTparamsInvariant(cdef) - val method = constrParamss(cdef) match { + val tparams = constrTparamsInvariant(cdef) + val method = constrParamss(cdef) match { case xs :: _ if xs.nonEmpty && isRepeatedParamType(xs.last.tpt) => nme.unapplySeq case _ => nme.unapply } - val cparams = List(ValDef(Modifiers(PARAM | SYNTHETIC), unapplyParamName, classType(cdef, tparams), EmptyTree)) - val ifNull = if (constrParamss(cdef).head.isEmpty) FALSE else REF(NoneModule) - val body = nullSafe({ case Ident(x) => caseClassUnapplyReturnValue(x, cdef) }, ifNull)(Ident(unapplyParamName)) + val cparams = List(ValDef(Modifiers(PARAM | SYNTHETIC), unapplyParamName, classType(cdef, tparams), EmptyTree)) + val resultType = if (!settings.isScala212) TypeTree() else { // fix for SI-6541 under -Xsource:2.12 + def repeatedToSeq(tp: Tree) = tp match { + case AppliedTypeTree(Select(_, tpnme.REPEATED_PARAM_CLASS_NAME), tps) => AppliedTypeTree(gen.rootScalaDot(tpnme.Seq), tps) + case _ => tp + } + constrParamss(cdef) match { + case Nil | Nil :: _ => + gen.rootScalaDot(tpnme.Boolean) + case params :: _ => + val constrParamTypes = params.map(param => repeatedToSeq(param.tpt)) + AppliedTypeTree(gen.rootScalaDot(tpnme.Option), List(treeBuilder.makeTupleType(constrParamTypes))) + } + } + val ifNull = if (constrParamss(cdef).head.isEmpty) FALSE else REF(NoneModule) + val body = nullSafe({ case Ident(x) => caseClassUnapplyReturnValue(x, cdef) }, ifNull)(Ident(unapplyParamName)) atPos(cdef.pos.focus)( - DefDef(caseMods, method, tparams, List(cparams), TypeTree(), body) + DefDef(caseMods, method, tparams, List(cparams), resultType, body) ) } |