diff options
Diffstat (limited to 'src')
10 files changed, 48 insertions, 25 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala index 068836fe4f..d50d4cd125 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala @@ -320,7 +320,12 @@ trait BasicBlocks { else instrs.zipWithIndex collect { case (oldInstr, i) if map contains oldInstr => - code.touched |= replaceInstruction(i, map(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/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index ad01de9447..70a736c91f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -946,8 +946,8 @@ trait Implicits { * - for alias types and abstract types, we take instead the parts * - of their upper bounds. * @return For those parts that refer to classes with companion objects that - * can be accessed with unambiguous stable prefixes, the implicits infos - * which are members of these companion objects. + * can be accessed with unambiguous stable prefixes that are not existentially + * bound, the implicits infos which are members of these companion objects. */ private def companionImplicitMap(tp: Type): InfoMap = { @@ -963,7 +963,7 @@ trait Implicits { infoMap(sym) = List() // ambiguous prefix - ignore implicit members } case None => - if (pre.isStable) { + if (pre.isStable && !pre.typeSymbol.isExistentiallyBound) { val companion = companionSymbolOf(sym, context) companion.moduleClass match { case mc: ModuleClassSymbol => diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala index 834c64aaae..fa8aff5cdd 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala @@ -801,8 +801,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL protected def spliceApply(binder: Symbol): Tree = { object splice extends Transformer { override def transform(t: Tree) = t match { - case Apply(x, List(Ident(nme.SELECTOR_DUMMY))) => - treeCopy.Apply(t, x, List(CODE.REF(binder))) + case Apply(x, List(i @ Ident(nme.SELECTOR_DUMMY))) => + treeCopy.Apply(t, x, List(CODE.REF(binder).setPos(i.pos))) case _ => super.transform(t) } } @@ -879,7 +879,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL override def transform(tree: Tree): Tree = { def subst(from: List[Symbol], to: List[Tree]): Tree = if (from.isEmpty) tree - else if (tree.symbol == from.head) typedIfOrigTyped(to.head.shallowDuplicate, tree.tpe) + else if (tree.symbol == from.head) typedIfOrigTyped(to.head.shallowDuplicate.setPos(tree.pos), tree.tpe) else subst(from.tail, to.tail) tree match { diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 3e1d3fdcc4..9bd3aa8fe5 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -1536,8 +1536,14 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans sym.name == nme.apply && isClassTypeAccessible(tree) - if (doTransform) + if (doTransform) { + tree foreach { + case i@Ident(_) => + enterReference(i.pos, i.symbol) // SI-5390 need to `enterReference` for `a` in `a.B()` + case _ => + } toConstructor(tree.pos, tree.tpe) + } else { ifNot tree diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 454b03c9b3..f8adcaa25b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -2835,6 +2835,7 @@ trait Typers extends Modes with Adaptations with Tags { def typedRefinement(templ: Template) { val stats = templ.body namer.enterSyms(stats) + // need to delay rest of typedRefinement to avoid cyclic reference errors unit.toCheck += { () => val stats1 = typedStats(stats, NoSymbol) @@ -5155,7 +5156,7 @@ trait Typers extends Modes with Adaptations with Tags { val tree1 = ( if (qual == EmptyTree) tree // atPos necessary because qualifier might come from startContext - else atPos(tree.pos)(Select(qual, name)) + else atPos(tree.pos)(Select(qual, name) setAttachments tree.attachments) ) val (tree2, pre2) = makeAccessible(tree1, defSym, pre, qual) // assert(pre.typeArgs isEmpty) // no need to add #2416-style check here, right? @@ -5180,14 +5181,20 @@ trait Typers extends Modes with Adaptations with Tags { def typedCompoundTypeTree(tree: CompoundTypeTree) = { val templ = tree.templ val parents1 = templ.parents mapConserve (typedType(_, mode)) - if (parents1 exists (_.isErrorTyped)) tree setType ErrorType + + // This is also checked later in typedStats, but that is too late for SI-5361, so + // we eagerly check this here. + for (stat <- templ.body if !treeInfo.isDeclarationOrTypeDef(stat)) + OnlyDeclarationsError(stat) + + if ((parents1 ++ templ.body) exists (_.isErrorTyped)) tree setType ErrorType else { val decls = newScope //Console.println("Owner: " + context.enclClass.owner + " " + context.enclClass.owner.id) val self = refinedType(parents1 map (_.tpe), context.enclClass.owner, decls, templ.pos) newTyper(context.make(templ, self.typeSymbol, decls)).typedRefinement(templ) templ updateAttachment CompoundTypeTreeOriginalAttachment(parents1, Nil) // stats are set elsewhere - tree setType self + tree setType (if (templ.exists(_.isErroneous)) ErrorType else self) // Being conservative to avoid SI-5361 } } diff --git a/src/partest/scala/tools/partest/DirectTest.scala b/src/partest/scala/tools/partest/DirectTest.scala index 8c18809ad6..483cb491a1 100644 --- a/src/partest/scala/tools/partest/DirectTest.scala +++ b/src/partest/scala/tools/partest/DirectTest.scala @@ -39,6 +39,10 @@ abstract class DirectTest extends App { // new compiler def newCompiler(args: String*): Global = { val settings = newSettings((CommandLineParser tokenize ("-d \"" + testOutput.path + "\" " + extraSettings)) ++ args.toList) + newCompiler(settings) + } + + def newCompiler(settings: Settings): Global = { if (settings.Yrangepos.value) new Global(settings, reporter(settings)) with interactive.RangePositions else new Global(settings, reporter(settings)) } diff --git a/src/reflect/scala/reflect/internal/StdAttachments.scala b/src/reflect/scala/reflect/internal/StdAttachments.scala index 1df91a67b0..b782353ed3 100644 --- a/src/reflect/scala/reflect/internal/StdAttachments.scala +++ b/src/reflect/scala/reflect/internal/StdAttachments.scala @@ -10,6 +10,7 @@ trait StdAttachments { trait Attachable { protected var rawatt: scala.reflect.macros.Attachments { type Pos = Position } = NoPosition def attachments = rawatt + def setAttachments(attachments: scala.reflect.macros.Attachments { type Pos = Position }): this.type = { rawatt = attachments; this } def updateAttachment[T: ClassTag](attachment: T): this.type = { rawatt = rawatt.update(attachment); this } def removeAttachment[T: ClassTag]: this.type = { rawatt = rawatt.remove[T]; this } diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index dceec18e57..431afd286d 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -811,7 +811,7 @@ trait Trees extends api.Trees { self: SymbolTable => } def Annotated(tree: Tree, annot: Tree, arg: Tree) = tree match { case t @ Annotated(annot0, arg0) - if (annot0==annot) => t + if (annot0==annot && arg0==arg) => t case _ => treeCopy.Annotated(tree, annot, arg) } def SingletonTypeTree(tree: Tree, ref: Tree) = tree match { diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index d110bd4273..01e0634902 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -574,7 +574,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni case None => // class does not have a Scala signature; it's a Java class info("translating reflection info for Java " + jclazz) //debug - initClassModule(clazz, module, new FromJavaClassCompleter(clazz, module, jclazz)) + initClassAndModule(clazz, module, new FromJavaClassCompleter(clazz, module, jclazz)) } } } catch { @@ -676,9 +676,9 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni def enter(sym: Symbol, mods: Int) = (if (jModifier.isStatic(mods)) module.moduleClass else clazz).info.decls enter sym - for (jinner <- jclazz.getDeclaredClasses) { - enter(jclassAsScala(jinner, clazz), jinner.getModifiers) - } + for (jinner <- jclazz.getDeclaredClasses) + jclassAsScala(jinner) // inner class is entered as a side-effect + // no need to call enter explicitly pendingLoadActions = { () => @@ -1036,14 +1036,14 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni * @param jclazz The Java class * @return A Scala class symbol that wraps all reflection info of `jclazz` */ - private def jclassAsScala(jclazz: jClass[_]): Symbol = jclassAsScala(jclazz, sOwner(jclazz)) + private def jclassAsScala(jclazz: jClass[_]): ClassSymbol = + toScala(classCache, jclazz)(_ jclassAsScala1 _) - private def jclassAsScala(jclazz: jClass[_], owner: Symbol): ClassSymbol = { + private def jclassAsScala1(jclazz: jClass[_]): ClassSymbol = { + val owner = sOwner(jclazz) val name = scalaSimpleName(jclazz) val completer = (clazz: Symbol, module: Symbol) => new FromJavaClassCompleter(clazz, module, jclazz) - val (clazz, module) = createClassModule(owner, name, completer) - classCache enter (jclazz, clazz) - clazz + initAndEnterClassAndModule(owner, name, completer)._1 } /** diff --git a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala index 61663f6181..311db64b91 100644 --- a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala +++ b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala @@ -57,7 +57,7 @@ private[reflect] trait SymbolLoaders { self: SymbolTable => * @param name The simple name of the newly created class * @param completer The completer to be used to set the info of the class and the module */ - protected def createClassModule(owner: Symbol, name: TypeName, completer: (Symbol, Symbol) => LazyType) = { + protected def initAndEnterClassAndModule(owner: Symbol, name: TypeName, completer: (Symbol, Symbol) => LazyType) = { assert(!(name.toString endsWith "[]"), name) val clazz = owner.newClass(name) val module = owner.newModule(name.toTermName) @@ -67,7 +67,7 @@ private[reflect] trait SymbolLoaders { self: SymbolTable => owner.info.decls enter clazz owner.info.decls enter module } - initClassModule(clazz, module, completer(clazz, module)) + initClassAndModule(clazz, module, completer(clazz, module)) (clazz, module) } @@ -75,7 +75,7 @@ private[reflect] trait SymbolLoaders { self: SymbolTable => List(clazz, module, module.moduleClass) foreach (_ setInfo info) } - protected def initClassModule(clazz: Symbol, module: Symbol, completer: LazyType) = + protected def initClassAndModule(clazz: Symbol, module: Symbol, completer: LazyType) = setAllInfos(clazz, module, completer) /** The type completer for packages. @@ -118,7 +118,7 @@ private[reflect] trait SymbolLoaders { self: SymbolTable => val loadingMirror = currentMirror.mirrorDefining(cls) val (clazz, module) = if (loadingMirror eq currentMirror) { - createClassModule(pkgClass, name.toTypeName, new TopClassCompleter(_, _)) + initAndEnterClassAndModule(pkgClass, name.toTypeName, new TopClassCompleter(_, _)) } else { val origOwner = loadingMirror.packageNameToScala(pkgClass.fullName) val clazz = origOwner.info decl name.toTypeName |