diff options
author | Adriaan Moors <adriaan.moors@typesafe.com> | 2013-03-23 08:14:04 -0700 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2013-03-23 08:14:04 -0700 |
commit | 6802371bada3bc5bb93da850295020bd94c423b0 (patch) | |
tree | 9312706da93b5e6351776218764668b66e3ce4f9 | |
parent | fbecd5d3e2364ff59cbfee5a3921384722f9cd36 (diff) | |
parent | c5ad8b478ab9fd3c1aaa0b42bf5f52098636740a (diff) | |
download | scala-6802371bada3bc5bb93da850295020bd94c423b0.tar.gz scala-6802371bada3bc5bb93da850295020bd94c423b0.tar.bz2 scala-6802371bada3bc5bb93da850295020bd94c423b0.zip |
Merge scala/2.10.x into build-cleanup-2.10
Conflicts:
build.xml
65 files changed, 622 insertions, 133 deletions
@@ -1464,40 +1464,61 @@ targets exercised: <mkdir dir="${bc-build.dir}"/> <!-- Pull down MIMA --> <artifact:dependencies pathId="mima.classpath"> - <dependency groupId="com.typesafe" artifactId="mima-reporter_2.9.2" version="0.1.4"/> + <dependency groupId="com.typesafe" artifactId="mima-reporter_2.9.2" version="0.1.5"/> </artifact:dependencies> <artifact:dependencies pathId="old.bc.classpath"> - <dependency groupId="org.scala-lang" artifactId="scala-library" version="2.10.0-RC2"/> - <dependency groupId="org.scala-lang" artifactId="scala-reflect" version="2.10.0-RC2"/> + <dependency groupId="org.scala-lang" artifactId="scala-swing" version="2.10.0"/> + <dependency groupId="org.scala-lang" artifactId="scala-library" version="2.10.0"/> + <dependency groupId="org.scala-lang" artifactId="scala-reflect" version="2.10.0"/> </artifact:dependencies> <property name="maven-deps-done-mima" value="true"/> </target> - <target name="test.bc" depends="bc.init, pack.lib"> - <java - fork="true" - failonerror="true" - classname="com.typesafe.tools.mima.cli.Main"> - <arg value="--prev"/> - <arg value="${org.scala-lang:scala-library:jar}"/> - <arg value="--curr"/> - <arg value="${build-pack.dir}/lib/scala-library.jar"/> - <classpath> - <path refid="mima.classpath"/> - </classpath> - </java> - <java - fork="true" - failonerror="true" - classname="com.typesafe.tools.mima.cli.Main"> - <arg value="--prev"/> - <arg value="${org.scala-lang:scala-reflect:jar}"/> - <arg value="--curr"/> - <arg value="${build-pack.dir}/lib/scala-reflect.jar"/> - <classpath> - <path refid="mima.classpath"/> - </classpath> - </java> + <macrodef name="bc.run-mima"> + <attribute name="jar-name"/> + <attribute name="prev"/> + <attribute name="curr"/> + <attribute name="direction"/> + <sequential> + <echo message="Checking @{direction} binary compatibility for @{jar-name}"/> + <java + fork="true" + failonerror="true" + classname="com.typesafe.tools.mima.cli.Main"> + <arg value="--prev"/> + <arg value="@{prev}"/> + <arg value="--curr"/> + <arg value="@{curr}"/> + <arg value="--filters"/> + <arg value="${basedir}/bincompat-@{direction}.whitelist.conf"/> + <arg value="--generate-filters"/> + <classpath> + <path refid="mima.classpath"/> + </classpath> + </java> + </sequential> + </macrodef> + + <macrodef name="bc.check"> + <attribute name="jar-name"/> + <sequential> + <bc.run-mima + jar-name="@{jar-name}" + prev="${org.scala-lang:@{jar-name}:jar}" + curr="${build-pack.dir}/lib/@{jar-name}.jar" + direction="backward"/> + <bc.run-mima + jar-name="@{jar-name}" + prev="${build-pack.dir}/lib/@{jar-name}.jar" + curr="${org.scala-lang:@{jar-name}:jar}" + direction="forward"/> + </sequential> + </macrodef> + + <target name="test.bc" depends="bc.init, pack.lib, pack.reflect, pack.swing"> + <bc.check jar-name="scala-library"/> + <bc.check jar-name="scala-reflect"/> + <bc.check jar-name="scala-swing"/> </target> <!-- =========================================================================== diff --git a/src/compiler/scala/reflect/reify/utils/Extractors.scala b/src/compiler/scala/reflect/reify/utils/Extractors.scala index 134ae13890..59cd4e5047 100644 --- a/src/compiler/scala/reflect/reify/utils/Extractors.scala +++ b/src/compiler/scala/reflect/reify/utils/Extractors.scala @@ -164,51 +164,30 @@ trait Extractors { } } - object FreeDef { - def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match { - case FreeTermDef(uref, name, binding, flags, origin) => - Some((uref, name, binding, flags, origin)) - case FreeTypeDef(uref, name, binding, flags, origin) => - Some((uref, name, binding, flags, origin)) - case _ => - None - } - } - - object FreeTermDef { - def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match { - case - ValDef(_, name, _, Apply( - Select(Select(uref1 @ Ident(_), build1), newFreeTerm), - List( - _, - _, - Apply(Select(Select(uref2 @ Ident(_), build2), flagsFromBits), List(Literal(Constant(flags: Long)))), - Literal(Constant(origin: String))))) - if uref1.name == nme.UNIVERSE_SHORT && build1 == nme.build && newFreeTerm == nme.newFreeTerm && - uref2.name == nme.UNIVERSE_SHORT && build2 == nme.build && flagsFromBits == nme.flagsFromBits => - Some(uref1, name, reifyBinding(tree), flags, origin) - case _ => - None - } - } - - object FreeTypeDef { - def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match { - case - ValDef(_, name, _, Apply( - Select(Select(uref1 @ Ident(_), build1), newFreeType), - List( - _, - Apply(Select(Select(uref2 @ Ident(_), build2), flagsFromBits), List(Literal(Constant(flags: Long)))), - Literal(Constant(origin: String))))) - if uref1.name == nme.UNIVERSE_SHORT && build1 == nme.build && newFreeType == nme.newFreeType && - uref2.name == nme.UNIVERSE_SHORT && build2 == nme.build && flagsFromBits == nme.flagsFromBits => - Some(uref1, name, reifyBinding(tree), flags, origin) - case _ => - None + sealed abstract class FreeDefExtractor(acceptTerms: Boolean, acceptTypes: Boolean) { + def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = { + def acceptFreeTermFactory(name: Name) = { + (acceptTerms && name == nme.newFreeTerm) || + (acceptTypes && name == nme.newFreeType) + } + tree match { + case + ValDef(_, name, _, Apply( + Select(Select(uref1 @ Ident(_), build1), freeTermFactory), + _ :+ + Apply(Select(Select(uref2 @ Ident(_), build2), flagsFromBits), List(Literal(Constant(flags: Long)))) :+ + Literal(Constant(origin: String)))) + if uref1.name == nme.UNIVERSE_SHORT && build1 == nme.build && acceptFreeTermFactory(freeTermFactory) && + uref2.name == nme.UNIVERSE_SHORT && build2 == nme.build && flagsFromBits == nme.flagsFromBits => + Some(uref1, name, reifyBinding(tree), flags, origin) + case _ => + None + } } } + object FreeDef extends FreeDefExtractor(acceptTerms = true, acceptTypes = true) + object FreeTermDef extends FreeDefExtractor(acceptTerms = true, acceptTypes = false) + object FreeTypeDef extends FreeDefExtractor(acceptTerms = false, acceptTypes = true) object FreeRef { def unapply(tree: Tree): Option[(Tree, TermName)] = tree match { diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index 9b16327ffc..7c46d648fe 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -2259,16 +2259,16 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { // info calls so that types are up to date; erasure may add lateINTERFACE to traits hostSymbol.info ; methodOwner.info - def isInterfaceCall(sym: Symbol) = ( - sym.isInterface && methodOwner != ObjectClass + def needsInterfaceCall(sym: Symbol) = ( + sym.isInterface || sym.isJavaDefined && sym.isNonBottomSubClass(ClassfileAnnotationClass) ) // whether to reference the type of the receiver or - // the type of the method owner (if not an interface!) + // the type of the method owner val useMethodOwner = ( style != Dynamic - || !isInterfaceCall(hostSymbol) && isAccessibleFrom(methodOwner, siteSymbol) || hostSymbol.isBottomClass + || methodOwner == ObjectClass ) val receiver = if (useMethodOwner) methodOwner else hostSymbol val jowner = javaName(receiver) @@ -2291,11 +2291,11 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { } style match { - case Static(true) => dbg("invokespecial"); jcode.invokespecial (jowner, jname, jtype) - case Static(false) => dbg("invokestatic"); jcode.invokestatic (jowner, jname, jtype) - case Dynamic if isInterfaceCall(receiver) => dbg("invokinterface"); jcode.invokeinterface(jowner, jname, jtype) - case Dynamic => dbg("invokevirtual"); jcode.invokevirtual (jowner, jname, jtype) - case SuperCall(_) => + case Static(true) => dbg("invokespecial"); jcode.invokespecial (jowner, jname, jtype) + case Static(false) => dbg("invokestatic"); jcode.invokestatic (jowner, jname, jtype) + case Dynamic if needsInterfaceCall(receiver) => dbg("invokinterface"); jcode.invokeinterface(jowner, jname, jtype) + case Dynamic => dbg("invokevirtual"); jcode.invokevirtual (jowner, jname, jtype) + case SuperCall(_) => dbg("invokespecial") jcode.invokespecial(jowner, jname, jtype) initModule() diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index 598965b982..36b294b289 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -1196,16 +1196,16 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with // info calls so that types are up to date; erasure may add lateINTERFACE to traits hostSymbol.info ; methodOwner.info - def isInterfaceCall(sym: Symbol) = ( - sym.isInterface && methodOwner != ObjectClass + def needsInterfaceCall(sym: Symbol) = ( + sym.isInterface || sym.isJavaDefined && sym.isNonBottomSubClass(ClassfileAnnotationClass) ) // whether to reference the type of the receiver or - // the type of the method owner (if not an interface!) + // the type of the method owner val useMethodOwner = ( style != Dynamic - || !isInterfaceCall(hostSymbol) && isAccessibleFrom(methodOwner, siteSymbol) || hostSymbol.isBottomClass + || methodOwner == ObjectClass ) val receiver = if (useMethodOwner) methodOwner else hostSymbol val jowner = javaName(receiver) @@ -1230,11 +1230,11 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with } style match { - case Static(true) => dbg("invokespecial"); jcode.emitINVOKESPECIAL(jowner, jname, jtype) - case Static(false) => dbg("invokestatic"); jcode.emitINVOKESTATIC(jowner, jname, jtype) - case Dynamic if isInterfaceCall(receiver) => dbg("invokinterface"); jcode.emitINVOKEINTERFACE(jowner, jname, jtype) - case Dynamic => dbg("invokevirtual"); jcode.emitINVOKEVIRTUAL(jowner, jname, jtype) - case SuperCall(_) => + case Static(true) => dbg("invokespecial"); jcode.emitINVOKESPECIAL(jowner, jname, jtype) + case Static(false) => dbg("invokestatic"); jcode.emitINVOKESTATIC(jowner, jname, jtype) + case Dynamic if needsInterfaceCall(receiver) => dbg("invokinterface"); jcode.emitINVOKEINTERFACE(jowner, jname, jtype) + case Dynamic => dbg("invokevirtual"); jcode.emitINVOKEVIRTUAL(jowner, jname, jtype) + case SuperCall(_) => dbg("invokespecial") jcode.emitINVOKESPECIAL(jowner, jname, jtype) initModule() diff --git a/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala b/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala index c4a672ac37..827ebe1678 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala @@ -57,15 +57,13 @@ trait ExprTyper { // Typing it with a lazy val would give us the right type, but runs // into compiler bugs with things like existentials, so we compile it // behind a def and strip the NullaryMethodType which wraps the expr. - val line = "def " + name + " = {\n" + code + "\n}" + val line = "def " + name + " = " + code interpretSynthetic(line) match { case IR.Success => val sym0 = symbolOfTerm(name) // drop NullaryMethodType - val sym = sym0.cloneSymbol setInfo afterTyper(sym0.info.finalResultType) - if (sym.info.typeSymbol eq UnitClass) NoSymbol - else sym + sym0.cloneSymbol setInfo afterTyper(sym0.info.finalResultType) case _ => NoSymbol } } @@ -82,7 +80,11 @@ trait ExprTyper { case _ => NoSymbol } } - beQuietDuring(asExpr()) orElse beQuietDuring(asDefn()) + def asError(): Symbol = { + interpretSynthetic(code) + NoSymbol + } + beSilentDuring(asExpr()) orElse beSilentDuring(asDefn()) orElse asError() } private var typeOfExpressionDepth = 0 diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala index 43a8402fc7..8aa9b81a72 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala @@ -800,13 +800,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { val pos = in.currentPos val name = identForType() val (statics, body) = typeBody(AT, name) - def getValueMethodType(tree: Tree) = tree match { - case DefDef(_, nme.value, _, _, tpt, _) => Some(tpt.duplicate) - case _ => None - } - var templ = makeTemplate(annotationParents, body) - for (stat <- templ.body; tpt <- getValueMethodType(stat)) - templ = makeTemplate(annotationParents, makeConstructor(List(tpt)) :: templ.body) + val templ = makeTemplate(annotationParents, body) addCompanionObject(statics, atPos(pos) { ClassDef(mods, name, List(), templ) }) diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index cb5268c422..ead6ef288c 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -781,7 +781,7 @@ abstract class Erasure extends AddInterfaces else if (tree.symbol == Any_isInstanceOf) adaptMember(atPos(tree.pos)(Select(qual, Object_isInstanceOf))) else if (tree.symbol.owner == AnyClass) - adaptMember(atPos(tree.pos)(Select(qual, getMember(ObjectClass, name)))) + adaptMember(atPos(tree.pos)(Select(qual, getMember(ObjectClass, tree.symbol.name)))) else { var qual1 = typedQualifier(qual) if ((isPrimitiveValueType(qual1.tpe) && !isPrimitiveValueMember(tree.symbol)) || diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index 2f28a16416..f6ee7be511 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -112,6 +112,29 @@ abstract class ExplicitOuter extends InfoTransform sym setInfo clazz.outerClass.thisType } + /** + * Will the outer accessor of the `clazz` subsume the outer accessor of + * `mixin`? + * + * This arises when an inner object mixes in its companion trait. + * + * {{{ + * class C { + * trait T { C.this } // C$T$$$outer$ : C + * object T extends T { C.this } // C$T$$$outer$ : C.this.type + * } + * }}} + * + * See SI-7242. + }} + */ + private def skipMixinOuterAccessor(clazz: Symbol, mixin: Symbol) = { + // Reliant on the current scheme for name expansion, the expanded name + // of the outer accessors in a trait and its companion object are the same. + // If the assumption is one day falsified, run/t7424.scala will let us know. + clazz.fullName == mixin.fullName + } + /** <p> * The type transformation method: * </p> @@ -177,10 +200,14 @@ abstract class ExplicitOuter extends InfoTransform for (mc <- clazz.mixinClasses) { val mixinOuterAcc: Symbol = afterExplicitOuter(outerAccessor(mc)) if (mixinOuterAcc != NoSymbol) { - if (decls1 eq decls) decls1 = decls.cloneScope - val newAcc = mixinOuterAcc.cloneSymbol(clazz, mixinOuterAcc.flags & ~DEFERRED) - newAcc setInfo (clazz.thisType memberType mixinOuterAcc) - decls1 enter newAcc + if (skipMixinOuterAccessor(clazz, mc)) + debuglog(s"Reusing outer accessor symbol of $clazz for the mixin outer accessor of $mc") + else { + if (decls1 eq decls) decls1 = decls.cloneScope + val newAcc = mixinOuterAcc.cloneSymbol(clazz, mixinOuterAcc.flags & ~DEFERRED) + newAcc setInfo (clazz.thisType memberType mixinOuterAcc) + decls1 enter newAcc + } } } } @@ -390,6 +417,7 @@ abstract class ExplicitOuter extends InfoTransform val outerAcc = outerAccessor(mixinClass) overridingSymbol currentClass def mixinPrefix = (currentClass.thisType baseType mixinClass).prefix assert(outerAcc != NoSymbol, "No outer accessor for inner mixin " + mixinClass + " in " + currentClass) + assert(outerAcc.alternatives.size == 1, s"Multiple outer accessors match inner mixin $mixinClass in $currentClass : ${outerAcc.alternatives.map(_.defString)}") // I added the mixinPrefix.typeArgs.nonEmpty condition to address the // crash in SI-4970. I feel quite sure this can be improved. val path = ( @@ -492,7 +520,7 @@ abstract class ExplicitOuter extends InfoTransform } if (!currentClass.isTrait) for (mc <- currentClass.mixinClasses) - if (outerAccessor(mc) != NoSymbol) + if (outerAccessor(mc) != NoSymbol && !skipMixinOuterAccessor(currentClass, mc)) newDefs += mixinOuterAccessorDef(mc) } } diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index e9f403aea0..66328e23bb 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -492,10 +492,14 @@ abstract class UnCurry extends InfoTransform } else { log(s"Argument '$arg' at line ${arg.pos.safeLine} is $formal from ${fun.fullName}") + def canUseDirectly(recv: Tree) = ( + recv.tpe.typeSymbol.isSubClass(FunctionClass(0)) + && treeInfo.isExprSafeToInline(recv) + ) arg match { // don't add a thunk for by-name argument if argument already is an application of // a Function0. We can then remove the application and use the existing Function0. - case Apply(Select(recv, nme.apply), Nil) if recv.tpe.typeSymbol isSubClass FunctionClass(0) => + case Apply(Select(recv, nme.apply), Nil) if canUseDirectly(recv) => recv case _ => newFunction0(arg) diff --git a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala index bbba7e0435..57b9dfe3e4 100644 --- a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala +++ b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala @@ -101,6 +101,7 @@ trait EtaExpansion { self: Analyzer => case TypeApply(fn, args) => treeCopy.TypeApply(tree, liftoutPrefix(fn), args) setType null case Select(qual, name) => + val name = tree.symbol.name // account for renamed imports, SI-7233 treeCopy.Select(tree, liftout(qual, false), name) setSymbol NoSymbol setType null case Ident(name) => tree diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 7a3ab00578..379f56521b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -516,7 +516,13 @@ trait Namers extends MethodSynthesis { // Setting the position at the import means that if there is // more than one hidden name, the second will not be warned. // So it is the position of the actual hidden name. - checkNotRedundant(tree.pos withPoint fromPos, from, to) + // + // Note: java imports have precence over definitions in the same package + // so don't warn for them. There is a corresponding special treatment + // in the shadowing rules in typedIdent to (SI-7232). In any case, + // we shouldn't be emitting warnings for .java source files. + if (!context.unit.isJava) + checkNotRedundant(tree.pos withPoint fromPos, from, to) } } diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index 1c60f0a79d..f3736f1519 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -502,7 +502,7 @@ trait NamesDefaults { self: Analyzer => // disable conforms as a view... val errsBefore = reporter.ERROR.count try typer.silent { tpr => - val res = tpr.typed(arg, subst(paramtpe)) + val res = tpr.typed(arg.duplicate, subst(paramtpe)) // better warning for SI-5044: if `silent` was not actually silent give a hint to the user // [H]: the reason why `silent` is not silent is because the cyclic reference exception is // thrown in a context completely different from `context` here. The exception happens while diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index d8493d2312..2458fc54e1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1375,9 +1375,8 @@ trait Typers extends Modes with Adaptations with Tags { def onError(reportError: => Tree): Tree = { context.tree match { case Apply(tree1, args) if (tree1 eq tree) && args.nonEmpty => - silent(_.typedArgs(args, mode)) match { - case SilentResultValue(xs) => - val args = xs.asInstanceOf[List[Tree]] + silent(_.typedArgs(args.map(_.duplicate), mode)) match { + case SilentResultValue(args) => if (args exists (_.isErrorTyped)) reportError else @@ -4813,7 +4812,9 @@ trait Typers extends Modes with Adaptations with Tags { if (!reallyExists(sym)) { def handleMissing: Tree = { - if (context.owner.enclosingTopLevelClass.isJavaDefined && name.isTypeName) { + if (context.unit.isJava && name.isTypeName) { + // SI-3120 Java uses the same syntax, A.B, to express selection from the + // value A and from the type A. We have to try both. val tree1 = atPos(tree.pos) { gen.convertToSelectFromType(qual, name) } if (tree1 != EmptyTree) return typed1(tree1, mode, pt) } @@ -5046,7 +5047,25 @@ trait Typers extends Modes with Adaptations with Tags { else cx.depth - (cx.scope.nestingLevel - defEntry.owner.nestingLevel) var impSym: Symbol = NoSymbol // the imported symbol var imports = context.imports // impSym != NoSymbol => it is imported from imports.head - while (!reallyExists(impSym) && !imports.isEmpty && imports.head.depth > symDepth) { + + // Java: A single-type-import declaration d in a compilation unit c of package p + // that imports a type named n shadows, throughout c, the declarations of: + // + // 1) any top level type named n declared in another compilation unit of p + // + // A type-import-on-demand declaration never causes any other declaration to be shadowed. + // + // Scala: Bindings of different kinds have a precedence defined on them: + // + // 1) Definitions and declarations that are local, inherited, or made available by a + // package clause in the same compilation unit where the definition occurs have + // highest precedence. + // 2) Explicit imports have next highest precedence. + def depthOk(imp: ImportInfo) = ( + imp.depth > symDepth + || (unit.isJava && imp.isExplicitImport(name) && imp.depth == symDepth) + ) + while (!reallyExists(impSym) && !imports.isEmpty && depthOk(imports.head)) { impSym = imports.head.importedSymbol(name) if (!impSym.exists) imports = imports.tail } diff --git a/src/compiler/scala/tools/nsc/util/SimpleTracer.scala b/src/compiler/scala/tools/nsc/util/SimpleTracer.scala index b103ae9cb0..2601798b96 100644 --- a/src/compiler/scala/tools/nsc/util/SimpleTracer.scala +++ b/src/compiler/scala/tools/nsc/util/SimpleTracer.scala @@ -10,7 +10,7 @@ import java.io.PrintStream * @param enabled: A condition that must be true for trace info to be produced. */ class SimpleTracer(out: PrintStream, enabled: Boolean = true) { - def apply[T](msg: String)(value: T): T = { + def apply[T](msg: => String)(value: T): T = { if (enabled) out.println(msg+value) value } diff --git a/src/compiler/scala/tools/reflect/MacroImplementations.scala b/src/compiler/scala/tools/reflect/MacroImplementations.scala index 86cd845c54..ae13cc561f 100644 --- a/src/compiler/scala/tools/reflect/MacroImplementations.scala +++ b/src/compiler/scala/tools/reflect/MacroImplementations.scala @@ -118,7 +118,8 @@ abstract class MacroImplementations { if (!strIsEmpty) { val len = str.length while (idx < len) { - if (str(idx) == '%') { + def notPercentN = str(idx) != '%' || (idx + 1 < len && str(idx + 1) != 'n') + if (str(idx) == '%' && notPercentN) { bldr append (str substring (start, idx)) append "%%" start = idx + 1 } diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 6e4ca76382..e5d9e54a16 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -1046,7 +1046,7 @@ trait Definitions extends api.StandardDefinitions { getMemberIfDefined(owner, name) orElse { if (phase.flatClasses && name.isTypeName && !owner.isPackageObjectOrClass) { val pkg = owner.owner - val flatname = nme.flattenedName(owner.name, name) + val flatname = tpnme.flattenedName(owner.name, name) getMember(pkg, flatname) } else fatalMissingSymbol(owner, name) diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index d9eb48ff2d..45c16b7302 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -3022,7 +3022,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => if (Statistics.canEnable) Statistics.incCounter(nameCount) if (needsFlatClasses) { if (flatname eq null) - flatname = nme.flattenedName(rawowner.name, rawname).toTypeName + flatname = tpnme.flattenedName(rawowner.name, rawname) flatname } diff --git a/src/reflect/scala/reflect/runtime/JavaUniverse.scala b/src/reflect/scala/reflect/runtime/JavaUniverse.scala index e18435d5b0..1b69ca4e89 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverse.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverse.scala @@ -17,7 +17,7 @@ class JavaUniverse extends internal.SymbolTable with ReflectSetup with runtime.S def forInteractive = false def forScaladoc = false - def log(msg: => AnyRef): Unit = println(" [] "+msg) + def log(msg: => AnyRef): Unit = if (settings.debug.value) println(" [] "+msg) type TreeCopier = InternalTreeCopierOps def newStrictTreeCopier: TreeCopier = new StrictTreeCopier diff --git a/test/files/jvm/t7253.check b/test/files/jvm/t7253.check new file mode 100644 index 0000000000..43f53aba12 --- /dev/null +++ b/test/files/jvm/t7253.check @@ -0,0 +1 @@ +bytecode identical diff --git a/test/files/jvm/t7253/Base_1.scala b/test/files/jvm/t7253/Base_1.scala new file mode 100644 index 0000000000..a531ebb69d --- /dev/null +++ b/test/files/jvm/t7253/Base_1.scala @@ -0,0 +1,5 @@ +trait A { def f(): Int } +trait B1 extends A +abstract class B2 extends A +class B3 extends A { def f(): Int = 1 } +class B4 extends B3 diff --git a/test/files/jvm/t7253/JavaClient_1.java b/test/files/jvm/t7253/JavaClient_1.java new file mode 100644 index 0000000000..43475de2f5 --- /dev/null +++ b/test/files/jvm/t7253/JavaClient_1.java @@ -0,0 +1,9 @@ +public class JavaClient_1 { + int foo() { + ((A) null).f(); + ((B1) null).f(); + ((B2) null).f(); + ((B3) null).f(); + return ((B4) null).f(); + } +} diff --git a/test/files/jvm/t7253/ScalaClient_1.scala b/test/files/jvm/t7253/ScalaClient_1.scala new file mode 100644 index 0000000000..d244b326a8 --- /dev/null +++ b/test/files/jvm/t7253/ScalaClient_1.scala @@ -0,0 +1,9 @@ +class ScalaClient_1 { + def foo() = { + (null: A).f() + (null: B1).f() + (null: B2).f() + (null: B3).f() + (null: B4).f() + } +} diff --git a/test/files/jvm/t7253/test.scala b/test/files/jvm/t7253/test.scala new file mode 100644 index 0000000000..7fe08e8813 --- /dev/null +++ b/test/files/jvm/t7253/test.scala @@ -0,0 +1,28 @@ +import scala.tools.partest.BytecodeTest + +import scala.tools.nsc.util.JavaClassPath +import java.io.InputStream +import scala.tools.asm +import asm.ClassReader +import asm.tree.{ClassNode, InsnList} +import scala.collection.JavaConverters._ + +object Test extends BytecodeTest { + import instructions._ + + def show: Unit = { + val instrBaseSeqs = Seq("ScalaClient_1", "JavaClient_1") map (name => instructions.fromMethod(getMethod(loadClassNode(name), "foo"))) + val instrSeqs = instrBaseSeqs map (_ filter isInvoke) + cmpInstructions(instrSeqs(0), instrSeqs(1)) + } + + def cmpInstructions(isa: List[Instruction], isb: List[Instruction]) = { + if (isa == isb) println("bytecode identical") + else diffInstructions(isa, isb) + } + + def isInvoke(node: Instruction): Boolean = { + val opcode = node.opcode + (opcode == "INVOKEVIRTUAL") || (opcode == "INVOKEINTERFACE") + } +} diff --git a/test/files/neg/t7259.check b/test/files/neg/t7259.check new file mode 100644 index 0000000000..0ad627fc3b --- /dev/null +++ b/test/files/neg/t7259.check @@ -0,0 +1,7 @@ +t7259.scala:1: error: not found: type xxxxx +@xxxxx // error: not found: type xxxx + ^ +t7259.scala:8: error: type xxxxx is not a member of package annotation +@annotation.xxxxx // error: not found: type scala + ^ +two errors found diff --git a/test/files/neg/t7259.scala b/test/files/neg/t7259.scala new file mode 100644 index 0000000000..0fdfe18822 --- /dev/null +++ b/test/files/neg/t7259.scala @@ -0,0 +1,9 @@ +@xxxxx // error: not found: type xxxx +class Ok + +// +// This had the wrong error message in 2.9 and 2.10. +// + +@annotation.xxxxx // error: not found: type scala +class WrongErrorMessage diff --git a/test/files/pos/t3120/J1.java b/test/files/pos/t3120/J1.java new file mode 100644 index 0000000000..12b23c1c98 --- /dev/null +++ b/test/files/pos/t3120/J1.java @@ -0,0 +1,4 @@ +class J1 { + public class Inner1 { } + public static class Inner2 { } +} diff --git a/test/files/pos/t3120/J2.java b/test/files/pos/t3120/J2.java new file mode 100644 index 0000000000..db6e859020 --- /dev/null +++ b/test/files/pos/t3120/J2.java @@ -0,0 +1,4 @@ +public class J2 { + public void f1(J1.Inner1 p) { } + public void f2(J1.Inner2 p) { } +} diff --git a/test/files/pos/t3120/Q.java b/test/files/pos/t3120/Q.java new file mode 100644 index 0000000000..fe2269308a --- /dev/null +++ b/test/files/pos/t3120/Q.java @@ -0,0 +1,3 @@ +public class Q { + public static void passInner(J1.Inner1 myInner) {} +} diff --git a/test/files/pos/t3120/Test.scala b/test/files/pos/t3120/Test.scala new file mode 100644 index 0000000000..c02146fba1 --- /dev/null +++ b/test/files/pos/t3120/Test.scala @@ -0,0 +1,3 @@ +object Test { + Q.passInner(null) +} diff --git a/test/files/pos/t6921.scala b/test/files/pos/t6921.scala new file mode 100644 index 0000000000..36e70e5d2c --- /dev/null +++ b/test/files/pos/t6921.scala @@ -0,0 +1,11 @@ +class Message(messageType: String, reason: Option[String]) + +class ReproForSI6921 { + + private[this] var reason = "" + + def decideElection = { + val explanation = None + new Message("", reason = explanation) + } +} diff --git a/test/files/pos/t7232.flags b/test/files/pos/t7232.flags new file mode 100644 index 0000000000..e8fb65d50c --- /dev/null +++ b/test/files/pos/t7232.flags @@ -0,0 +1 @@ +-Xfatal-warnings
\ No newline at end of file diff --git a/test/files/pos/t7232/Foo.java b/test/files/pos/t7232/Foo.java new file mode 100644 index 0000000000..3478301b30 --- /dev/null +++ b/test/files/pos/t7232/Foo.java @@ -0,0 +1,9 @@ +package pack; + +import java.util.List; + +public class Foo { + public static java.util.List okay() { throw new Error(); } + + public static List wrong() { throw new Error(); } +} diff --git a/test/files/pos/t7232/List.java b/test/files/pos/t7232/List.java new file mode 100644 index 0000000000..e42c63aa67 --- /dev/null +++ b/test/files/pos/t7232/List.java @@ -0,0 +1,4 @@ +package pack; + +public class List { +} diff --git a/test/files/pos/t7232/Test.scala b/test/files/pos/t7232/Test.scala new file mode 100644 index 0000000000..49c3c12aed --- /dev/null +++ b/test/files/pos/t7232/Test.scala @@ -0,0 +1,5 @@ +object Test { + import pack._ + Foo.okay().size() + Foo.wrong().size() +} diff --git a/test/files/pos/t7232b.flags b/test/files/pos/t7232b.flags new file mode 100644 index 0000000000..e8fb65d50c --- /dev/null +++ b/test/files/pos/t7232b.flags @@ -0,0 +1 @@ +-Xfatal-warnings
\ No newline at end of file diff --git a/test/files/pos/t7232b/Foo.java b/test/files/pos/t7232b/Foo.java new file mode 100644 index 0000000000..94f08d545e --- /dev/null +++ b/test/files/pos/t7232b/Foo.java @@ -0,0 +1,8 @@ +package pack; + +import java.util.*; + +public class Foo { + // should be pack.List. + public static List list() { throw new Error(); } +} diff --git a/test/files/pos/t7232b/List.java b/test/files/pos/t7232b/List.java new file mode 100644 index 0000000000..ce977152b9 --- /dev/null +++ b/test/files/pos/t7232b/List.java @@ -0,0 +1,5 @@ +package pack; + +public class List { + public void packList() {} +} diff --git a/test/files/pos/t7232b/Test.scala b/test/files/pos/t7232b/Test.scala new file mode 100644 index 0000000000..6377e26bec --- /dev/null +++ b/test/files/pos/t7232b/Test.scala @@ -0,0 +1,5 @@ +object Test { + import pack._ + + Foo.list().packList() +} diff --git a/test/files/pos/t7232c.flags b/test/files/pos/t7232c.flags new file mode 100644 index 0000000000..e8fb65d50c --- /dev/null +++ b/test/files/pos/t7232c.flags @@ -0,0 +1 @@ +-Xfatal-warnings
\ No newline at end of file diff --git a/test/files/pos/t7232c/Foo.java b/test/files/pos/t7232c/Foo.java new file mode 100644 index 0000000000..bbda09a2da --- /dev/null +++ b/test/files/pos/t7232c/Foo.java @@ -0,0 +1,10 @@ +package pack; + +import java.util.List; + +public class Foo { + public static class List { + public void isInnerList() {} + } + public static List innerList() { throw new Error(); } +} diff --git a/test/files/pos/t7232c/Test.scala b/test/files/pos/t7232c/Test.scala new file mode 100644 index 0000000000..aa7c710948 --- /dev/null +++ b/test/files/pos/t7232c/Test.scala @@ -0,0 +1,4 @@ +object Test { + import pack._ + Foo.innerList().isInnerList() +} diff --git a/test/files/pos/t7232d.flags b/test/files/pos/t7232d.flags new file mode 100644 index 0000000000..e8fb65d50c --- /dev/null +++ b/test/files/pos/t7232d.flags @@ -0,0 +1 @@ +-Xfatal-warnings
\ No newline at end of file diff --git a/test/files/pos/t7232d/Entry.java b/test/files/pos/t7232d/Entry.java new file mode 100644 index 0000000000..0cfb6fb25b --- /dev/null +++ b/test/files/pos/t7232d/Entry.java @@ -0,0 +1,4 @@ +package pack; + +public class Entry { +} diff --git a/test/files/pos/t7232d/Foo.java b/test/files/pos/t7232d/Foo.java new file mode 100644 index 0000000000..df7114a0f0 --- /dev/null +++ b/test/files/pos/t7232d/Foo.java @@ -0,0 +1,8 @@ +package pack; + +import java.util.Map.Entry; + +public class Foo { + public static Entry mapEntry() { throw new Error(); } + public static void javaTest() { mapEntry().getKey(); } +} diff --git a/test/files/pos/t7232d/Test.scala b/test/files/pos/t7232d/Test.scala new file mode 100644 index 0000000000..89a8063b3c --- /dev/null +++ b/test/files/pos/t7232d/Test.scala @@ -0,0 +1,4 @@ +object Test { + import pack._ + Foo.mapEntry().getKey() +} diff --git a/test/files/pos/t7233.scala b/test/files/pos/t7233.scala new file mode 100644 index 0000000000..ae15c08c35 --- /dev/null +++ b/test/files/pos/t7233.scala @@ -0,0 +1,14 @@ +object Foo { + def bar(i: Int) = i + + def ol(i: Int) = i + def ol(i: String) = i +} +object Test { + import Foo.{ bar => quux, toString => bar, ol => olRenamed} + + val f1 = quux _ + val f1Typed: (Int => Int) = f1 + + val f2: String => String = olRenamed _ +} diff --git a/test/files/pos/t7233b.scala b/test/files/pos/t7233b.scala new file mode 100644 index 0000000000..927c7fcfd1 --- /dev/null +++ b/test/files/pos/t7233b.scala @@ -0,0 +1,8 @@ +object Test { + // crash + def foo(a: Any) = { import a.{toString => toS}; toS } + + // okay + def ok1(a: String) = { import a.{isInstanceOf => iio}; iio[String] } + def ok2(a: Int) = { import a.{toInt => ti}; ti } +} diff --git a/test/files/pos/t7239.scala b/test/files/pos/t7239.scala new file mode 100644 index 0000000000..16e9d00f17 --- /dev/null +++ b/test/files/pos/t7239.scala @@ -0,0 +1,38 @@ +object Test { + def BrokenMethod(): HasFilter[(Int, String)] = ??? + + trait HasFilter[B] { + def filter(p: B => Boolean) = ??? + } + + trait HasWithFilter { + def withFilter = ??? + } + + object addWithFilter { + trait NoImplicit + implicit def enrich(v: Any) + (implicit F0: NoImplicit): HasWithFilter = ??? + } + + BrokenMethod().withFilter(_ => true) // okay + BrokenMethod().filter(_ => true) // okay + + locally { + import addWithFilter._ + BrokenMethod().withFilter((_: (Int, String)) => true) // okay + } + + locally { + import addWithFilter._ + // adaptToMemberWithArgs sets the type of the tree `x` + // to ErrorType (while in silent mode, so the error is not + // reported. Later, when the fallback from `withFilter` + // to `filter` is attempted, the closure is taken to have + // have the type `<error> => Boolean`, which conforms to + // `(B => Boolean)`. Only later during pickling does the + // defensive check for erroneous types in the tree pick up + // the problem. + BrokenMethod().withFilter(x => true) // erroneous or inaccessible type. + } +} diff --git a/test/files/run/repl-colon-type.check b/test/files/run/repl-colon-type.check index 56ddd74375..0cb18e989a 100644 --- a/test/files/run/repl-colon-type.check +++ b/test/files/run/repl-colon-type.check @@ -4,12 +4,6 @@ Type :help for more information. scala> scala> :type List[1, 2, 3] -<console>:2: error: identifier expected but integer literal found. - List[1, 2, 3] - ^ -<console>:3: error: ']' expected but '}' found. - } - ^ <console>:1: error: identifier expected but integer literal found. List[1, 2, 3] ^ @@ -45,12 +39,9 @@ scala> :type lazy val f = 5 Int scala> :type protected lazy val f = 5 -<console>:2: error: illegal start of statement (no modifiers allowed here) - protected lazy val f = 5 - ^ <console>:5: error: lazy value f cannot be accessed in object $iw Access to protected value f not permitted because - enclosing object $eval in package $line19 is not a subclass of + enclosing object $eval in package $line13 is not a subclass of object $iw where target is defined lazy val $result = `f` ^ @@ -223,4 +214,14 @@ PolyType( scala> +scala> // SI-7132 - :type doesn't understand Unit + +scala> :type () +Unit + +scala> :type println("side effect!") +Unit + +scala> + scala> diff --git a/test/files/run/repl-colon-type.scala b/test/files/run/repl-colon-type.scala index c055b215c2..8cf81a6afe 100644 --- a/test/files/run/repl-colon-type.scala +++ b/test/files/run/repl-colon-type.scala @@ -26,6 +26,10 @@ object Test extends ReplTest { |:type -v Nil.combinations _ |:type -v def f[T <: AnyVal] = List[T]().combinations _ |:type -v def f[T, U >: T](x: T, y: List[U]) = x :: y + | + |// SI-7132 - :type doesn't understand Unit + |:type () + |:type println("side effect!") """.stripMargin } diff --git a/test/files/run/t3994.scala b/test/files/run/t3994.scala new file mode 100644 index 0000000000..0ee1d9d966 --- /dev/null +++ b/test/files/run/t3994.scala @@ -0,0 +1,20 @@ +trait T { + trait Default { def foo = this } + object Default extends Default +} + +class Crash { // if you change this to a `trait` it keeps failing, though if it is an `object` it compiles just fine! + class Element + + /* declare this as a class, and the crash goes away */ + trait ElementOrdering extends Ordering[Element] { + def compare(a: Element, b: Element): Int = 0 + } + + implicit object ElementOrdering extends ElementOrdering +} + +object Test extends App { + (new T {}).Default + (new Crash).ElementOrdering +} diff --git a/test/files/run/t5699.check b/test/files/run/t5699.check new file mode 100755 index 0000000000..df19644ae6 --- /dev/null +++ b/test/files/run/t5699.check @@ -0,0 +1,11 @@ +[[syntax trees at end of parser]] // annodef.java +package <empty> { + object MyAnnotation extends { + def <init>() = _ + }; + class MyAnnotation extends scala.annotation.Annotation with _root_.java.lang.annotation.Annotation with scala.annotation.ClassfileAnnotation { + def <init>() = _; + def value(): String + } +} + diff --git a/test/files/run/t5699.scala b/test/files/run/t5699.scala new file mode 100755 index 0000000000..5cef67e3b1 --- /dev/null +++ b/test/files/run/t5699.scala @@ -0,0 +1,24 @@ +import scala.tools.partest.DirectTest +import scala.tools.nsc.util.BatchSourceFile + +object Test extends DirectTest { + // Java code + override def code = """ + |public @interface MyAnnotation { String value(); } + """.stripMargin + + override def extraSettings: String = "-usejavacp -Ystop-after:typer -Xprint:parser" + + override def show(): Unit = { + // redirect err to out, for logging + val prevErr = System.err + System.setErr(System.out) + compile() + System.setErr(prevErr) + } + + override def newSources(sourceCodes: String*) = { + assert(sourceCodes.size == 1) + List(new BatchSourceFile("annodef.java", sourceCodes(0))) + } +} diff --git a/test/files/run/t6223.check b/test/files/run/t6223.check index 90ec019407..f83799bab1 100644 --- a/test/files/run/t6223.check +++ b/test/files/run/t6223.check @@ -1,4 +1,4 @@ bar -bar$mcI$sp bar$mIc$sp bar$mIcI$sp +bar$mcI$sp
\ No newline at end of file diff --git a/test/files/run/t6223.scala b/test/files/run/t6223.scala index 4ab7c832e6..0996ea1c45 100644 --- a/test/files/run/t6223.scala +++ b/test/files/run/t6223.scala @@ -5,7 +5,7 @@ class Foo[@specialized(Int) A](a:A) { object Test { def main(args:Array[String]) { val f = new Foo(333) - val ms = f.getClass().getDeclaredMethods() - ms.foreach(m => println(m.getName)) + val ms = f.getClass().getDeclaredMethods().map(_.getName).sorted + ms.foreach(println) } } diff --git a/test/files/run/t6725-1.check b/test/files/run/t6725-1.check new file mode 100644 index 0000000000..6ed281c757 --- /dev/null +++ b/test/files/run/t6725-1.check @@ -0,0 +1,2 @@ +1 +1 diff --git a/test/files/run/t6725-1.scala b/test/files/run/t6725-1.scala new file mode 100644 index 0000000000..a167ef8aa3 --- /dev/null +++ b/test/files/run/t6725-1.scala @@ -0,0 +1,5 @@ +object Test extends App { + val a = 1 + val s = f"$a%s%n$a%s" + println(s) +}
\ No newline at end of file diff --git a/test/files/run/t6725-2.check b/test/files/run/t6725-2.check new file mode 100644 index 0000000000..3496917ad5 --- /dev/null +++ b/test/files/run/t6725-2.check @@ -0,0 +1,8 @@ + + +aaaa + + +aaaa +aaaa +aaaa diff --git a/test/files/run/t6725-2.scala b/test/files/run/t6725-2.scala new file mode 100644 index 0000000000..e033cf5ea8 --- /dev/null +++ b/test/files/run/t6725-2.scala @@ -0,0 +1,6 @@ +object Test extends App { + println(f"%n") + println(f"aaaa%n") + println(f"%naaaa") + println(f"aaaa%naaaa") +}
\ No newline at end of file diff --git a/test/files/run/t7240.check b/test/files/run/t7240.check new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/files/run/t7240.check diff --git a/test/files/run/t7240/Macros_1.scala b/test/files/run/t7240/Macros_1.scala new file mode 100644 index 0000000000..6465e18760 --- /dev/null +++ b/test/files/run/t7240/Macros_1.scala @@ -0,0 +1,48 @@ +package bakery + +import scala.language.experimental.macros +import scala.reflect.macros.Context + +trait FailureCake { + implicit def liftAnyFails[T: Manifest]: Any = ??? + + // This works + // implicit def liftAny[T]: Any = ??? +} + +object Bakery { + + def failure: Any = macro failureImpl + def failureImpl(c: Context): c.Expr[Any] = { + import c.universe._ + + def dslTrait(dslName: String) = { + val names = dslName.split("\\.").toList.reverse + assert(names.length >= 1, "DSL trait name must be in the valid format. DSL trait name is " + dslName) + + val tpeName = newTypeName(names.head) + names.tail.reverse match { + case head :: tail ⇒ + Select(tail.foldLeft[Tree](Ident(newTermName(head)))((tree, name) ⇒ Select(tree, newTermName(name))), tpeName) + case Nil ⇒ + Ident(tpeName) + } + } + + def composeDSL(transformedBody: Tree) = + ClassDef(Modifiers(), newTypeName("eval"), List(), Template( + List(dslTrait("bakery.FailureCake")), + emptyValDef, + List( + DefDef(Modifiers(), nme.CONSTRUCTOR, List(), List(List()), TypeTree(), + Block(List(Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List())), Literal(Constant(())))), + DefDef(Modifiers(), newTermName("main"), List(), List(List()), Ident(newTypeName("Any")), transformedBody)))) + + def constructor = Apply(Select(New(Ident(newTypeName("eval"))), nme.CONSTRUCTOR), List()) + + c.eval(c.Expr[Any]( + c.resetAllAttrs(Block(composeDSL(Literal(Constant(1))), constructor)))) + + c.Expr[Any](Literal(Constant(1))) + } +}
\ No newline at end of file diff --git a/test/files/run/t7240/Test_2.scala b/test/files/run/t7240/Test_2.scala new file mode 100644 index 0000000000..2450bdabf9 --- /dev/null +++ b/test/files/run/t7240/Test_2.scala @@ -0,0 +1,3 @@ +object Test extends App { + bakery.Bakery.failure +}
\ No newline at end of file diff --git a/test/files/run/t7242.scala b/test/files/run/t7242.scala new file mode 100644 index 0000000000..c995336144 --- /dev/null +++ b/test/files/run/t7242.scala @@ -0,0 +1,71 @@ +class CrashTest { + def foo = () + trait CrashTestTable { + def cols = foo + } + // This was leading to a class between the mixed in + // outer accessor and the outer accessor of this object. + object CrashTestTable extends CrashTestTable { + foo + cols + } +} + +class CrashTest1 { + def foo = () + class CrashTestTable { + def cols = foo + } + object CrashTestTable extends CrashTestTable { + foo + cols + } +} + +class CrashTest2 { + def foo = () + trait CrashTestTable { + def cols = foo + } + object Obj extends CrashTestTable { + foo + cols + } +} + +class CrashTest3 { + def foo = () + + def meth() { + trait CrashTestTable { + def cols = foo + } + object Obj extends CrashTestTable { + foo + cols + } + Obj + } +} + +object Test extends App { + { + val c = new CrashTest + c.CrashTestTable + } + + { + val c = new CrashTest1 + c.CrashTestTable + } + + { + val c = new CrashTest2 + c.Obj + } + + { + val c = new CrashTest3 + c.meth() + } +} diff --git a/test/files/run/t7249.check b/test/files/run/t7249.check new file mode 100644 index 0000000000..7777e0a5a2 --- /dev/null +++ b/test/files/run/t7249.check @@ -0,0 +1 @@ +Yup! diff --git a/test/files/run/t7249.scala b/test/files/run/t7249.scala new file mode 100644 index 0000000000..375df5c3ad --- /dev/null +++ b/test/files/run/t7249.scala @@ -0,0 +1,7 @@ +object Test extends App { + def bnToLambda(s: => String): () => String = () => s + var x: () => String = () => sys.error("Nope") + val y = bnToLambda { x() } + x = () => "Yup!" + println(y()) +} |