diff options
Diffstat (limited to 'src/compiler/scala/tools')
8 files changed, 64 insertions, 20 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index f9eeb41e6d..6d7948f0a9 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -558,7 +558,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { def innerClassSymbolFor(s: Symbol): Symbol = if (s.isClass) s else if (s.isModule) s.moduleClass else NoSymbol - /** Return the a name of this symbol that can be used on the Java platform. It removes spaces from names. + /** Return the name of this symbol that can be used on the Java platform. It removes spaces from names. * * Special handling: * scala.Nothing erases to scala.runtime.Nothing$ @@ -607,7 +607,8 @@ abstract class GenASM extends SubComponent with BytecodeWriters { case None => reverseJavaName.put(internalName, trackedSym) case Some(oldsym) => - assert((oldsym == trackedSym) || (oldsym == RuntimeNothingClass) || (oldsym == RuntimeNullClass), // In contrast, neither NothingClass nor NullClass show up bytecode-level. + assert((oldsym == trackedSym) || (oldsym == RuntimeNothingClass) || (oldsym == RuntimeNullClass) || + (oldsym.isModuleClass && (oldsym.sourceModule == trackedSym.sourceModule)), // In contrast, neither NothingClass nor NullClass show up bytecode-level. "how can getCommonSuperclass() do its job if different class symbols get the same bytecode-level internal name: " + internalName) } } diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 8fd8dfaf83..9caafe6912 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -94,7 +94,10 @@ abstract class ClassfileParser { pushBusy(root) { this.in = new AbstractFileReader(file) this.clazz = if (root.isModule) root.companionClass else root - this.staticModule = clazz.companionModule + // WARNING! do no use clazz.companionModule to find staticModule. + // In a situation where root can be defined, but its companionClass not, + // this would give incorrect results (see SI-5031 in separate compilation scenario) + this.staticModule = if (root.isModule) root else root.companionModule this.isScala = false parseHeader diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 3ac7dd2a8f..a581c6d734 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -469,7 +469,7 @@ abstract class Erasure extends AddInterfaces } def checkPair(member: Symbol, other: Symbol) { - val otpe = erasure(root)(other.tpe) + val otpe = specialErasure(root)(other.tpe) val bridgeNeeded = afterErasure ( !(other.tpe =:= member.tpe) && !(deconstMap(other.tpe) =:= deconstMap(member.tpe)) && @@ -488,7 +488,7 @@ abstract class Erasure extends AddInterfaces debuglog("generating bridge from %s (%s): %s to %s: %s".format( other, flagsToString(newFlags), otpe + other.locationString, member, - erasure(root)(member.tpe) + member.locationString) + specialErasure(root)(member.tpe) + member.locationString) ) // the parameter symbols need to have the new owner @@ -1118,6 +1118,8 @@ abstract class Erasure extends AddInterfaces } else { // store exact array erasure in map to be retrieved later when we might // need to do the cast in adaptMember + // Note: No specialErasure needed here because we simply cast, on + // elimination of SelectFromArray, no boxing or unboxing is done there. treeCopy.Apply( tree, SelectFromArray(qual, name, erasure(tree.symbol)(qual.tpe)).copyAttrs(fn), diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 2b0520592b..80900a1a0a 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -481,7 +481,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { /** The typer */ private var localTyper: erasure.Typer = _ - private def typedPos(pos: Position)(tree: Tree) = localTyper typed { atPos(pos)(tree) } + private def typedPos(pos: Position)(tree: Tree): Tree = localTyper.typedPos(pos)(tree) private def localTyped(pos: Position, tree: Tree, pt: Type) = localTyper.typed(atPos(pos)(tree), pt) /** Map lazy values to the fields they should null after initialization. */ diff --git a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala index 97e86d183e..aa507efe5a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala @@ -321,7 +321,9 @@ abstract class Duplicators extends Analyzer { // we use the symbol name instead of the tree name because the symbol may have been // name mangled, rendering the tree name obsolete // log(tree) - val t = super.typed(atPos(tree.pos)(Select(This(newClassOwner), tree.symbol.name)), mode, pt) + val t = super.typedPos(tree.pos, mode, pt) { + Select(This(newClassOwner), tree.symbol.name) + } // log("typed to: " + t + "; tpe = " + t.tpe + "; " + inspectTpe(t.tpe)) t @@ -331,7 +333,7 @@ abstract class Duplicators extends Analyzer { val tree1 = This(newClassOwner) // log("tree1: " + tree1) debuglog("mapped " + tree + " to " + tree1) - super.typed(atPos(tree.pos)(tree1), mode, pt) + super.typedPos(tree.pos, mode, pt)(tree1) case This(_) => debuglog("selection on this, plain: " + tree) @@ -368,7 +370,7 @@ abstract class Duplicators extends Analyzer { cases } - super.typed(atPos(tree.pos)(Match(scrut, cases1)), mode, pt) + super.typedPos(tree.pos, mode, pt)(Match(scrut, cases1)) case EmptyTree => // no need to do anything, in particular, don't set the type to null, EmptyTree.tpe_= asserts diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 7852ff49e1..99301cebcf 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -1172,7 +1172,7 @@ trait Implicits { } try { - val tree1 = typed(atPos(pos.focus)(arg)) + val tree1 = typedPos(pos.focus)(arg) if (context.hasErrors) processMacroExpansionError(context.errBuffer.head.errPos, context.errBuffer.head.errMsg) else new SearchResult(tree1, EmptyTreeTypeSubstituter) } catch { diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index 903b5904d3..6afc823376 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -36,11 +36,31 @@ trait SyntheticMethods extends ast.TreeDSL { import definitions._ import CODE._ + private lazy val productSymbols = List(Product_productPrefix, Product_productArity, Product_productElement, Product_iterator, Product_canEqual) + private lazy val valueSymbols = List(Any_hashCode, Any_equals) + private lazy val caseSymbols = List(Object_hashCode, Object_toString) ::: productSymbols + private lazy val caseValueSymbols = Any_toString :: valueSymbols ::: productSymbols + private lazy val caseObjectSymbols = Object_equals :: caseSymbols + private def symbolsToSynthesize(clazz: Symbol): List[Symbol] = { + if (clazz.isCase) { + if (clazz.isDerivedValueClass) caseValueSymbols + else if (clazz.isModuleClass) caseSymbols + else caseObjectSymbols + } + else if (clazz.isDerivedValueClass) valueSymbols + else Nil + } + /** Add the synthetic methods to case classes. */ def addSyntheticMethods(templ: Template, clazz0: Symbol, context: Context): Template = { - - if (phase.erasedTypes) + val syntheticsOk = (phase.id <= currentRun.typerPhase.id) && { + symbolsToSynthesize(clazz0) filter (_ matchingSymbol clazz0.info isSynthetic) match { + case Nil => true + case syms => log("Not adding synthetic methods: already has " + syms.mkString(", ")) ; false + } + } + if (!syntheticsOk) return templ val synthesizer = new ClassMethodSynthesis( @@ -94,9 +114,9 @@ trait SyntheticMethods extends ast.TreeDSL { Apply(gen.mkAttributedRef(method), args.toList) } - // Any member, including private + // Any concrete member, including private def hasConcreteImpl(name: Name) = - clazz.info.member(name).alternatives exists (m => !m.isDeferred && !m.isSynthetic) + clazz.info.member(name).alternatives exists (m => !m.isDeferred) def hasOverridingImplementation(meth: Symbol) = { val sym = clazz.info nonPrivateMember meth.name @@ -364,8 +384,7 @@ trait SyntheticMethods extends ast.TreeDSL { (lb ++= templ.body ++= synthesize()).toList } - if (phase.id > currentRun.typerPhase.id) templ - else deriveTemplate(templ)(body => + deriveTemplate(templ)(body => if (clazz.isCase) caseTemplateBody() else synthesize() match { case Nil => body // avoiding unnecessary copy diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index f82786da35..c5bd92a943 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1049,7 +1049,9 @@ trait Typers extends Modes with Adaptations with Tags { case other => other } - typed(atPos(tree.pos)(Select(qual setPos tree.pos.makeTransparent, nme.apply)), mode, pt) + typedPos(tree.pos, mode, pt) { + Select(qual setPos tree.pos.makeTransparent, nme.apply) + } } // begin adapt @@ -1147,11 +1149,15 @@ trait Typers extends Modes with Adaptations with Tags { if (sym == UnitClass && tree.tpe <:< AnyClass.tpe) { // (12) if (settings.warnValueDiscard.value) context.unit.warning(tree.pos, "discarded non-Unit value") - return typed(atPos(tree.pos)(Block(List(tree), Literal(Constant()))), mode, pt) + return typedPos(tree.pos, mode, pt) { + Block(List(tree), Literal(Constant())) + } } else if (isNumericValueClass(sym) && isNumericSubType(tree.tpe, pt)) { if (settings.warnNumericWiden.value) context.unit.warning(tree.pos, "implicit numeric widening") - return typed(atPos(tree.pos)(Select(tree, "to" + sym.name)), mode, pt) + return typedPos(tree.pos, mode, pt) { + Select(tree, "to" + sym.name) + } } case AnnotatedType(_, _, _) if canAdaptAnnotations(tree, mode, pt) => // (13) return typed(adaptAnnotations(tree, mode, pt), mode, pt) @@ -2590,7 +2596,17 @@ trait Typers extends Modes with Adaptations with Tags { def translated = if (members.head eq EmptyTree) setError(tree) - else typed(atPos(tree.pos)(Block(List(ClassDef(anonClass, NoMods, ListOfNil, ListOfNil, members, tree.pos.focus)), atPos(tree.pos.focus)(New(anonClass.tpe)))), mode, pt) + else { + val typedBlock = typedPos(tree.pos, mode, pt) { + Block(ClassDef(anonClass, NoMods, ListOfNil, ListOfNil, members, tree.pos.focus), atPos(tree.pos.focus)(New(anonClass.tpe))) + } + // Don't leak implementation details into the type, see SI-6575 + if (isPartial && !typedBlock.isErrorTyped) + typedPos(tree.pos, mode, pt) { + Typed(typedBlock, TypeTree(typedBlock.tpe baseType PartialFunctionClass)) + } + else typedBlock + } } // Function(params, Match(sel, cases)) ==> new <Partial>Function { def apply<OrElse>(params) = `translateMatch('sel match { cases }')` } @@ -5494,6 +5510,7 @@ trait Typers extends Modes with Adaptations with Tags { ret } + def typedPos(pos: Position, mode: Int, pt: Type)(tree: Tree) = typed(atPos(pos)(tree), mode, pt) def typedPos(pos: Position)(tree: Tree) = typed(atPos(pos)(tree)) // TODO: see if this formulation would impose any penalty, since // it makes for a lot less casting. |