diff options
257 files changed, 3307 insertions, 996 deletions
@@ -22,7 +22,7 @@ END-USER TARGETS <target name="clean" depends="quick.clean" description="Removes binaries of compiler and library. Distributions are untouched."/> - <target name="test" depends="test.done, osgi.test" + <target name="test" depends="test.done, osgi.test, bc.run" description="Runs test suite and bootstrapping test on Scala compiler and library."/> <target name="test-opt" @@ -2644,6 +2644,40 @@ BOOTRAPING TEST AND TEST SUITE <target name="test.done" depends="test.suite, test.continuations.suite, test.scaladoc, test.stability, test.sbt"/> + +<!-- =========================================================================== +Binary compatibility testing +============================================================================ --> + + <target name="bc.init" depends="init"> + <property name="bc-build.dir" value="${build.dir}/bc"/> + <!-- Obtain mima --> + <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"/> + </artifact:dependencies> + <artifact:dependencies pathId="old.bc.classpath"> + <dependency groupId="org.scala-lang" artifactId="scala-library" version="2.10.0-RC2"/> + </artifact:dependencies> + </target> + + <target name="bc.run" 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> + </target> + + <!-- =========================================================================== DISTRIBUTION ============================================================================ --> diff --git a/src/compiler/scala/reflect/reify/Errors.scala b/src/compiler/scala/reflect/reify/Errors.scala index 3d7cb95792..7c66d5b9eb 100644 --- a/src/compiler/scala/reflect/reify/Errors.scala +++ b/src/compiler/scala/reflect/reify/Errors.scala @@ -33,10 +33,10 @@ trait Errors { } def CannotConvertManifestToTagWithoutScalaReflect(tpe: Type, manifestInScope: Tree) = { - val msg = s""" - |to create a type tag here, it is necessary to interoperate with the manifest `$manifestInScope` in scope. - |however manifest -> typetag conversion requires Scala reflection, which is not present on the classpath. - |to proceed put scala-reflect.jar on your compilation classpath and recompile.""".trim.stripMargin + val msg = + sm"""to create a type tag here, it is necessary to interoperate with the manifest `$manifestInScope` in scope. + |however manifest -> typetag conversion requires Scala reflection, which is not present on the classpath. + |to proceed put scala-reflect.jar on your compilation classpath and recompile.""" throw new ReificationException(defaultErrorPosition, msg) } diff --git a/src/compiler/scala/reflect/reify/codegen/GenTrees.scala b/src/compiler/scala/reflect/reify/codegen/GenTrees.scala index bdcc7383b0..31974b5b76 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenTrees.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenTrees.scala @@ -45,7 +45,9 @@ trait GenTrees { case global.EmptyTree => reifyMirrorObject(EmptyTree) case global.emptyValDef => - mirrorBuildSelect(nme.emptyValDef) + mirrorSelect(nme.emptyValDef) + case global.pendingSuperCall => + mirrorSelect(nme.pendingSuperCall) case FreeDef(_, _, _, _, _) => reifyNestedFreeDef(tree) case FreeRef(_, _) => @@ -101,7 +103,8 @@ trait GenTrees { case ReifiedTree(_, _, inlinedSymtab, rtree, _, _, _) => if (reifyDebug) println("inlining the splicee") // all free vars local to the enclosing reifee should've already been inlined by ``Metalevels'' - inlinedSymtab.syms foreach (sym => if (sym.isLocalToReifee) assert(false, inlinedSymtab.symDef(sym))) + for (sym <- inlinedSymtab.syms if sym.isLocalToReifee) + abort("local free var, should have already been inlined by Metalevels: " + inlinedSymtab.symDef(sym)) state.symtab ++= inlinedSymtab rtree case tree => @@ -117,88 +120,102 @@ trait GenTrees { // unlike in `reifyBoundType` we can skip checking for `tpe` being local or not local w.r.t the reifee // a single check for a symbol of the bound term should be enough // that's because only Idents and Thises can be bound terms, and they cannot host complex types - private def reifyBoundTerm(tree: Tree): Tree = tree match { - case tree @ This(_) if tree.symbol == NoSymbol => - throw new Error("unexpected: bound term that doesn't have a symbol: " + showRaw(tree)) - case tree @ This(_) if tree.symbol.isClass && !tree.symbol.isModuleClass && !tree.symbol.isLocalToReifee => - val sym = tree.symbol - if (reifyDebug) println("This for %s, reified as freeVar".format(sym)) - if (reifyDebug) println("Free: " + sym) - mirrorBuildCall(nme.Ident, reifyFreeTerm(This(sym))) - case tree @ This(_) if !tree.symbol.isLocalToReifee => - if (reifyDebug) println("This for %s, reified as This".format(tree.symbol)) - mirrorBuildCall(nme.This, reify(tree.symbol)) - case tree @ This(_) if tree.symbol.isLocalToReifee => - mirrorCall(nme.This, reify(tree.qual)) - case tree @ Ident(_) if tree.symbol == NoSymbol => - // this sometimes happens, e.g. for binds that don't have a body - // or for untyped code generated during previous phases - // (see a comment in Reifiers about the latter, starting with "why do we resetAllAttrs?") - mirrorCall(nme.Ident, reify(tree.name)) - case tree @ Ident(_) if !tree.symbol.isLocalToReifee => - if (tree.symbol.isVariable && tree.symbol.owner.isTerm) { - captureVariable(tree.symbol) // Note order dependency: captureVariable needs to come before reification here. - mirrorCall(nme.Select, mirrorBuildCall(nme.Ident, reify(tree.symbol)), reify(nme.elem)) - } else { - mirrorBuildCall(nme.Ident, reify(tree.symbol)) - } - case tree @ Ident(_) if tree.symbol.isLocalToReifee => - mirrorCall(nme.Ident, reify(tree.name)) - case _ => - throw new Error("internal error: %s (%s, %s) is not supported".format(tree, tree.productPrefix, tree.getClass)) + private def reifyBoundTerm(tree: Tree): Tree = { + val sym = tree.symbol + + tree match { + case This(qual) => + assert(sym != NoSymbol, "unexpected: bound term that doesn't have a symbol: " + showRaw(tree)) + if (sym.isLocalToReifee) + mirrorCall(nme.This, reify(qual)) + else if (sym.isClass && !sym.isModuleClass) { + if (reifyDebug) println("This for %s, reified as freeVar".format(sym)) + if (reifyDebug) println("Free: " + sym) + mirrorBuildCall(nme.Ident, reifyFreeTerm(This(sym))) + } + else { + if (reifyDebug) println("This for %s, reified as This".format(sym)) + mirrorBuildCall(nme.This, reify(sym)) + } + + case Ident(name) => + if (sym == NoSymbol) { + // this sometimes happens, e.g. for binds that don't have a body + // or for untyped code generated during previous phases + // (see a comment in Reifiers about the latter, starting with "why do we resetAllAttrs?") + mirrorCall(nme.Ident, reify(name)) + } + else if (!sym.isLocalToReifee) { + if (sym.isVariable && sym.owner.isTerm) { + captureVariable(sym) // Note order dependency: captureVariable needs to come before reification here. + mirrorCall(nme.Select, mirrorBuildCall(nme.Ident, reify(sym)), reify(nme.elem)) + } + else mirrorBuildCall(nme.Ident, reify(sym)) + } + else mirrorCall(nme.Ident, reify(name)) + + case Select(qual, name) => + if (sym == NoSymbol || sym.name == name) + reifyProduct(tree) + else + reifyProduct(Select(qual, sym.name)) + + case _ => + throw new Error("internal error: %s (%s, %s) is not supported".format(tree, tree.productPrefix, tree.getClass)) + } } private def reifyBoundType(tree: Tree): Tree = { + val sym = tree.symbol + val tpe = tree.tpe + def reifyBoundType(tree: Tree): Tree = { - if (tree.tpe == null) - throw new Error("unexpected: bound type that doesn't have a tpe: " + showRaw(tree)) + assert(tpe != null, "unexpected: bound type that doesn't have a tpe: " + showRaw(tree)) // if a symbol or a type of the scrutinee are local to reifee // (e.g. point to a locally declared class or to a path-dependent thingie that depends on a local variable) // then we can reify the scrutinee as a symless AST and that will definitely be hygienic // why? because then typechecking of a scrutinee doesn't depend on the environment external to the quasiquote // otherwise we need to reify the corresponding type - if (tree.symbol.isLocalToReifee || tree.tpe.isLocalToReifee) + if (sym.isLocalToReifee || tpe.isLocalToReifee) reifyProduct(tree) else { - val sym = tree.symbol - val tpe = tree.tpe if (reifyDebug) println("reifying bound type %s (underlying type is %s)".format(sym, tpe)) if (tpe.isSpliceable) { val spliced = spliceType(tpe) + if (spliced == EmptyTree) { if (reifyDebug) println("splicing failed: reify as is") mirrorBuildCall(nme.TypeTree, reify(tpe)) - } else { - spliced match { - case TypeRefToFreeType(freeType) => - if (reifyDebug) println("splicing returned a free type: " + freeType) - Ident(freeType) - case _ => - if (reifyDebug) println("splicing succeeded: " + spliced) - mirrorBuildCall(nme.TypeTree, spliced) - } } - } else { - if (sym.isLocatable) { - if (reifyDebug) println("tpe is locatable: reify as Ident(%s)".format(sym)) - mirrorBuildCall(nme.Ident, reify(sym)) - } else { - if (reifyDebug) println("tpe is not locatable: reify as TypeTree(%s)".format(tpe)) - mirrorBuildCall(nme.TypeTree, reify(tpe)) + else spliced match { + case TypeRefToFreeType(freeType) => + if (reifyDebug) println("splicing returned a free type: " + freeType) + Ident(freeType) + case _ => + if (reifyDebug) println("splicing succeeded: " + spliced) + mirrorBuildCall(nme.TypeTree, spliced) } } + else if (sym.isLocatable) { + if (reifyDebug) println("tpe is locatable: reify as Ident(%s)".format(sym)) + mirrorBuildCall(nme.Ident, reify(sym)) + } + else { + if (reifyDebug) println("tpe is not locatable: reify as TypeTree(%s)".format(tpe)) + mirrorBuildCall(nme.TypeTree, reify(tpe)) + } } } tree match { - case Select(_, _) => - reifyBoundType(tree) - case SelectFromTypeTree(_, _) => - reifyBoundType(tree) - case Ident(_) => + case Select(qual, name) if name != sym.name => + reifyBoundType(Select(qual, sym.name)) + + case Select(_, _) | SelectFromTypeTree(_, _) | Ident(_) => reifyBoundType(tree) + case _ => throw new Error("internal error: %s (%s, %s) is not supported".format(tree, tree.productPrefix, tree.getClass)) } diff --git a/src/compiler/scala/reflect/reify/codegen/GenUtils.scala b/src/compiler/scala/reflect/reify/codegen/GenUtils.scala index 49877b4286..21db93d8f5 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenUtils.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenUtils.scala @@ -34,9 +34,6 @@ trait GenUtils { def mirrorSelect(name: String): Tree = termPath(nme.UNIVERSE_PREFIX + name) - def mirrorBuildSelect(name: String): Tree = - termPath(nme.UNIVERSE_BUILD_PREFIX + name) - def mirrorMirrorSelect(name: String): Tree = termPath(nme.MIRROR_PREFIX + name) diff --git a/src/compiler/scala/reflect/reify/utils/Extractors.scala b/src/compiler/scala/reflect/reify/utils/Extractors.scala index b60d15c1d4..ebbcb95481 100644 --- a/src/compiler/scala/reflect/reify/utils/Extractors.scala +++ b/src/compiler/scala/reflect/reify/utils/Extractors.scala @@ -251,6 +251,8 @@ trait Extractors { object BoundTerm { def unapply(tree: Tree): Option[Tree] = tree match { + case Select(_, name) if name.isTermName => + Some(tree) case Ident(name) if name.isTermName => Some(tree) case This(_) => diff --git a/src/compiler/scala/tools/nsc/CompilationUnits.scala b/src/compiler/scala/tools/nsc/CompilationUnits.scala index 4e7ba60d5e..355a1fd262 100644 --- a/src/compiler/scala/tools/nsc/CompilationUnits.scala +++ b/src/compiler/scala/tools/nsc/CompilationUnits.scala @@ -23,7 +23,7 @@ trait CompilationUnits { self: Global => /** One unit of compilation that has been submitted to the compiler. * It typically corresponds to a single file of source code. It includes * error-reporting hooks. */ - class CompilationUnit(val source: SourceFile) extends CompilationUnitContextApi { + class CompilationUnit(val source: SourceFile) extends CompilationUnitContextApi { self => /** the fresh name creator */ var fresh: FreshNameCreator = new FreshNameCreator.Default @@ -57,7 +57,23 @@ trait CompilationUnits { self: Global => /** Synthetic definitions generated by namer, eliminated by typer. */ - val synthetics = mutable.HashMap[Symbol, Tree]() + object synthetics { + private val map = mutable.HashMap[Symbol, Tree]() + def update(sym: Symbol, tree: Tree) { + debuglog(s"adding synthetic ($sym, $tree) to $self") + map.update(sym, tree) + } + def -=(sym: Symbol) { + debuglog(s"removing synthetic $sym from $self") + map -= sym + } + def get(sym: Symbol): Option[Tree] = logResultIf[Option[Tree]](s"found synthetic for $sym in $self", _.isDefined) { + map get sym + } + def keys: Iterable[Symbol] = map.keys + def clear(): Unit = map.clear() + override def toString = map.toString + } /** things to check at end of compilation unit */ val toCheck = new ListBuffer[() => Unit] diff --git a/src/compiler/scala/tools/nsc/Driver.scala b/src/compiler/scala/tools/nsc/Driver.scala index 1775602122..814bd58a66 100644 --- a/src/compiler/scala/tools/nsc/Driver.scala +++ b/src/compiler/scala/tools/nsc/Driver.scala @@ -54,10 +54,10 @@ abstract class Driver { doCompile(compiler) } catch { case ex: Throwable => - compiler.logThrowable(ex) + compiler.reportThrowable(ex) ex match { - case FatalError(msg) => reporter.error(null, "fatal error: " + msg) - case _ => throw ex + case FatalError(msg) => // signals that we should fail compilation. + case _ => throw ex // unexpected error, tell the outside world. } } } diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index b0288c0149..8883920325 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -292,7 +292,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter) log(msg) } - def logThrowable(t: Throwable): Unit = globalError(throwableAsString(t)) + @deprecated("Renamed to reportThrowable", "2.10.1") + def logThrowable(t: Throwable): Unit = reportThrowable(t) + def reportThrowable(t: Throwable): Unit = globalError(throwableAsString(t)) override def throwableAsString(t: Throwable) = util.stackTraceString(t) // ------------ File interface ----------------------------------------- @@ -1144,37 +1146,41 @@ class Global(var currentSettings: Settings, var reporter: Reporter) /** Don't want to introduce new errors trying to report errors, * so swallow exceptions. */ - override def supplementErrorMessage(errorMessage: String): String = try { - val tree = analyzer.lastTreeToTyper - val sym = tree.symbol - val tpe = tree.tpe - val enclosing = lastSeenContext.enclClassOrMethod.tree - - val info1 = formatExplain( - "while compiling" -> currentSource.path, - "during phase" -> ( if (globalPhase eq phase) phase else "global=%s, atPhase=%s".format(globalPhase, phase) ), - "library version" -> scala.util.Properties.versionString, - "compiler version" -> Properties.versionString, - "reconstructed args" -> settings.recreateArgs.mkString(" ") - ) - val info2 = formatExplain( - "last tree to typer" -> tree.summaryString, - "symbol" -> Option(sym).fold("null")(_.debugLocationString), - "symbol definition" -> Option(sym).fold("null")(_.defString), - "tpe" -> tpe, - "symbol owners" -> ownerChainString(sym), - "context owners" -> ownerChainString(lastSeenContext.owner) - ) - val info3: List[String] = ( - ( List("== Enclosing template or block ==", nodePrinters.nodeToString(enclosing).trim) ) - ++ ( if (tpe eq null) Nil else List("== Expanded type of tree ==", typeDeconstruct.show(tpe)) ) - ++ ( if (!opt.debug) Nil else List("== Current unit body ==", nodePrinters.nodeToString(currentUnit.body)) ) - ++ ( List(errorMessage) ) - ) - - ("\n" + info1) :: info2 :: info3 mkString "\n\n" - } - catch { case x: Exception => errorMessage } + override def supplementErrorMessage(errorMessage: String): String = + if (currentRun.supplementedError) errorMessage + else try { + val tree = analyzer.lastTreeToTyper + val sym = tree.symbol + val tpe = tree.tpe + val enclosing = lastSeenContext.enclClassOrMethod.tree + + val info1 = formatExplain( + "while compiling" -> currentSource.path, + "during phase" -> ( if (globalPhase eq phase) phase else "global=%s, atPhase=%s".format(globalPhase, phase) ), + "library version" -> scala.util.Properties.versionString, + "compiler version" -> Properties.versionString, + "reconstructed args" -> settings.recreateArgs.mkString(" ") + ) + val info2 = formatExplain( + "last tree to typer" -> tree.summaryString, + "symbol" -> Option(sym).fold("null")(_.debugLocationString), + "symbol definition" -> Option(sym).fold("null")(_.defString), + "tpe" -> tpe, + "symbol owners" -> ownerChainString(sym), + "context owners" -> ownerChainString(lastSeenContext.owner) + ) + val info3: List[String] = ( + ( List("== Enclosing template or block ==", nodePrinters.nodeToString(enclosing).trim) ) + ++ ( if (tpe eq null) Nil else List("== Expanded type of tree ==", typeDeconstruct.show(tpe)) ) + ++ ( if (!opt.debug) Nil else List("== Current unit body ==", nodePrinters.nodeToString(currentUnit.body)) ) + ++ ( List(errorMessage) ) + ) + + currentRun.supplementedError = true + + ("\n" + info1) :: info2 :: info3 mkString "\n\n" + } + catch { case x: Exception => errorMessage } /** The id of the currently active run */ @@ -1230,6 +1236,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter) /** Has any macro expansion used a fallback during this run? */ var seenMacroExpansionsFallingBack = false + /** Have we already supplemented the error message of a compiler crash? */ + private[nsc] final var supplementedError = false + /** To be initialized from firstPhase. */ private var terminalPhase: Phase = NoPhase diff --git a/src/compiler/scala/tools/nsc/ast/Positions.scala b/src/compiler/scala/tools/nsc/ast/Positions.scala index d8fb632f73..49569f5e05 100644 --- a/src/compiler/scala/tools/nsc/ast/Positions.scala +++ b/src/compiler/scala/tools/nsc/ast/Positions.scala @@ -20,7 +20,7 @@ trait Positions extends scala.reflect.internal.Positions { // When we prune due to encountering a position, traverse the // pruned children so we can warn about those lacking positions. t.children foreach { c => - if ((c eq EmptyTree) || (c eq emptyValDef)) () + if (!c.canHaveAttrs) () else if (c.pos == NoPosition) { reporter.warning(t.pos, " Positioned tree has unpositioned child in phase " + globalPhase) inform("parent: " + treeSymStatus(t)) diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index 53d35791b6..5cb43575b8 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -58,7 +58,7 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL { def mkUnchecked(expr: Tree): Tree = atPos(expr.pos) { // This can't be "Annotated(New(UncheckedClass), expr)" because annotations // are very picky about things and it crashes the compiler with "unexpected new". - Annotated(New(scalaDot(UncheckedClass.name), ListOfNil), expr) + Annotated(New(scalaDot(UncheckedClass.name), Nil), expr) } // if it's a Match, mark the selector unchecked; otherwise nothing. def mkUncheckedMatch(tree: Tree) = tree match { diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index ed73464c93..54402f0903 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -56,7 +56,7 @@ trait Trees extends scala.reflect.internal.Trees { self: Global => * The class `C` is stored as a tree attachment. */ case class InjectDerivedValue(arg: Tree) - extends SymTree + extends SymTree with TermTree class PostfixSelect(qual: Tree, name: Name) extends Select(qual, name) @@ -65,6 +65,13 @@ trait Trees extends scala.reflect.internal.Trees { self: Global => // --- factory methods ---------------------------------------------------------- + /** Factory method for a primary constructor super call `super.<init>(args_1)...(args_n)` + */ + def PrimarySuperCall(argss: List[List[Tree]]): Tree = argss match { + case Nil => Apply(gen.mkSuperSelect, Nil) + case xs :: rest => rest.foldLeft(Apply(gen.mkSuperSelect, xs): Tree)(Apply.apply) + } + /** Generates a template with constructor corresponding to * * constrmods (vparams1_) ... (vparams_n) preSuper { presupers } @@ -82,7 +89,7 @@ trait Trees extends scala.reflect.internal.Trees { self: Global => * body * } */ - def Template(parents: List[Tree], self: ValDef, constrMods: Modifiers, vparamss: List[List[ValDef]], argss: List[List[Tree]], body: List[Tree], superPos: Position): Template = { + def Template(parents: List[Tree], self: ValDef, constrMods: Modifiers, vparamss: List[List[ValDef]], body: List[Tree], superPos: Position): Template = { /* Add constructor to template */ // create parameters for <init> as synthetic trees. @@ -117,9 +124,16 @@ trait Trees extends scala.reflect.internal.Trees { self: Global => if (vparamss1.isEmpty || !vparamss1.head.isEmpty && vparamss1.head.head.mods.isImplicit) vparamss1 = List() :: vparamss1; val superRef: Tree = atPos(superPos)(gen.mkSuperSelect) - val superCall = (superRef /: argss) (Apply.apply) + val superCall = pendingSuperCall // we can't know in advance which of the parents will end up as a superclass + // this requires knowing which of the parents is a type macro and which is not + // and that's something that cannot be found out before typer + // (the type macros aren't in the trunk yet, but there is a plan for them to land there soon) + // this means that we don't know what will be the arguments of the super call + // therefore here we emit a dummy which gets populated when the template is named and typechecked List( - atPos(wrappingPos(superPos, lvdefs ::: argss.flatten)) ( + // TODO: previously this was `wrappingPos(superPos, lvdefs ::: argss.flatten)` + // is it going to be a problem that we can no longer include the `argss`? + atPos(wrappingPos(superPos, lvdefs)) ( DefDef(constrMods, nme.CONSTRUCTOR, List(), vparamss1, TypeTree(), Block(lvdefs ::: List(superCall), Literal(Constant()))))) } } @@ -137,11 +151,10 @@ trait Trees extends scala.reflect.internal.Trees { self: Global => * @param constrMods the modifiers for the class constructor, i.e. as in `class C private (...)` * @param vparamss the value parameters -- if they have symbols they * should be owned by `sym` - * @param argss the supercall arguments * @param body the template statements without primary constructor * and value parameter fields. */ - def ClassDef(sym: Symbol, constrMods: Modifiers, vparamss: List[List[ValDef]], argss: List[List[Tree]], body: List[Tree], superPos: Position): ClassDef = { + def ClassDef(sym: Symbol, constrMods: Modifiers, vparamss: List[List[ValDef]], body: List[Tree], superPos: Position): ClassDef = { // "if they have symbols they should be owned by `sym`" assert( mforall(vparamss)(p => (p.symbol eq NoSymbol) || (p.symbol.owner == sym)), @@ -151,7 +164,7 @@ trait Trees extends scala.reflect.internal.Trees { self: Global => ClassDef(sym, Template(sym.info.parents map TypeTree, if (sym.thisSym == sym || phase.erasedTypes) emptyValDef else ValDef(sym.thisSym), - constrMods, vparamss, argss, body, superPos)) + constrMods, vparamss, body, superPos)) } // --- subcomponents -------------------------------------------------- @@ -324,6 +337,8 @@ trait Trees extends scala.reflect.internal.Trees { self: Global => else super.transform { tree match { + case tree if !tree.canHaveAttrs => + tree case tpt: TypeTree => if (tpt.original != null) transform(tpt.original) @@ -337,8 +352,6 @@ trait Trees extends scala.reflect.internal.Trees { self: Global => transform(fn) case This(_) if tree.symbol != null && tree.symbol.isPackageClass => tree - case EmptyTree => - tree case _ => val dupl = tree.duplicate if (tree.hasSymbol && (!localOnly || (locals contains tree.symbol)) && !(keepLabels && tree.symbol.isLabel)) diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index a2a45d0684..33db4ee2d5 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -1562,9 +1562,9 @@ self => val nstart = in.skipToken() val npos = r2p(nstart, nstart, in.lastOffset) val tstart = in.offset - val (parents, argss, self, stats) = template(isTrait = false) + val (parents, self, stats) = template() val cpos = r2p(tstart, tstart, in.lastOffset max tstart) - makeNew(parents, self, stats, argss, npos, cpos) + makeNew(parents, self, stats, npos, cpos) case _ => syntaxErrorOrIncomplete("illegal start of simple expression", true) errorTermTree @@ -1933,7 +1933,7 @@ self => case _ => } val typeAppliedTree = in.token match { - case LBRACKET => atPos(start, in.offset)(TypeApply(convertToTypeId(t), typeArgs())) + case LBRACKET => atPos(start, in.offset)(AppliedTypeTree(convertToTypeId(t), typeArgs())) case _ => t } in.token match { @@ -2106,7 +2106,7 @@ self => def annotationExpr(): Tree = atPos(in.offset) { val t = exprSimpleType() if (in.token == LPAREN) New(t, multipleArgumentExprs()) - else New(t, ListOfNil) + else New(t, Nil) } /* -------- PARAMETERS ------------------------------------------- */ @@ -2742,20 +2742,17 @@ self => * TraitParents ::= AnnotType {with AnnotType} * }}} */ - def templateParents(isTrait: Boolean): (List[Tree], List[List[Tree]]) = { - val parents = new ListBuffer[Tree] += startAnnotType() - val argss = ( - // TODO: the insertion of ListOfNil here is where "new Foo" becomes - // indistinguishable from "new Foo()". - if (in.token == LPAREN && !isTrait) multipleArgumentExprs() - else ListOfNil - ) - - while (in.token == WITH) { - in.nextToken() - parents += startAnnotType() + def templateParents(): List[Tree] = { + val parents = new ListBuffer[Tree] + def readAppliedParent() = { + val start = in.offset + val parent = startAnnotType() + val argss = if (in.token == LPAREN) multipleArgumentExprs() else Nil + parents += atPos(start)((parent /: argss)(Apply.apply)) } - (parents.toList, argss) + readAppliedParent() + while (in.token == WITH) { in.nextToken(); readAppliedParent() } + parents.toList } /** {{{ @@ -2765,12 +2762,12 @@ self => * EarlyDef ::= Annotations Modifiers PatDef * }}} */ - def template(isTrait: Boolean): (List[Tree], List[List[Tree]], ValDef, List[Tree]) = { + def template(): (List[Tree], ValDef, List[Tree]) = { newLineOptWhenFollowedBy(LBRACE) if (in.token == LBRACE) { // @S: pre template body cannot stub like post body can! val (self, body) = templateBody(isPre = true) - if (in.token == WITH && self.isEmpty) { + if (in.token == WITH && (self eq emptyValDef)) { val earlyDefs: List[Tree] = body flatMap { case vdef @ ValDef(mods, _, _, _) if !mods.isDeferred => List(copyValDef(vdef)(mods = mods | Flags.PRESUPER)) @@ -2782,16 +2779,16 @@ self => case _ => List() } in.nextToken() - val (parents, argss) = templateParents(isTrait = isTrait) - val (self1, body1) = templateBodyOpt(traitParentSeen = isTrait) - (parents, argss, self1, earlyDefs ::: body1) + val parents = templateParents() + val (self1, body1) = templateBodyOpt(parenMeansSyntaxError = false) + (parents, self1, earlyDefs ::: body1) } else { - (List(), ListOfNil, self, body) + (List(), self, body) } } else { - val (parents, argss) = templateParents(isTrait = isTrait) - val (self, body) = templateBodyOpt(traitParentSeen = isTrait) - (parents, argss, self, body) + val parents = templateParents() + val (self, body) = templateBodyOpt(parenMeansSyntaxError = false) + (parents, self, body) } } @@ -2805,15 +2802,15 @@ self => * }}} */ def templateOpt(mods: Modifiers, name: Name, constrMods: Modifiers, vparamss: List[List[ValDef]], tstart: Int): Template = { - val (parents0, argss, self, body) = ( + val (parents0, self, body) = ( if (in.token == EXTENDS || in.token == SUBTYPE && mods.isTrait) { in.nextToken() - template(isTrait = mods.isTrait) + template() } else { newLineOptWhenFollowedBy(LBRACE) - val (self, body) = templateBodyOpt(traitParentSeen = false) - (List(), ListOfNil, self, body) + val (self, body) = templateBodyOpt(parenMeansSyntaxError = mods.isTrait || name.isTermName) + (List(), self, body) } ) def anyrefParents() = { @@ -2835,7 +2832,7 @@ self => if (inScalaRootPackage && ScalaValueClassNames.contains(name)) Template(parents0, self, anyvalConstructor :: body) else - Template(anyrefParents, self, constrMods, vparamss, argss, body, o2p(tstart)) + Template(anyrefParents, self, constrMods, vparamss, body, o2p(tstart)) } } @@ -2850,14 +2847,15 @@ self => case (self, Nil) => (self, EmptyTree.asList) case result => result } - def templateBodyOpt(traitParentSeen: Boolean): (ValDef, List[Tree]) = { + def templateBodyOpt(parenMeansSyntaxError: Boolean): (ValDef, List[Tree]) = { newLineOptWhenFollowedBy(LBRACE) if (in.token == LBRACE) { templateBody(isPre = false) } else { - if (in.token == LPAREN) - syntaxError((if (traitParentSeen) "parents of traits" else "traits or objects")+ - " may not have parameters", true) + if (in.token == LPAREN) { + if (parenMeansSyntaxError) syntaxError(s"traits or objects may not have parameters", true) + else abort("unexpected opening parenthesis") + } (emptyValDef, List()) } } diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala index 0d13623e0c..f94055f666 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala @@ -205,20 +205,26 @@ abstract class TreeBuilder { */ def makeAnonymousNew(stats: List[Tree]): Tree = { val stats1 = if (stats.isEmpty) List(Literal(Constant(()))) else stats - makeNew(Nil, emptyValDef, stats1, ListOfNil, NoPosition, NoPosition) + makeNew(Nil, emptyValDef, stats1, NoPosition, NoPosition) } /** Create positioned tree representing an object creation <new parents { stats } * @param npos the position of the new * @param cpos the position of the anonymous class starting with parents */ - def makeNew(parents: List[Tree], self: ValDef, stats: List[Tree], argss: List[List[Tree]], + def makeNew(parents: List[Tree], self: ValDef, stats: List[Tree], npos: Position, cpos: Position): Tree = if (parents.isEmpty) - makeNew(List(scalaAnyRefConstr), self, stats, argss, npos, cpos) - else if (parents.tail.isEmpty && stats.isEmpty) - atPos(npos union cpos) { New(parents.head, argss) } - else { + makeNew(List(scalaAnyRefConstr), self, stats, npos, cpos) + else if (parents.tail.isEmpty && stats.isEmpty) { + // `Parsers.template` no longer differentiates tpts and their argss + // e.g. `C()` will be represented as a single tree Apply(Ident(C), Nil) + // instead of parents = Ident(C), argss = Nil as before + // this change works great for things that are actually templates + // but in this degenerate case we need to perform postprocessing + val app = treeInfo.dissectApplied(parents.head) + atPos(npos union cpos) { New(app.callee, app.argss) } + } else { val x = tpnme.ANON_CLASS_NAME atPos(npos union cpos) { Block( @@ -226,12 +232,12 @@ abstract class TreeBuilder { atPos(cpos) { ClassDef( Modifiers(FINAL), x, Nil, - Template(parents, self, NoMods, ListOfNil, argss, stats, cpos.focus)) + Template(parents, self, NoMods, ListOfNil, stats, cpos.focus)) }), atPos(npos) { New( Ident(x) setPos npos.focus, - ListOfNil) + Nil) } ) } @@ -285,7 +291,7 @@ abstract class TreeBuilder { def makeGenerator(pos: Position, pat: Tree, valeq: Boolean, rhs: Tree): Enumerator = { val pat1 = patvarTransformer.transform(pat) val rhs1 = - if (valeq || treeInfo.isVariablePattern(pat)) rhs + if (valeq || treeInfo.isVarPatternDeep(pat)) rhs else makeFilter(rhs, pat1.duplicate, nme.CHECK_IF_REFUTABLE_STRING) if (valeq) ValEq(pos, pat1, rhs1) diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index ea4e8475f9..fd2b11898c 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -753,7 +753,8 @@ abstract class GenICode extends SubComponent { } else ctx1.bb.emit(CONSTANT(Constant(false))) } else if (r.isValueType && cast) { - assert(false, tree) /* Erasure should have added an unboxing operation to prevent that. */ + /* Erasure should have added an unboxing operation to prevent that. */ + abort("should have been unboxed by erasure: " + tree) } else if (r.isValueType) { ctx.bb.emit(IS_INSTANCE(REFERENCE(definitions.boxedClass(r.toType.typeSymbol)))) } else { @@ -1257,7 +1258,7 @@ abstract class GenICode extends SubComponent { val sym = ( if (!tree.symbol.isPackageClass) tree.symbol else tree.symbol.info.member(nme.PACKAGE) match { - case NoSymbol => assert(false, "Cannot use package as value: " + tree) ; NoSymbol + case NoSymbol => abort("Cannot use package as value: " + tree) case s => debugwarn("Bug: found package class where package object expected. Converting.") ; s.moduleClass } ) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index 6eb05c4402..d185ed0c34 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -21,7 +21,7 @@ import asm.Label * * Documentation at http://lamp.epfl.ch/~magarcia/ScalaCompilerCornerReloaded/2012Q2/GenASM.pdf */ -abstract class GenASM extends SubComponent with BytecodeWriters { +abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { import global._ import icodes._ import icodes.opcodes._ @@ -32,20 +32,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters { /** Create a new phase */ override def newPhase(p: Phase): Phase = new AsmPhase(p) - private def outputDirectory(sym: Symbol): AbstractFile = - settings.outputDirs outputDirFor beforeFlatten(sym.sourceFile) - - private def getFile(base: AbstractFile, clsName: String, suffix: String): AbstractFile = { - var dir = base - val pathParts = clsName.split("[./]").toList - for (part <- pathParts.init) { - dir = dir.subdirectoryNamed(part) - } - dir.fileNamed(pathParts.last + suffix) - } - private def getFile(sym: Symbol, clsName: String, suffix: String): AbstractFile = - getFile(outputDirectory(sym), clsName, suffix) - /** JVM code generation phase */ class AsmPhase(prev: Phase) extends ICodePhase(prev) { @@ -55,62 +41,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters { val BeanInfoAttr = rootMirror.getRequiredClass("scala.beans.BeanInfo") - def isJavaEntryPoint(icls: IClass) = { - val sym = icls.symbol - def fail(msg: String, pos: Position = sym.pos) = { - icls.cunit.warning(sym.pos, - sym.name + " has a main method with parameter type Array[String], but " + sym.fullName('.') + " will not be a runnable program.\n" + - " Reason: " + msg - // TODO: make this next claim true, if possible - // by generating valid main methods as static in module classes - // not sure what the jvm allows here - // + " You can still run the program by calling it as " + sym.javaSimpleName + " instead." - ) - false - } - def failNoForwarder(msg: String) = { - fail(msg + ", which means no static forwarder can be generated.\n") - } - val possibles = if (sym.hasModuleFlag) (sym.tpe nonPrivateMember nme.main).alternatives else Nil - val hasApproximate = possibles exists { m => - m.info match { - case MethodType(p :: Nil, _) => p.tpe.typeSymbol == ArrayClass - case _ => false - } - } - // At this point it's a module with a main-looking method, so either succeed or warn that it isn't. - hasApproximate && { - // Before erasure so we can identify generic mains. - beforeErasure { - val companion = sym.linkedClassOfClass - val companionMain = companion.tpe.member(nme.main) - - if (hasJavaMainMethod(companion)) - failNoForwarder("companion contains its own main method") - else if (companion.tpe.member(nme.main) != NoSymbol) - // this is only because forwarders aren't smart enough yet - failNoForwarder("companion contains its own main method (implementation restriction: no main is allowed, regardless of signature)") - else if (companion.isTrait) - failNoForwarder("companion is a trait") - // Now either succeeed, or issue some additional warnings for things which look like - // attempts to be java main methods. - else possibles exists { m => - m.info match { - case PolyType(_, _) => - fail("main methods cannot be generic.") - case MethodType(params, res) => - if (res.typeSymbol :: params exists (_.isAbstractType)) - fail("main methods cannot refer to type parameters or abstract types.", m.pos) - else - isJavaMainMethod(m) || fail("main method must have exact signature (Array[String])Unit", m.pos) - case tp => - fail("don't know what this is: " + tp, m.pos) - } - } - } - } - } - private def initBytecodeWriter(entryPoints: List[IClass]): BytecodeWriter = { settings.outputDirs.getSingleOutput match { case Some(f) if f hasExtension "jar" => @@ -160,7 +90,14 @@ abstract class GenASM extends SubComponent with BytecodeWriters { } // For predictably ordered error messages. - var sortedClasses = classes.values.toList sortBy ("" + _.symbol.fullName) + var sortedClasses = classes.values.toList sortBy (_.symbol.fullName) + + // Warn when classes will overwrite one another on case-insensitive systems. + for ((_, v1 :: v2 :: _) <- sortedClasses groupBy (_.symbol.javaClassName.toString.toLowerCase)) { + v1.cunit.warning(v1.symbol.pos, + s"Class ${v1.symbol.javaClassName} differs only in case from ${v2.symbol.javaClassName}. " + + "Such classes will overwrite one another on case-insensitive filesystems.") + } debuglog("Created new bytecode generator for " + classes.size + " classes.") val bytecodeWriter = initBytecodeWriter(sortedClasses filter isJavaEntryPoint) @@ -1090,12 +1027,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters { // a plain class lacking companion module, for details see `isCandidateForForwarders`). // ----------------------------------------------------------------------------------------- - val ExcludedForwarderFlags = { - import Flags._ - // Should include DEFERRED but this breaks findMember. - ( CASE | SPECIALIZED | LIFTED | PROTECTED | STATIC | EXPANDEDNAME | BridgeAndPrivateFlags ) - } - /** Add a forwarder for method m. Used only from addForwarders(). */ private def addForwarder(isRemoteClass: Boolean, jclass: asm.ClassVisitor, module: Symbol, m: Symbol) { val moduleName = javaName(module) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index 3d29b2590e..fe0020e074 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -26,7 +26,7 @@ import scala.language.postfixOps * @version 1.0 * */ -abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with BytecodeWriters { +abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with BytecodeWriters with GenJVMASM { import global._ import icodes._ import icodes.opcodes._ @@ -37,20 +37,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with /** Create a new phase */ override def newPhase(p: Phase): Phase = new JvmPhase(p) - private def outputDirectory(sym: Symbol): AbstractFile = - settings.outputDirs outputDirFor beforeFlatten(sym.sourceFile) - - private def getFile(base: AbstractFile, clsName: String, suffix: String): AbstractFile = { - var dir = base - val pathParts = clsName.split("[./]").toList - for (part <- pathParts.init) { - dir = dir.subdirectoryNamed(part) - } - dir.fileNamed(pathParts.last + suffix) - } - private def getFile(sym: Symbol, clsName: String, suffix: String): AbstractFile = - getFile(outputDirectory(sym), clsName, suffix) - /** JVM code generation phase */ class JvmPhase(prev: Phase) extends ICodePhase(prev) { @@ -58,63 +44,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with override def erasedTypes = true def apply(cls: IClass) = sys.error("no implementation") - def isJavaEntryPoint(clasz: IClass) = { - val sym = clasz.symbol - def fail(msg: String, pos: Position = sym.pos) = { - clasz.cunit.warning(sym.pos, - sym.name + " has a main method with parameter type Array[String], but " + sym.fullName('.') + " will not be a runnable program.\n" + - " Reason: " + msg - // TODO: make this next claim true, if possible - // by generating valid main methods as static in module classes - // not sure what the jvm allows here - // + " You can still run the program by calling it as " + sym.javaSimpleName + " instead." - ) - false - } - def failNoForwarder(msg: String) = { - fail(msg + ", which means no static forwarder can be generated.\n") - } - val possibles = if (sym.hasModuleFlag) (sym.tpe nonPrivateMember nme.main).alternatives else Nil - val hasApproximate = possibles exists { m => - m.info match { - case MethodType(p :: Nil, _) => p.tpe.typeSymbol == ArrayClass - case _ => false - } - } - // At this point it's a module with a main-looking method, so either - // succeed or warn that it isn't. - hasApproximate && { - // Before erasure so we can identify generic mains. - beforeErasure { - val companion = sym.linkedClassOfClass - val companionMain = companion.tpe.member(nme.main) - - if (hasJavaMainMethod(companion)) - failNoForwarder("companion contains its own main method") - else if (companion.tpe.member(nme.main) != NoSymbol) - // this is only because forwarders aren't smart enough yet - failNoForwarder("companion contains its own main method (implementation restriction: no main is allowed, regardless of signature)") - else if (companion.isTrait) - failNoForwarder("companion is a trait") - // Now either succeeed, or issue some additional warnings for things which look like - // attempts to be java main methods. - else possibles exists { m => - m.info match { - case PolyType(_, _) => - fail("main methods cannot be generic.") - case MethodType(params, res) => - if (res.typeSymbol :: params exists (_.isAbstractType)) - fail("main methods cannot refer to type parameters or abstract types.", m.pos) - else - isJavaMainMethod(m) || fail("main method must have exact signature (Array[String])Unit", m.pos) - case tp => - fail("don't know what this is: " + tp, m.pos) - } - } - } - } - } - override def run() { // we reinstantiate the bytecode generator at each run, to allow the GC // to collect everything @@ -210,12 +139,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with val BeanDisplayNameAttr = rootMirror.getRequiredClass("scala.beans.BeanDisplayName") val BeanDescriptionAttr = rootMirror.getRequiredClass("scala.beans.BeanDescription") - final val ExcludedForwarderFlags = { - import Flags._ - // Should include DEFERRED but this breaks findMember. - ( CASE | SPECIALIZED | LIFTED | PROTECTED | STATIC | EXPANDEDNAME | BridgeAndPrivateFlags ) - } - // Additional interface parents based on annotations and other cues def newParentForAttr(attr: Symbol): Option[Symbol] = attr match { case SerializableAttr => Some(SerializableClass) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVMASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVMASM.scala new file mode 100644 index 0000000000..49c0fa2757 --- /dev/null +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVMASM.scala @@ -0,0 +1,97 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2013 LAMP/EPFL + * @author Jason Zaugg + */ + +package scala.tools.nsc +package backend.jvm +import scala.tools.nsc.io.AbstractFile +import scala.tools.nsc.symtab._ + +/** Code shared between the legagy backend [[scala.tools.nsc.backend.jvm.GenJVM]] + * and the new backend [[scala.tools.nsc.backend.jvm.GenASM]]. There should be + * more here, but for now I'm starting with the refactorings that are either + * straightforward to review or necessary for maintenance. + */ +trait GenJVMASM { + val global: Global + import global._ + import icodes._ + import definitions._ + + protected def outputDirectory(sym: Symbol): AbstractFile = + settings.outputDirs outputDirFor beforeFlatten(sym.sourceFile) + + protected def getFile(base: AbstractFile, clsName: String, suffix: String): AbstractFile = { + var dir = base + val pathParts = clsName.split("[./]").toList + for (part <- pathParts.init) { + dir = dir.subdirectoryNamed(part) + } + dir.fileNamed(pathParts.last + suffix) + } + protected def getFile(sym: Symbol, clsName: String, suffix: String): AbstractFile = + getFile(outputDirectory(sym), clsName, suffix) + + protected val ExcludedForwarderFlags = { + import Flags._ + // Should include DEFERRED but this breaks findMember. + ( CASE | SPECIALIZED | LIFTED | PROTECTED | STATIC | EXPANDEDNAME | BridgeAndPrivateFlags | MACRO ) + } + + protected def isJavaEntryPoint(icls: IClass) = { + val sym = icls.symbol + def fail(msg: String, pos: Position = sym.pos) = { + icls.cunit.warning(sym.pos, + sym.name + " has a main method with parameter type Array[String], but " + sym.fullName('.') + " will not be a runnable program.\n" + + " Reason: " + msg + // TODO: make this next claim true, if possible + // by generating valid main methods as static in module classes + // not sure what the jvm allows here + // + " You can still run the program by calling it as " + sym.javaSimpleName + " instead." + ) + false + } + def failNoForwarder(msg: String) = { + fail(msg + ", which means no static forwarder can be generated.\n") + } + val possibles = if (sym.hasModuleFlag) (sym.tpe nonPrivateMember nme.main).alternatives else Nil + val hasApproximate = possibles exists { m => + m.info match { + case MethodType(p :: Nil, _) => p.tpe.typeSymbol == ArrayClass + case _ => false + } + } + // At this point it's a module with a main-looking method, so either succeed or warn that it isn't. + hasApproximate && { + // Before erasure so we can identify generic mains. + beforeErasure { + val companion = sym.linkedClassOfClass + val companionMain = companion.tpe.member(nme.main) + + if (hasJavaMainMethod(companion)) + failNoForwarder("companion contains its own main method") + else if (companion.tpe.member(nme.main) != NoSymbol) + // this is only because forwarders aren't smart enough yet + failNoForwarder("companion contains its own main method (implementation restriction: no main is allowed, regardless of signature)") + else if (companion.isTrait) + failNoForwarder("companion is a trait") + // Now either succeeed, or issue some additional warnings for things which look like + // attempts to be java main methods. + else possibles exists { m => + m.info match { + case PolyType(_, _) => + fail("main methods cannot be generic.") + case MethodType(params, res) => + if (res.typeSymbol :: params exists (_.isAbstractType)) + fail("main methods cannot refer to type parameters or abstract types.", m.pos) + else + isJavaMainMethod(m) || fail("main method must have exact signature (Array[String])Unit", m.pos) + case tp => + fail("don't know what this is: " + tp, m.pos) + } + } + } + } + } +} diff --git a/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala index bb14c3dce0..23f932b5b4 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala @@ -147,18 +147,18 @@ abstract class ClosureElimination extends SubComponent { case _ => } - case UNBOX(_) => + case UNBOX(boxType) => info.stack match { case Deref(LocalVar(loc1)) :: _ if info.bindings isDefinedAt LocalVar(loc1) => val value = info.getBinding(loc1) value match { - case Boxed(LocalVar(loc2)) => + case Boxed(LocalVar(loc2)) if loc2.kind == boxType => bb.replaceInstruction(i, DROP(icodes.ObjectReference) :: valueToInstruction(info.getBinding(loc2)) :: Nil) debuglog("replaced " + i + " with " + info.getBinding(loc2)) case _ => () } - case Boxed(LocalVar(loc1)) :: _ => + case Boxed(LocalVar(loc1)) :: _ if loc1.kind == boxType => val loc2 = info.getAlias(loc1) bb.replaceInstruction(i, DROP(icodes.ObjectReference) :: valueToInstruction(Deref(LocalVar(loc2))) :: Nil) debuglog("replaced " + i + " with " + LocalVar(loc2)) diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala index 4c7f5dc9c6..ea074873e8 100644 --- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala @@ -950,7 +950,16 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { // units.filter should return only one element (currentRun.units filter (_.source.file == aSym.sourceFile)).toList match { case List(unit) => - (unit.body find (_.symbol == aSym)) match { + // SI-4922 `sym == aSym` is insufficent if `aSym` is a clone of symbol + // of the parameter in the tree, as can happen with type parametric methods. + def isCorrespondingParam(sym: Symbol) = ( + sym != null && + sym != NoSymbol && + sym.owner == aSym.owner && + sym.name == aSym.name && + sym.isParamWithDefault + ) + (unit.body find (t => isCorrespondingParam(t.symbol))) match { case Some(ValDef(_,_,_,rhs)) => makeTree(rhs) case _ => None } diff --git a/src/compiler/scala/tools/nsc/interactive/RangePositions.scala b/src/compiler/scala/tools/nsc/interactive/RangePositions.scala index b95f1fa7ca..64117bd8ee 100644 --- a/src/compiler/scala/tools/nsc/interactive/RangePositions.scala +++ b/src/compiler/scala/tools/nsc/interactive/RangePositions.scala @@ -144,7 +144,7 @@ self: scala.tools.nsc.Global => */ private def setChildrenPos(pos: Position, trees: List[Tree]): Unit = try { for (tree <- trees) { - if (!tree.isEmpty && tree.pos == NoPosition) { + if (!tree.isEmpty && tree.canHaveAttrs && tree.pos == NoPosition) { val children = tree.children if (children.isEmpty) { tree setPos pos.focus @@ -165,7 +165,7 @@ self: scala.tools.nsc.Global => */ override def atPos[T <: Tree](pos: Position)(tree: T): T = { if (pos.isOpaqueRange) { - if (!tree.isEmpty && tree.pos == NoPosition) { + if (!tree.isEmpty && tree.canHaveAttrs && tree.pos == NoPosition) { tree.setPos(pos) val children = tree.children if (children.nonEmpty) { @@ -203,7 +203,7 @@ self: scala.tools.nsc.Global => def validate(tree: Tree, encltree: Tree): Unit = { - if (!tree.isEmpty) { + if (!tree.isEmpty && tree.canHaveAttrs) { if (settings.Yposdebug.value && (settings.verbose.value || settings.Yrangepos.value)) println("[%10s] %s".format("validate", treeStatus(tree, encltree))) diff --git a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala index 12fb8f1507..67519cf90c 100644 --- a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala +++ b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala @@ -120,7 +120,7 @@ trait MemberHandlers { if (replProps.vids) """" + " @ " + "%%8x".format(System.identityHashCode(%s)) + " """.trim.format(req fullPath name) else "" - """ + "%s%s: %s = " + %s""".format(prettyName, vidString, string2code(req typeOf name), resultString) + """ + "%s%s: %s = " + %s""".format(string2code(prettyName), vidString, string2code(req typeOf name), resultString) } } } @@ -147,8 +147,7 @@ trait MemberHandlers { override def resultExtractionCode(req: Request) = { val lhsType = string2code(req lookupTypeOf name) val res = string2code(req fullPath name) - - """ + "%s: %s = " + %s + "\n" """.format(lhs, lhsType, res) + "\n" + """ + "%s: %s = " + %s + "\n" """.format(string2code(lhs.toString), lhsType, res) + "\n" } } diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala index 43a8402fc7..050f7a8f95 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala @@ -551,7 +551,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { if (parentToken == AT && in.token == DEFAULT) { val annot = atPos(pos) { - New(Select(scalaDot(nme.runtime), tpnme.AnnotationDefaultATTR), ListOfNil) + New(Select(scalaDot(nme.runtime), tpnme.AnnotationDefaultATTR), Nil) } mods1 = mods1 withAnnotations List(annot) skipTo(SEMI) diff --git a/src/compiler/scala/tools/nsc/reporters/Reporter.scala b/src/compiler/scala/tools/nsc/reporters/Reporter.scala index c5321dd728..8871ae6555 100644 --- a/src/compiler/scala/tools/nsc/reporters/Reporter.scala +++ b/src/compiler/scala/tools/nsc/reporters/Reporter.scala @@ -20,9 +20,15 @@ abstract class Reporter { class Severity(val id: Int) extends severity.Value { var count: Int = 0 } - val INFO = new Severity(0) - val WARNING = new Severity(1) - val ERROR = new Severity(2) + val INFO = new Severity(0) { + override def toString: String = "INFO" + } + val WARNING = new Severity(1) { + override def toString: String = "WARNING" + } + val ERROR = new Severity(2) { + override def toString: String = "ERROR" + } /** Whether very long lines can be truncated. This exists so important * debugging information (like printing the classpath) is not rendered diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala index b9eb1ba0cd..25b7813646 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala @@ -198,7 +198,7 @@ abstract class Pickler extends SubComponent { case RefinedType(parents, decls) => val rclazz = tp.typeSymbol for (m <- decls.iterator) - if (m.owner != rclazz) assert(false, "bad refinement member "+m+" of "+tp+", owner = "+m.owner) + if (m.owner != rclazz) abort("bad refinement member "+m+" of "+tp+", owner = "+m.owner) putSymbol(rclazz); putTypes(parents); putSymbols(decls.toList) case ClassInfoType(parents, decls, clazz) => putSymbol(clazz); putTypes(parents); putSymbols(decls.toList) diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index 4092d1262a..ec0797acb5 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -68,7 +68,7 @@ abstract class Constructors extends Transform with ast.TreeDSL { def matchesName(param: Symbol) = param.name == name || param.name.startsWith(name + nme.NAME_JOIN_STRING) (constrParams filter matchesName) match { - case Nil => assert(false, name + " not in " + constrParams) ; null + case Nil => abort(name + " not in " + constrParams) case p :: _ => p } } @@ -511,7 +511,6 @@ abstract class Constructors extends Transform with ast.TreeDSL { sym = closureClass, constrMods = Modifiers(0), vparamss = List(List(outerFieldDef)), - argss = ListOfNil, body = List(applyMethodDef), superPos = impl.pos) } diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 7b45b3efe5..7b9b13ae1c 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -437,19 +437,19 @@ abstract class Erasure extends AddInterfaces noclash = false unit.error( if (member.owner == root) member.pos else root.pos, - s"""bridge generated for member ${fulldef(member)} - |which overrides ${fulldef(other)} - |clashes with definition of $what; - |both have erased type ${afterPostErasure(bridge.tpe)}""".stripMargin) + sm"""bridge generated for member ${fulldef(member)} + |which overrides ${fulldef(other)} + |clashes with definition of $what; + |both have erased type ${afterPostErasure(bridge.tpe)}""") } for (bc <- root.baseClasses) { if (settings.debug.value) afterPostErasure(println( - s"""check bridge overrides in $bc - ${bc.info.nonPrivateDecl(bridge.name)} - ${site.memberType(bridge)} - ${site.memberType(bc.info.nonPrivateDecl(bridge.name) orElse IntClass)} - ${(bridge.matchingSymbol(bc, site))}""".stripMargin)) + sm"""check bridge overrides in $bc + |${bc.info.nonPrivateDecl(bridge.name)} + |${site.memberType(bridge)} + |${site.memberType(bc.info.nonPrivateDecl(bridge.name) orElse IntClass)} + |${(bridge.matchingSymbol(bc, site))}""")) def overriddenBy(sym: Symbol) = sym.matchingSymbol(bc, site).alternatives filter (sym => !sym.isBridge) @@ -693,7 +693,7 @@ abstract class Erasure extends AddInterfaces adaptToType(unbox(tree, pt), pt) else if (isPrimitiveValueType(tree.tpe) && !isPrimitiveValueType(pt)) { adaptToType(box(tree, pt.toString), pt) - } else if (tree.tpe.isInstanceOf[MethodType] && tree.tpe.params.isEmpty) { + } else if (isMethodTypeWithEmptyParams(tree.tpe)) { // [H] this assert fails when trying to typecheck tree !(SomeClass.this.bitmap) for single lazy val //assert(tree.symbol.isStable, "adapt "+tree+":"+tree.tpe+" to "+pt) adaptToType(Apply(tree, List()) setPos tree.pos setType tree.tpe.resultType, pt) @@ -783,16 +783,21 @@ abstract class Erasure extends AddInterfaces else if (!isPrimitiveValueType(qual1.tpe) && isPrimitiveValueMember(tree.symbol)) qual1 = unbox(qual1, tree.symbol.owner.tpe) - if (isPrimitiveValueMember(tree.symbol) && !isPrimitiveValueType(qual1.tpe)) + def selectFrom(qual: Tree) = treeCopy.Select(tree, qual, name) + + if (isPrimitiveValueMember(tree.symbol) && !isPrimitiveValueType(qual1.tpe)) { tree.symbol = NoSymbol - else if (qual1.tpe.isInstanceOf[MethodType] && qual1.tpe.params.isEmpty) { + selectFrom(qual1) + } else if (isMethodTypeWithEmptyParams(qual1.tpe)) { assert(qual1.symbol.isStable, qual1.symbol); - qual1 = Apply(qual1, List()) setPos qual1.pos setType qual1.tpe.resultType + val applied = Apply(qual1, List()) setPos qual1.pos setType qual1.tpe.resultType + adaptMember(selectFrom(applied)) } else if (!(qual1.isInstanceOf[Super] || (qual1.tpe.typeSymbol isSubClass tree.symbol.owner))) { assert(tree.symbol.owner != ArrayClass) - qual1 = cast(qual1, tree.symbol.owner.tpe) + selectFrom(cast(qual1, tree.symbol.owner.tpe)) + } else { + selectFrom(qual1) } - treeCopy.Select(tree, qual1, name) } case SelectFromArray(qual, name, erasure) => var qual1 = typedQualifier(qual) @@ -870,6 +875,11 @@ abstract class Erasure extends AddInterfaces tree1 } } + + private def isMethodTypeWithEmptyParams(tpe: Type) = tpe match { + case MethodType(Nil, _) => true + case _ => false + } } /** The erasure transformer */ diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala index 6cc957a9eb..6f3d7932a5 100644 --- a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala +++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala @@ -173,9 +173,7 @@ abstract class ExtensionMethods extends Transform with TypingTransformers { List(This(currentOwner))) val extensionCall = atOwner(origMeth) { localTyper.typedPos(rhs.pos) { - (extensionCallPrefix /: vparamss) { - case (fn, params) => Apply(fn, params map (param => Ident(param.symbol))) - } + gen.mkForwarder(extensionCallPrefix, mmap(vparamss)(_.symbol)) } } deriveDefDef(tree)(_ => extensionCall) diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 64bb98e2c5..57bdaea17a 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -269,7 +269,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { /** Mix in members of implementation class mixinClass into class clazz */ def mixinImplClassMembers(mixinClass: Symbol, mixinInterface: Symbol) { - assert(mixinClass.isImplClass, "Not an impl class:" + + if (!mixinClass.isImplClass) debugwarn ("Impl class flag is not set " + ((mixinClass.debugLocationString, mixinInterface.debugLocationString))) for (member <- mixinClass.info.decls ; if isForwarded(member)) { @@ -360,7 +360,6 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { // first complete the superclass with mixed in members addMixedinMembers(clazz.superClass, unit) - //Console.println("adding members of " + clazz.info.baseClasses.tail.takeWhile(superclazz !=) + " to " + clazz);//DEBUG for (mc <- clazz.mixinClasses ; if mc hasFlag lateINTERFACE) { // @SEAN: adding trait tracking so we don't have to recompile transitive closures unit.depends += mc @@ -871,8 +870,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { val cond = Apply(Select(moduleVarRef, nme.eq), List(NULL)) mkFastPathBody(clazz, moduleSym, cond, List(assign), List(NULL), returnTree, attrThis, args) case _ => - assert(false, "Invalid getter " + rhs + " for module in class " + clazz) - EmptyTree + abort("Invalid getter " + rhs + " for module in class " + clazz) } def mkCheckedAccessor(clazz: Symbol, retVal: Tree, offset: Int, pos: Position, fieldSym: Symbol): Tree = { diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index 2f79472cfb..bbab545d9e 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -965,6 +965,11 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { case (NoSymbol, _) => None case (overridden, env) => val om = specializedOverload(clazz, overridden, env) + foreachWithIndex(om.paramss) { (params, i) => + foreachWithIndex(params) { (param, j) => + param.name = overriding.paramss(i)(j).name // SI-6555 Retain the parameter names from the subclass. + } + } debuglog("specialized overload %s for %s in %s: %s".format(om, overriding.name.decode, pp(env), om.info)) typeEnv(om) = env addConcreteSpecMethod(overriding) diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala index 95cb052fda..a767850cba 100644 --- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala +++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala @@ -327,8 +327,16 @@ abstract class TailCalls extends Transform { transformTrees(cases).asInstanceOf[List[CaseDef]] ) + case Try(block, catches, finalizer @ EmptyTree) => + // SI-1672 Catches are in tail position when there is no finalizer + treeCopy.Try(tree, + noTailTransform(block), + transformTrees(catches).asInstanceOf[List[CaseDef]], + EmptyTree + ) + case Try(block, catches, finalizer) => - // no calls inside a try are in tail position, but keep recursing for nested functions + // no calls inside a try are in tail position if there is a finalizer, but keep recursing for nested functions treeCopy.Try(tree, noTailTransform(block), noTailTransforms(catches).asInstanceOf[List[CaseDef]], diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index f6b55b6606..838ea7d5a0 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -251,7 +251,10 @@ abstract class UnCurry extends InfoTransform val applyMethodDef = { val methSym = anonClass.newMethod(nme.apply, fun.pos, FINAL) - methSym setInfoAndEnter MethodType(methSym newSyntheticValueParams formals, restpe) + val paramSyms = map2(formals, fun.vparams) { + (tp, param) => methSym.newSyntheticValueParam(tp, param.name) + } + methSym setInfoAndEnter MethodType(paramSyms, restpe) fun.vparams foreach (_.symbol.owner = methSym) fun.body changeOwner (fun.symbol -> methSym) @@ -267,7 +270,7 @@ abstract class UnCurry extends InfoTransform localTyper.typedPos(fun.pos) { Block( - List(ClassDef(anonClass, NoMods, ListOfNil, ListOfNil, List(applyMethodDef), fun.pos)), + List(ClassDef(anonClass, NoMods, ListOfNil, List(applyMethodDef), fun.pos)), Typed(New(anonClass.tpe), TypeTree(fun.tpe))) } @@ -369,7 +372,7 @@ abstract class UnCurry extends InfoTransform } val isDefinedAtMethodDef = { - val methSym = anonClass.newMethod(nme.isDefinedAt, fun.pos, FINAL) + val methSym = anonClass.newMethod(nme.isDefinedAt, fun.pos, FINAL | SYNTHETIC) val params = methSym newSyntheticValueParams formals methSym setInfoAndEnter MethodType(params, BooleanClass.tpe) @@ -392,7 +395,7 @@ abstract class UnCurry extends InfoTransform localTyper.typedPos(fun.pos) { Block( - List(ClassDef(anonClass, NoMods, ListOfNil, ListOfNil, List(applyOrElseMethodDef, isDefinedAtMethodDef), fun.pos)), + List(ClassDef(anonClass, NoMods, ListOfNil, List(applyOrElseMethodDef, isDefinedAtMethodDef), fun.pos)), Typed(New(anonClass.tpe), TypeTree(fun.tpe))) } } diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index 9e9b8b995b..ae3b0bc0b7 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -107,9 +107,9 @@ trait ContextErrors { s"$name extends Any, not AnyRef" ) if (isPrimitiveValueType(found) || isTrivialTopType(tp)) "" else "\n" + - s"""|Note that $what. - |Such types can participate in value classes, but instances - |cannot appear in singleton types or in reference comparisons.""".stripMargin + sm"""|Note that $what. + |Such types can participate in value classes, but instances + |cannot appear in singleton types or in reference comparisons.""" } import ErrorUtils._ @@ -184,14 +184,18 @@ trait ContextErrors { } def ParentTypesError(templ: Template, ex: TypeError) = { - templ.tpe = null - issueNormalTypeError(templ, ex.getMessage()) + templ.tpe = null + issueNormalTypeError(templ, ex.getMessage()) + setError(templ) } // additional parentTypes errors - def ConstrArgsInTraitParentTpeError(arg: Tree, parent: Symbol) = + def ConstrArgsInParentWhichIsTraitError(arg: Tree, parent: Symbol) = issueNormalTypeError(arg, parent + " is a trait; does not take constructor arguments") + def ConstrArgsInParentOfTraitError(arg: Tree, parent: Symbol) = + issueNormalTypeError(arg, "parents of traits may not have parameters") + def MissingTypeArgumentsParentTpeError(supertpt: Tree) = issueNormalTypeError(supertpt, "missing type arguments") @@ -1043,9 +1047,6 @@ trait ContextErrors { def MaxParametersCaseClassError(tree: Tree) = issueNormalTypeError(tree, "Implementation restriction: case classes cannot have more than " + definitions.MaxFunctionArity + " parameters.") - def InheritsItselfError(tree: Tree) = - issueNormalTypeError(tree, tree.tpe.typeSymbol+" inherits itself") - def MissingParameterOrValTypeError(vparam: Tree) = issueNormalTypeError(vparam, "missing parameter type") @@ -1128,9 +1129,9 @@ trait ContextErrors { (isView: Boolean, pt: Type, tree: Tree)(implicit context0: Context) = { if (!info1.tpe.isErroneous && !info2.tpe.isErroneous) { def coreMsg = - s"""| $pre1 ${info1.sym.fullLocationString} of type ${info1.tpe} - | $pre2 ${info2.sym.fullLocationString} of type ${info2.tpe} - | $trailer""".stripMargin + sm"""| $pre1 ${info1.sym.fullLocationString} of type ${info1.tpe} + | $pre2 ${info2.sym.fullLocationString} of type ${info2.tpe} + | $trailer""" def viewMsg = { val found :: req :: _ = pt.typeArgs def explanation = { @@ -1141,19 +1142,19 @@ trait ContextErrors { // involving Any, are further explained from foundReqMsg. if (AnyRefClass.tpe <:< req) ( if (sym == AnyClass || sym == UnitClass) ( - s"""|Note: ${sym.name} is not implicitly converted to AnyRef. You can safely - |pattern match `x: AnyRef` or cast `x.asInstanceOf[AnyRef]` to do so.""".stripMargin + sm"""|Note: ${sym.name} is not implicitly converted to AnyRef. You can safely + |pattern match `x: AnyRef` or cast `x.asInstanceOf[AnyRef]` to do so.""" ) else boxedClass get sym map (boxed => - s"""|Note: an implicit exists from ${sym.fullName} => ${boxed.fullName}, but - |methods inherited from Object are rendered ambiguous. This is to avoid - |a blanket implicit which would convert any ${sym.fullName} to any AnyRef. - |You may wish to use a type ascription: `x: ${boxed.fullName}`.""".stripMargin + sm"""|Note: an implicit exists from ${sym.fullName} => ${boxed.fullName}, but + |methods inherited from Object are rendered ambiguous. This is to avoid + |a blanket implicit which would convert any ${sym.fullName} to any AnyRef. + |You may wish to use a type ascription: `x: ${boxed.fullName}`.""" ) getOrElse "" ) else - s"""|Note that implicit conversions are not applicable because they are ambiguous: - |${coreMsg}are possible conversion functions from $found to $req""".stripMargin + sm"""|Note that implicit conversions are not applicable because they are ambiguous: + |${coreMsg}are possible conversion functions from $found to $req""" } typeErrorMsg(found, req, infer.isPossiblyMissingArgs(found, req)) + ( if (explanation == "") "" else "\n" + explanation @@ -1279,7 +1280,10 @@ trait ContextErrors { fail() } - private def implRefError(message: String) = genericError(methPart(macroDdef.rhs), message) + private def implRefError(message: String) = { + val treeInfo.Applied(implRef, _, _) = macroDdef.rhs + genericError(implRef, message) + } private def compatibilityError(message: String) = implRefError( diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index 507825ff15..0907f1088a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -510,8 +510,8 @@ trait Contexts { self: Analyzer => /* var c = this while (c != NoContext && c.owner != owner) { - if (c.outer eq null) assert(false, "accessWithin(" + owner + ") " + c);//debug - if (c.outer.enclClass eq null) assert(false, "accessWithin(" + owner + ") " + c);//debug + if (c.outer eq null) abort("accessWithin(" + owner + ") " + c);//debug + if (c.outer.enclClass eq null) abort("accessWithin(" + owner + ") " + c);//debug c = c.outer.enclClass } c != NoContext diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 547d756888..ad01de9447 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -149,9 +149,20 @@ trait Implicits { class SearchResult(val tree: Tree, val subst: TreeTypeSubstituter) { override def toString = "SearchResult(%s, %s)".format(tree, if (subst.isEmpty) "" else subst) + + def isFailure = false + def isAmbiguousFailure = false + final def isSuccess = !isFailure } - lazy val SearchFailure = new SearchResult(EmptyTree, EmptyTreeTypeSubstituter) + lazy val SearchFailure = new SearchResult(EmptyTree, EmptyTreeTypeSubstituter) { + override def isFailure = true + } + + lazy val AmbiguousSearchFailure = new SearchResult(EmptyTree, EmptyTreeTypeSubstituter) { + override def isFailure = true + override def isAmbiguousFailure = true + } /** A class that records an available implicit * @param name The name of the implicit @@ -831,7 +842,7 @@ trait Implicits { catch divergenceHandler tryImplicitInfo(i) match { - case SearchFailure => + case sr if sr.isFailure => // We don't want errors that occur during checking implicit info // to influence the check of further infos. context.condBufferFlush(_.kind != ErrorKinds.Divergent) @@ -871,14 +882,14 @@ trait Implicits { rest find (alt => !improves(chosen, alt)) match { case Some(competing) => AmbiguousImplicitError(chosen, competing, "both", "and", "")(isView, pt, tree)(context) - return SearchFailure // Stop the search once ambiguity is encountered, see t4457_2.scala + return AmbiguousSearchFailure // Stop the search once ambiguity is encountered, see t4457_2.scala case _ => if (isView) chosen.useCountView += 1 else chosen.useCountArg += 1 } } - if (best == SearchFailure) { + if (best.isFailure) { /** If there is no winner, and we witnessed and caught divergence, * now we can throw it for the error message. */ @@ -1306,17 +1317,17 @@ trait Implicits { else { if (ReflectRuntimeUniverse == NoSymbol) { // todo. write a test for this - context.error(pos, s""" - |to create a manifest here, it is necessary to interoperate with the type tag `$tagInScope` in scope. - |however typetag -> manifest conversion requires Scala reflection, which is not present on the classpath. - |to proceed put scala-reflect.jar on your compilation classpath and recompile.""".trim.stripMargin) + context.error(pos, + sm"""to create a manifest here, it is necessary to interoperate with the type tag `$tagInScope` in scope. + |however typetag -> manifest conversion requires Scala reflection, which is not present on the classpath. + |to proceed put scala-reflect.jar on your compilation classpath and recompile.""") return SearchFailure } if (resolveClassTag(pos, tp, allowMaterialization = true) == EmptyTree) { - context.error(pos, s""" - |to create a manifest here, it is necessary to interoperate with the type tag `$tagInScope` in scope. - |however typetag -> manifest conversion requires a class tag for the corresponding type to be present. - |to proceed add a class tag to the type `$tp` (e.g. by introducing a context bound) and recompile.""".trim.stripMargin) + context.error(pos, + sm"""to create a manifest here, it is necessary to interoperate with the type tag `$tagInScope` in scope. + |however typetag -> manifest conversion requires a class tag for the corresponding type to be present. + |to proceed add a class tag to the type `$tp` (e.g. by introducing a context bound) and recompile.""") return SearchFailure } val cm = typed(Ident(ReflectRuntimeCurrentMirror)) @@ -1377,24 +1388,25 @@ trait Implicits { var result = searchImplicit(context.implicitss, true) - if (result == SearchFailure) { + if (result.isFailure) { if (Statistics.canEnable) Statistics.stopTimer(inscopeFailNanos, failstart) } else { if (Statistics.canEnable) Statistics.stopTimer(inscopeSucceedNanos, succstart) if (Statistics.canEnable) Statistics.incCounter(inscopeImplicitHits) } - if (result == SearchFailure) { + if (result.isFailure) { val previousErrs = context.flushAndReturnBuffer() val failstart = if (Statistics.canEnable) Statistics.startTimer(oftypeFailNanos) else null val succstart = if (Statistics.canEnable) Statistics.startTimer(oftypeSucceedNanos) else null + val wasAmbigious = result.isAmbiguousFailure // SI-6667, never search companions after an ambiguous error in in-scope implicits result = materializeImplicit(pt) // `materializeImplicit` does some preprocessing for `pt` // is it only meant for manifests/tags or we need to do the same for `implicitsOfExpectedType`? - if (result == SearchFailure) result = searchImplicit(implicitsOfExpectedType, false) + if (result.isFailure && !wasAmbigious) result = searchImplicit(implicitsOfExpectedType, false) - if (result == SearchFailure) { + if (result.isFailure) { context.updateBuffer(previousErrs) if (Statistics.canEnable) Statistics.stopTimer(oftypeFailNanos, failstart) } else { @@ -1403,7 +1415,7 @@ trait Implicits { } } - if (result == SearchFailure && settings.debug.value) + if (result.isFailure && settings.debug.value) log("no implicits found for "+pt+" "+pt.typeSymbol.info.baseClasses+" "+implicitsOfExpectedType) result diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 5deed4ffee..22daf13e33 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -221,7 +221,7 @@ trait Infer extends Checkable { // such as T <: T gets completed. See #360 tvar.constr.inst = ErrorType else - assert(false, tvar.origin+" at "+tvar.origin.typeSymbol.owner) + abort(tvar.origin+" at "+tvar.origin.typeSymbol.owner) } tvars map instantiate } diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index bcc37e8b37..b20a9ea626 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -122,16 +122,9 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { } def pickle(macroImplRef: Tree): Tree = { - val macroImpl = macroImplRef.symbol + val MacroImplReference(owner, macroImpl, targs) = macroImplRef val paramss = macroImpl.paramss - // this logic relies on the assumptions that were valid for the old macro prototype - // namely that macro implementations can only be defined in top-level classes and modules - // with the new prototype that materialized in a SIP, macros need to be statically accessible, which is different - // for example, a macro def could be defined in a trait that is implemented by an object - // there are some more clever cases when seemingly non-static method ends up being statically accessible - // however, the code below doesn't account for these guys, because it'd take a look of time to get it right - // for now I leave it as a todo and move along to more the important stuff // todo. refactor when fixing SI-5498 def className: String = { def loop(sym: Symbol): String = sym match { @@ -143,7 +136,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { loop(sym.owner) + separator + sym.javaSimpleName.toString } - loop(macroImpl.owner.enclClass) + loop(owner) } def signature: List[Int] = { @@ -164,7 +157,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { // I just named it "macro", because it's macro-related, but I could as well name it "foobar" val nucleus = Ident(newTermName("macro")) val wrapped = Apply(nucleus, payload map { case (k, v) => Assign(pickleAtom(k), pickleAtom(v)) }) - val pickle = gen.mkTypeApply(wrapped, treeInfo.typeArguments(macroImplRef.duplicate)) + val pickle = gen.mkTypeApply(wrapped, targs map (_.duplicate)) // assign NoType to all freshly created AST nodes // otherwise pickler will choke on tree.tpe being null diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala index e8a2c9f43c..acc4f7ff67 100644 --- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala +++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala @@ -426,6 +426,7 @@ trait MethodSynthesis { // spot that brand of them. In other words it's an artifact of the implementation. val tpt = derivedSym.tpe.finalResultType match { case ExistentialType(_, _) => TypeTree() + case _ if mods.isDeferred => TypeTree() case tp => TypeTree(tp) } tpt setPos derivedSym.pos.focus diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index f5d4df14fe..3f546c9a51 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -847,13 +847,8 @@ trait Namers extends MethodSynthesis { private def templateSig(templ: Template): Type = { val clazz = context.owner def checkParent(tpt: Tree): Type = { - val tp = tpt.tpe - val inheritsSelf = tp.typeSymbol == owner - if (inheritsSelf) - InheritsItselfError(tpt) - - if (inheritsSelf || tp.isError) AnyRefClass.tpe - else tp + if (tpt.tpe.isError) AnyRefClass.tpe + else tpt.tpe } val parents = typer.parentTypes(templ) map checkParent @@ -1260,7 +1255,11 @@ trait Namers extends MethodSynthesis { case defn: MemberDef => val ainfos = defn.mods.annotations filterNot (_ eq null) map { ann => // need to be lazy, #1782. beforeTyper to allow inferView in annotation args, SI-5892. - AnnotationInfo lazily beforeTyper(typer typedAnnotation ann) + AnnotationInfo lazily { + val context1 = typer.context.make(ann) + context1.setReportErrors() + beforeTyper(newTyper(context1) typedAnnotation ann) + } } if (ainfos.nonEmpty) { annotated setAnnotations ainfos @@ -1289,7 +1288,8 @@ trait Namers extends MethodSynthesis { if (clazz.isDerivedValueClass) { log("Ensuring companion for derived value class " + name + " at " + cdef.pos.show) clazz setFlag FINAL - enclosingNamerWithScope(clazz.owner.info.decls).ensureCompanionObject(cdef) + // Don't force the owner's info lest we create cycles as in SI-6357. + enclosingNamerWithScope(clazz.owner.rawInfo.decls).ensureCompanionObject(cdef) } result diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala index 31db042942..834c64aaae 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala @@ -417,7 +417,17 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL // (the prefix of the argument passed to the unapply must equal the prefix of the type of the binder) val treeMaker = TypeTestTreeMaker(patBinder, patBinder, extractor.paramType, extractor.paramType)(pos, extractorArgTypeTest = true) (List(treeMaker), treeMaker.nextBinder) - } else (Nil, patBinder) + } else { + // no type test needed, but the tree maker relies on `patBinderOrCasted` having type `extractor.paramType` (and not just some type compatible with it) + // SI-6624 shows this is necessary because apparently patBinder may have an unfortunate type (.decls don't have the case field accessors) + // TODO: get to the bottom of this -- I assume it happens when type checking infers a weird type for an unapply call + // by going back to the parameterType for the extractor call we get a saner type, so let's just do that for now + /* TODO: uncomment when `settings.developer` and `devWarning` become available + if (settings.developer.value && !(patBinder.info =:= extractor.paramType)) + devWarning(s"resetting info of $patBinder: ${patBinder.info} to ${extractor.paramType}") + */ + (Nil, patBinder setInfo extractor.paramType) + } withSubPats(typeTestTreeMaker :+ extractor.treeMaker(patBinderOrCasted, pos), extractor.subBindersAndPatterns: _*) } @@ -1143,7 +1153,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL // ExplicitOuter replaces `Select(q, outerSym) OBJ_EQ expectedPrefix` by `Select(q, outerAccessor(outerSym.owner)) OBJ_EQ expectedPrefix` // if there's an outer accessor, otherwise the condition becomes `true` -- TODO: can we improve needsOuterTest so there's always an outerAccessor? - val outer = expectedTp.typeSymbol.newMethod(vpmName.outer) setInfo expectedTp.prefix setFlag SYNTHETIC | ARTIFACT + val outer = expectedTp.typeSymbol.newMethod(vpmName.outer, newFlags = SYNTHETIC | ARTIFACT) setInfo expectedTp.prefix (Select(codegen._asInstanceOf(testedBinder, expectedTp), outer)) OBJ_EQ expectedOuter } @@ -1405,7 +1415,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL // assert(owner ne null); assert(owner ne NoSymbol) def freshSym(pos: Position, tp: Type = NoType, prefix: String = "x") = - NoSymbol.newTermSymbol(freshName(prefix), pos) setInfo tp + NoSymbol.newTermSymbol(freshName(prefix), pos, newFlags = SYNTHETIC) setInfo tp def newSynthCaseLabel(name: String) = NoSymbol.newLabel(freshName(name), NoPosition) setFlag treeInfo.SYNTH_CASE_FLAGS @@ -3601,7 +3611,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL */ def matcher(scrut: Tree, scrutSym: Symbol, restpe: Type)(cases: List[Casegen => Tree], matchFailGen: Option[Tree => Tree]): Tree = { val matchEnd = newSynthCaseLabel("matchEnd") - val matchRes = NoSymbol.newValueParameter(newTermName("x"), NoPosition, SYNTHETIC) setInfo restpe.withoutAnnotations + val matchRes = NoSymbol.newValueParameter(newTermName("x"), NoPosition, newFlags = SYNTHETIC) setInfo restpe.withoutAnnotations matchEnd setInfo MethodType(List(matchRes), restpe) def newCaseSym = newSynthCaseLabel("case") setInfo MethodType(Nil, restpe) diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index ee7805cb3d..3e1d3fdcc4 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -1264,13 +1264,15 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans val cdef = ClassDef(mods | MODULE, name.toTypeName, Nil, impl) setSymbol classSym setType NoType def findOrCreateModuleVar() = localTyper.typedPos(tree.pos) { - lazy val createModuleVar = gen.mkModuleVarDef(sym) - sym.enclClass.info.decl(nme.moduleVarName(sym.name.toTermName)) match { - // In case we are dealing with local symbol then we already have - // to correct error with forward reference - case NoSymbol => createModuleVar - case vsym => ValDef(vsym) - } + // See SI-5012, SI-6712. + val vsym = ( + if (sym.owner.isTerm) NoSymbol + else sym.enclClass.info.decl(nme.moduleVarName(sym.name.toTermName)) + ) + // In case we are dealing with local symbol then we already have + // to correct error with forward reference + if (vsym == NoSymbol) gen.mkModuleVarDef(sym) + else ValDef(vsym) } def createStaticModuleAccessor() = afterRefchecks { val method = ( @@ -1379,8 +1381,8 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans private def checkCompileTimeOnly(sym: Symbol, pos: Position) = { if (sym.isCompileTimeOnly) { def defaultMsg = - s"""|Reference to ${sym.fullLocationString} should not have survived past type checking, - |it should have been processed and eliminated during expansion of an enclosing macro.""".stripMargin + sm"""Reference to ${sym.fullLocationString} should not have survived past type checking, + |it should have been processed and eliminated during expansion of an enclosing macro.""" // The getOrElse part should never happen, it's just here as a backstop. unit.error(pos, sym.compileTimeOnlyMessage getOrElse defaultMsg) } @@ -1671,7 +1673,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans checkAnyValSubclass(currentOwner) if (bridges.nonEmpty) deriveTemplate(tree)(_ ::: bridges) else tree - case dc@TypeTreeWithDeferredRefCheck() => assert(false, "adapt should have turned dc: TypeTreeWithDeferredRefCheck into tpt: TypeTree, with tpt.original == dc"); dc + case dc@TypeTreeWithDeferredRefCheck() => abort("adapt should have turned dc: TypeTreeWithDeferredRefCheck into tpt: TypeTree, with tpt.original == dc") case tpt@TypeTree() => if(tpt.original != null) { tpt.original foreach { diff --git a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala index 64c5b41638..0a1d3bfa7a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala +++ b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala @@ -4,7 +4,31 @@ package typechecker trait StdAttachments { self: Analyzer => + import global._ + + /** Carries information necessary to expand the host tree. + * At times we need to store this info, because macro expansion can be delayed until its targs are inferred. + * After a macro application has been successfully expanded, this attachment is destroyed. + */ type UnaffiliatedMacroContext = scala.reflect.macros.runtime.Context type MacroContext = UnaffiliatedMacroContext { val universe: self.global.type } case class MacroRuntimeAttachment(delayed: Boolean, typerContext: Context, macroContext: Option[MacroContext]) + + /** After being synthesized by the parser, primary constructors aren't fully baked yet. + * A call to super in such constructors is just a fill-me-in-later dummy resolved later + * by `parentTypes`. This attachment coordinates `parentTypes` and `typedTemplate` and + * allows them to complete the synthesis. + */ + case class SuperCallArgsAttachment(argss: List[List[Tree]]) + + /** Convenience method for `SuperCallArgsAttachment`. + * Compared with `MacroRuntimeAttachment` this attachment has different a usage pattern, + * so it really benefits from a dedicated extractor. + */ + def superCallArgs(tree: Tree): Option[List[List[Tree]]] = + tree.attachments.get[SuperCallArgsAttachment] collect { case SuperCallArgsAttachment(argss) => argss } + + /** Determines whether the given tree has an associated SuperCallArgsAttachment. + */ + def hasSuperArgs(tree: Tree): Boolean = superCallArgs(tree).nonEmpty }
\ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index c9e45b6348..fb8a111da1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -527,8 +527,8 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT } def isJavaProtected = host.isTrait && sym.isJavaDefined && { restrictionError(pos, unit, - s"""|$clazz accesses protected $sym inside a concrete trait method. - |Add an accessor in a class extending ${sym.enclClass} as a workaround.""".stripMargin + sm"""$clazz accesses protected $sym inside a concrete trait method. + |Add an accessor in a class extending ${sym.enclClass} as a workaround.""" ) true } diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala index b4cdad70e2..48a5a36b00 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala @@ -280,11 +280,9 @@ abstract class TreeCheckers extends Analyzer { if (sym.owner != currentOwner) { val expected = currentOwner.ownerChain find (x => cond(x)) getOrElse fail("DefTree can't find owner: ") if (sym.owner != expected) - fail("""| - | currentOwner chain: %s - | symbol chain: %s""".stripMargin.format( - currentOwner.ownerChain take 3 mkString " -> ", - sym.ownerChain mkString " -> ") + fail(sm"""| + | currentOwner chain: ${currentOwner.ownerChain take 3 mkString " -> "} + | symbol chain: ${sym.ownerChain mkString " -> "}""" ) } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 4d320de173..76fd07f63a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -53,8 +53,10 @@ trait Typers extends Modes with Adaptations with Tags { object UnTyper extends Traverser { override def traverse(tree: Tree) = { - if (tree != EmptyTree) tree.tpe = null - if (tree.hasSymbol) tree.symbol = NoSymbol + if (tree.canHaveAttrs) { + tree.tpe = null + if (tree.hasSymbol) tree.symbol = NoSymbol + } super.traverse(tree) } } @@ -133,7 +135,7 @@ trait Typers extends Modes with Adaptations with Tags { val res = if (paramFailed || (paramTp.isError && {paramFailed = true; true})) SearchFailure else inferImplicit(fun, paramTp, context.reportErrors, false, context) argResultsBuff += res - if (res != SearchFailure) { + if (res.isSuccess) { argBuff += mkArg(res.tree, param.name) } else { mkArg = mkNamedArg // don't pass the default argument (if any) here, but start emitting named arguments for the following args @@ -762,7 +764,7 @@ trait Typers extends Modes with Adaptations with Tags { featureTrait.owner.ownerChain.takeWhile(_ != languageFeatureModule.moduleClass).reverse val featureName = (nestedOwners map (_.name + ".")).mkString + featureTrait.name def action(): Boolean = { - def hasImport = inferImplicit(EmptyTree: Tree, featureTrait.tpe, true, false, context) != SearchFailure + def hasImport = inferImplicit(EmptyTree: Tree, featureTrait.tpe, true, false, context).isSuccess def hasOption = settings.language.value exists (s => s == featureName || s == "_") val OK = hasImport || hasOption if (!OK) { @@ -1118,7 +1120,8 @@ trait Typers extends Modes with Adaptations with Tags { adaptType() else if ( inExprModeButNot(mode, FUNmode) && !tree.isDef && // typechecking application - tree.symbol != null && tree.symbol.isTermMacro) // of a macro + tree.symbol != null && tree.symbol.isTermMacro && // of a macro + !tree.attachments.get[SuppressMacroExpansionAttachment.type].isDefined) macroExpand(this, tree, mode, pt) else if ((mode & (PATTERNmode | FUNmode)) == (PATTERNmode | FUNmode)) adaptConstrPattern() @@ -1378,13 +1381,6 @@ trait Typers extends Modes with Adaptations with Tags { if (member(qual, name) != NoSymbol) qual else adaptToMember(qual, HasMember(name)) - private def typePrimaryConstrBody(clazz : Symbol, cbody: Tree, tparams: List[Symbol], enclTparams: List[Symbol], vparamss: List[List[ValDef]]): Tree = { - // XXX: see about using the class's symbol.... - enclTparams foreach (sym => context.scope.enter(sym)) - namer.enterValueParams(vparamss) - typed(cbody) - } - private def validateNoCaseAncestor(clazz: Symbol) = { if (!phase.erasedTypes) { for (ancestor <- clazz.ancestors find (_.isCase)) { @@ -1486,125 +1482,243 @@ trait Typers extends Modes with Adaptations with Tags { unit.error(tparam.pos, "type parameter of value class may not be specialized") } - def parentTypes(templ: Template): List[Tree] = - if (templ.parents.isEmpty) List(atPos(templ.pos)(TypeTree(AnyRefClass.tpe))) - else try { - val clazz = context.owner - // Normalize supertype and mixins so that supertype is always a class, not a trait. - var supertpt = typedTypeConstructor(templ.parents.head) - val firstParent = supertpt.tpe.typeSymbol - var mixins = templ.parents.tail map typedType - // If first parent is a trait, make it first mixin and add its superclass as first parent - while ((supertpt.tpe.typeSymbol ne null) && supertpt.tpe.typeSymbol.initialize.isTrait) { - val supertpt1 = typedType(supertpt) - if (!supertpt1.isErrorTyped) { - mixins = supertpt1 :: mixins - supertpt = TypeTree(supertpt1.tpe.firstParent) setPos supertpt.pos.focus + /** Typechecks a parent type reference. + * + * This typecheck is harder than it might look, because it should honor early + * definitions and also perform type argument inference with the help of super call + * arguments provided in `encodedtpt`. + * + * The method is called in batches (batch = 1 time per each parent type referenced), + * two batches per definition: once from namer, when entering a ClassDef or a ModuleDef + * and once from typer, when typechecking the definition. + * + * ***Arguments*** + * + * `encodedtpt` represents the parent type reference wrapped in an `Apply` node + * which indicates value arguments (i.e. type macro arguments or super constructor call arguments) + * If no value arguments are provided by the user, the `Apply` node is still + * there, but its `args` will be set to `Nil`. + * This argument is synthesized by `tools.nsc.ast.Parsers.templateParents`. + * + * `templ` is an enclosing template, which contains a primary constructor synthesized by the parser. + * Such a constructor is a DefDef which contains early initializers and maybe a super constructor call + * (I wrote "maybe" because trait constructors don't call super constructors). + * This argument is synthesized by `tools.nsc.ast.Trees.Template`. + * + * `inMixinPosition` indicates whether the reference is not the first in the + * list of parents (and therefore cannot be a class) or the opposite. + * + * ***Return value and side effects*** + * + * Returns a `TypeTree` representing a resolved parent type. + * If the typechecked parent reference implies non-nullary and non-empty argument list, + * this argument list is attached to the returned value in SuperCallArgsAttachment. + * The attachment is necessary for the subsequent typecheck to fixup a super constructor call + * in the body of the primary constructor (see `typedTemplate` for details). + * + * This method might invoke `typedPrimaryConstrBody`, hence it might cause the side effects + * described in the docs of that method. It might also attribute the Super(_, _) reference + * (if present) inside the primary constructor of `templ`. + * + * ***Example*** + * + * For the following definition: + * + * class D extends { + * val x = 2 + * val y = 4 + * } with B(x)(3) with C(y) with T + * + * this method will be called six times: + * + * (3 times from the namer) + * typedParentType(Apply(Apply(Ident(B), List(Ident(x))), List(3)), templ, inMixinPosition = false) + * typedParentType(Apply(Ident(C), List(Ident(y))), templ, inMixinPosition = true) + * typedParentType(Apply(Ident(T), List()), templ, inMixinPosition = true) + * + * (3 times from the typer) + * <the same three calls> + */ + private def typedParentType(encodedtpt: Tree, templ: Template, inMixinPosition: Boolean): Tree = { + val app = treeInfo.dissectApplied(encodedtpt) + val (treeInfo.Applied(core, targs, argss), decodedtpt) = (app, app.callee) + val argssAreTrivial = argss == Nil || argss == ListOfNil + + // we cannot avoid cyclic references with `initialize` here, because when type macros arrive, + // we'll have to check the probe for isTypeMacro anyways. + // therefore I think it's reasonable to trade a more specific "inherits itself" error + // for a generic, yet understandable "cyclic reference" error + var probe = typedTypeConstructor(core.duplicate).tpe.typeSymbol + if (probe == null) probe = NoSymbol + probe.initialize + + if (probe.isTrait || inMixinPosition) { + if (!argssAreTrivial) { + if (probe.isTrait) ConstrArgsInParentWhichIsTraitError(encodedtpt, probe) + else () // a class in a mixin position - this warrants an error in `validateParentClasses` + // therefore here we do nothing, e.g. don't check that the # of ctor arguments + // matches the # of ctor parameters or stuff like that + } + typedType(decodedtpt) + } else { + var supertpt = typedTypeConstructor(decodedtpt) + val supertparams = if (supertpt.hasSymbol) supertpt.symbol.typeParams else Nil + if (supertparams.nonEmpty) { + typedPrimaryConstrBody(templ) { + val supertpe = PolyType(supertparams, appliedType(supertpt.tpe, supertparams map (_.tpeHK))) + val supercall = New(supertpe, mmap(argss)(_.duplicate)) + val treeInfo.Applied(Select(ctor, nme.CONSTRUCTOR), _, _) = supercall + ctor setType supertpe // this is an essential hack, otherwise it will occasionally fail to typecheck + atPos(supertpt.pos.focus)(supercall) + } match { + case EmptyTree => MissingTypeArgumentsParentTpeError(supertpt) + case tpt => supertpt = TypeTree(tpt.tpe) setPos supertpt.pos.focus } } - if (supertpt.tpe.typeSymbol == AnyClass && firstParent.isTrait) - supertpt.tpe = AnyRefClass.tpe - - // Determine - // - supertparams: Missing type parameters from supertype - // - supertpe: Given supertype, polymorphic in supertparams - val supertparams = if (supertpt.hasSymbol) supertpt.symbol.typeParams else List() - var supertpe = supertpt.tpe - if (!supertparams.isEmpty) - supertpe = PolyType(supertparams, appliedType(supertpe, supertparams map (_.tpeHK))) - - // A method to replace a super reference by a New in a supercall - def transformSuperCall(scall: Tree): Tree = (scall: @unchecked) match { - case Apply(fn, args) => - treeCopy.Apply(scall, transformSuperCall(fn), args map (_.duplicate)) - case Select(Super(_, _), nme.CONSTRUCTOR) => - treeCopy.Select( - scall, - atPos(supertpt.pos.focus)(New(TypeTree(supertpe)) setType supertpe), - nme.CONSTRUCTOR) - } - - treeInfo.firstConstructor(templ.body) match { - case constr @ DefDef(_, _, _, vparamss, _, cbody @ Block(cstats, cunit)) => - // Convert constructor body to block in environment and typecheck it - val (preSuperStats, superCall) = { - val (stats, rest) = cstats span (x => !treeInfo.isSuperConstrCall(x)) - (stats map (_.duplicate), if (rest.isEmpty) EmptyTree else rest.head.duplicate) - } - val cstats1 = if (superCall == EmptyTree) preSuperStats else preSuperStats :+ superCall - val cbody1 = treeCopy.Block(cbody, preSuperStats, superCall match { - case Apply(_, _) if supertparams.nonEmpty => transformSuperCall(superCall) - case _ => cunit.duplicate - }) - val outercontext = context.outer - - assert(clazz != NoSymbol, templ) - val cscope = outercontext.makeNewScope(constr, outercontext.owner) - val cbody2 = newTyper(cscope) // called both during completion AND typing. - .typePrimaryConstrBody(clazz, - cbody1, supertparams, clazz.unsafeTypeParams, vparamss map (_.map(_.duplicate))) - - superCall match { - case Apply(_, _) => - val sarg = treeInfo.firstArgument(superCall) - if (sarg != EmptyTree && supertpe.typeSymbol != firstParent) - ConstrArgsInTraitParentTpeError(sarg, firstParent) - if (!supertparams.isEmpty) - supertpt = TypeTree(cbody2.tpe) setPos supertpt.pos.focus - case _ => - if (!supertparams.isEmpty) - MissingTypeArgumentsParentTpeError(supertpt) - } + // this is the place where we tell the typer what argss should be used for the super call + // if argss are nullary or empty, then (see the docs for `typedPrimaryConstrBody`) + // the super call dummy is already good enough, so we don't need to do anything + if (argssAreTrivial) supertpt else supertpt updateAttachment SuperCallArgsAttachment(argss) + } + } - val preSuperVals = treeInfo.preSuperFields(templ.body) - if (preSuperVals.isEmpty && preSuperStats.nonEmpty) - debugwarn("Wanted to zip empty presuper val list with " + preSuperStats) - else - map2(preSuperStats, preSuperVals)((ldef, gdef) => gdef.tpt.tpe = ldef.symbol.tpe) + /** Typechecks the mishmash of trees that happen to be stuffed into the primary constructor of a given template. + * Before commencing the typecheck, replaces the `pendingSuperCall` dummy with the result of `actualSuperCall`. + * `actualSuperCall` can return `EmptyTree`, in which case the dummy is replaced with a literal unit. + * + * ***Return value and side effects*** + * + * If a super call is present in the primary constructor and is not erased by the transform, returns it typechecked. + * Otherwise (e.g. if the primary constructor is missing or the super call isn't there) returns `EmptyTree`. + * + * As a side effect, this method attributes the underlying fields of early vals. + * Early vals aren't typechecked anywhere else, so it's essential to call `typedPrimaryConstrBody` + * at least once per definition. It'd be great to disentangle this logic at some point. + * + * ***Example*** + * + * For the following definition: + * + * class D extends { + * val x = 2 + * val y = 4 + * } with B(x)(3) with C(y) with T + * + * the primary constructor of `templ` will be: + * + * Block(List( + * ValDef(NoMods, x, TypeTree(), 2) + * ValDef(NoMods, y, TypeTree(), 4) + * global.pendingSuperCall, + * Literal(Constant(()))) + * + * Note the `pendingSuperCall` part. This is the representation of a fill-me-in-later supercall dummy, + * which encodes the fact that supercall argss are unknown during parsing and need to be transplanted + * from one of the parent types. Read more about why the argss are unknown in `tools.nsc.ast.Trees.Template`. + */ + private def typedPrimaryConstrBody(templ: Template)(actualSuperCall: => Tree): Tree = + treeInfo.firstConstructor(templ.body) match { + case ctor @ DefDef(_, _, _, vparamss, _, cbody @ Block(cstats, cunit)) => + val (preSuperStats, superCall) = { + val (stats, rest) = cstats span (x => !treeInfo.isSuperConstrCall(x)) + (stats map (_.duplicate), if (rest.isEmpty) EmptyTree else rest.head.duplicate) + } + val superCall1 = (superCall match { + case global.pendingSuperCall => actualSuperCall + case EmptyTree => EmptyTree + }) orElse cunit + 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 cbody2 = { // called both during completion AND typing. + val typer1 = newTyper(cscope) + // XXX: see about using the class's symbol.... + clazz.unsafeTypeParams foreach (sym => typer1.context.scope.enter(sym)) + typer1.namer.enterValueParams(vparamss map (_.map(_.duplicate))) + typer1.typed(cbody1) + } - case _ => - if (!supertparams.isEmpty) - MissingTypeArgumentsParentTpeError(supertpt) - } -/* experimental: early types as type arguments - val hasEarlyTypes = templ.body exists (treeInfo.isEarlyTypeDef) - val earlyMap = new EarlyMap(clazz) - List.mapConserve(supertpt :: mixins){ tpt => - val tpt1 = checkNoEscaping.privates(clazz, tpt) - if (hasEarlyTypes) tpt1 else tpt1 setType earlyMap(tpt1.tpe) - } -*/ + val preSuperVals = treeInfo.preSuperFields(templ.body) + if (preSuperVals.isEmpty && preSuperStats.nonEmpty) + debugwarn("Wanted to zip empty presuper val list with " + preSuperStats) + else + map2(preSuperStats, preSuperVals)((ldef, gdef) => gdef.tpt.tpe = ldef.symbol.tpe) - //Console.println("parents("+clazz") = "+supertpt :: mixins);//DEBUG + if (superCall1 == cunit) EmptyTree else cbody2 + case _ => + EmptyTree + } - // Certain parents are added in the parser before it is known whether - // that class also declared them as parents. For instance, this is an - // error unless we take corrective action here: - // - // case class Foo() extends Serializable - // - // So we strip the duplicates before typer. - def fixDuplicates(remaining: List[Tree]): List[Tree] = remaining match { - case Nil => Nil - case x :: xs => - val sym = x.symbol - x :: fixDuplicates( - if (isPossibleSyntheticParent(sym)) xs filterNot (_.symbol == sym) - else xs - ) + /** Makes sure that the first type tree in the list of parent types is always a class. + * If the first parent is a trait, prepend its supertype to the list until it's a class. + */ + private def normalizeFirstParent(parents: List[Tree]): List[Tree] = parents match { + case first :: rest if treeInfo.isTraitRef(first) => + def explode(supertpt: Tree, acc: List[Tree]): List[Tree] = { + if (treeInfo.isTraitRef(supertpt)) { + val supertpt1 = typedType(supertpt) + if (!supertpt1.isErrorTyped) { + val supersupertpt = TypeTree(supertpt1.tpe.firstParent) setPos supertpt.pos.focus + return explode(supersupertpt, supertpt1 :: acc) + } + } + if (supertpt.tpe.typeSymbol == AnyClass) supertpt.tpe = AnyRefClass.tpe + supertpt :: acc } + explode(first, Nil) ++ rest + case _ => parents + } - fixDuplicates(supertpt :: mixins) mapConserve (tpt => checkNoEscaping.privates(clazz, tpt)) - } - catch { - case ex: TypeError => - // fallback in case of cyclic errors - // @H none of the tests enter here but I couldn't rule it out - log("Type error calculating parents in template " + templ) - log("Error: " + ex) - ParentTypesError(templ, ex) - List(TypeTree(AnyRefClass.tpe)) - } + /** Certain parents are added in the parser before it is known whether + * that class also declared them as parents. For instance, this is an + * error unless we take corrective action here: + * + * case class Foo() extends Serializable + * + * So we strip the duplicates before typer. + */ + private def fixDuplicateSyntheticParents(parents: List[Tree]): List[Tree] = parents match { + case Nil => Nil + case x :: xs => + val sym = x.symbol + x :: fixDuplicateSyntheticParents( + if (isPossibleSyntheticParent(sym)) xs filterNot (_.symbol == sym) + else xs + ) + } + + def parentTypes(templ: Template): List[Tree] = templ.parents match { + case Nil => List(atPos(templ.pos)(TypeTree(AnyRefClass.tpe))) + case first :: rest => + try { + val supertpts = fixDuplicateSyntheticParents(normalizeFirstParent( + typedParentType(first, templ, inMixinPosition = false) +: + (rest map (typedParentType(_, templ, inMixinPosition = true))))) + + // if that is required to infer the targs of a super call + // typedParentType calls typedPrimaryConstrBody to do the inferring typecheck + // as a side effect, that typecheck also assigns types to the fields underlying early vals + // however if inference is not required, the typecheck doesn't happen + // and therefore early fields have their type trees not assigned + // here we detect this situation and take preventive measures + if (treeInfo.hasUntypedPreSuperFields(templ.body)) + typedPrimaryConstrBody(templ)(EmptyTree) + + supertpts mapConserve (tpt => checkNoEscaping.privates(context.owner, tpt)) + } catch { + case ex: TypeError => + // fallback in case of cyclic errors + // @H none of the tests enter here but I couldn't rule it out + // upd. @E when a definitions inherits itself, we end up here + // because `typedParentType` triggers `initialize` for parent types symbols + log("Type error calculating parents in template " + templ) + log("Error: " + ex) + ParentTypesError(templ, ex) + List(TypeTree(AnyRefClass.tpe)) + } + } /** <p>Check that</p> * <ul> @@ -1844,9 +1958,12 @@ trait Typers extends Modes with Adaptations with Tags { // the following is necessary for templates generated later assert(clazz.info.decls != EmptyScope, clazz) enterSyms(context.outer.make(templ, clazz, clazz.info.decls), templ.body) - validateParentClasses(parents1, selfType) + if (!templ.isErrorTyped) // if `parentTypes` has invalidated the template, don't validate it anymore + validateParentClasses(parents1, selfType) if (clazz.isCase) validateNoCaseAncestor(clazz) + if (clazz.isTrait && hasSuperArgs(parents1.head)) + ConstrArgsInParentOfTraitError(parents1.head, clazz) if ((clazz isSubClass ClassfileAnnotationClass) && !clazz.owner.isPackageClass) unit.error(clazz.pos, "inner classes cannot be classfile annotations") @@ -1854,9 +1971,21 @@ trait Typers extends Modes with Adaptations with Tags { if (!phase.erasedTypes && !clazz.info.resultType.isError) // @S: prevent crash for duplicated type members checkFinitary(clazz.info.resultType.asInstanceOf[ClassInfoType]) - val body = - if (isPastTyper || reporter.hasErrors) templ.body - else templ.body flatMap rewrappingWrapperTrees(namer.addDerivedTrees(Typer.this, _)) + val body = { + val body = + if (isPastTyper || reporter.hasErrors) templ.body + else templ.body flatMap rewrappingWrapperTrees(namer.addDerivedTrees(Typer.this, _)) + val primaryCtor = treeInfo.firstConstructor(body) + val primaryCtor1 = primaryCtor match { + case DefDef(_, _, _, _, _, Block(earlyVals :+ global.pendingSuperCall, unit)) => + val argss = superCallArgs(parents1.head) getOrElse Nil + val pos = wrappingPos(parents1.head.pos, argss.flatten) + val superCall = atPos(pos)(PrimarySuperCall(argss)) + deriveDefDef(primaryCtor)(block => Block(earlyVals :+ superCall, unit) setPos pos) setPos pos + case _ => primaryCtor + } + body mapConserve { case `primaryCtor` => primaryCtor1; case stat => stat } + } val body1 = typedStats(body, templ.symbol) @@ -2603,7 +2732,7 @@ trait Typers extends Modes with Adaptations with Tags { if (members.head eq EmptyTree) setError(tree) 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))) + Block(ClassDef(anonClass, NoMods, 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) @@ -2828,7 +2957,11 @@ trait Typers extends Modes with Adaptations with Tags { var moreToAdd = true while (moreToAdd) { val initElems = scope.elems - for (sym <- scope) + // SI-5877 The decls of a package include decls of the package object. But we don't want to add + // the corresponding synthetics to the package class, only to the package object class. + def shouldAdd(sym: Symbol) = + inBlock || !isInPackageObject(sym, context.owner) + for (sym <- scope if shouldAdd(sym)) for (tree <- context.unit.synthetics get sym) { newStats += typedStat(tree) // might add even more synthetics to the scope context.unit.synthetics -= sym @@ -3891,7 +4024,7 @@ trait Typers extends Modes with Adaptations with Tags { case DynamicApplicationNamed(qual, _) if acceptsApplyDynamic(qual.tpe.widen) => true case _ => false // look deeper? - // val methPart = treeInfo.methPart(fun) + // val treeInfo.Applied(methPart, _, _) = fun // println("methPart of "+ fun +" is "+ methPart) // if (methPart ne fun) isApplyDynamicNamed(methPart) // else false @@ -3926,54 +4059,44 @@ trait Typers extends Modes with Adaptations with Tags { * */ def mkInvoke(cxTree: Tree, tree: Tree, qual: Tree, name: Name): Option[Tree] = { - debuglog(s"mkInvoke($cxTree, $tree, $qual, $name)") + log(s"dyna.mkInvoke($cxTree, $tree, $qual, $name)") + val treeInfo.Applied(treeSelection, _, _) = tree + def isDesugaredApply = treeSelection match { + case Select(`qual`, nme.apply) => true + case _ => false + } acceptsApplyDynamicWithType(qual, name) map { tp => - // tp eq NoType => can call xxxDynamic, but not passing any type args (unless specified explicitly by the user) - // in scala-virtualized, when not NoType, tp is passed as type argument (for selection on a staged Struct) - - // strip off type application -- we're not doing much with outer, - // so don't bother preserving cxTree's attributes etc - val cxTree1 = cxTree match { - case t: ValOrDefDef => t.rhs - case t => t - } - val cxTree2 = cxTree1 match { - case Typed(t, tpe) => t // ignore outer type annotation - case t => t - } - val (outer, explicitTargs) = cxTree2 match { - case TypeApply(fun, targs) => (fun, targs) - case Apply(TypeApply(fun, targs), args) => (Apply(fun, args), targs) - case Select(TypeApply(fun, targs), nme) => (Select(fun, nme), targs) - case t => (t, Nil) - } - def hasNamedArg(as: List[Tree]) = as.collectFirst{case AssignOrNamedArg(lhs, rhs) =>}.nonEmpty - - def desugaredApply = tree match { - case Select(`qual`, nme.apply) => true - case _ => false + // If tp == NoType, pass only explicit type arguments to applyXXX. Not used at all + // here - it is for scala-virtualized, where tp will be passed as an argument (for + // selection on a staged Struct) + def hasNamed(args: List[Tree]): Boolean = args exists (_.isInstanceOf[AssignOrNamedArg]) + // not supported: foo.bar(a1,..., an: _*) + def hasStar(args: List[Tree]) = treeInfo.isWildcardStarArgList(args) + def applyOp(args: List[Tree]) = if (hasNamed(args)) nme.applyDynamicNamed else nme.applyDynamic + def matches(t: Tree) = isDesugaredApply || treeInfo.dissectApplied(t).core == treeSelection + + /** Note that the trees which arrive here are potentially some distance from + * the trees of direct interest. `cxTree` is some enclosing expression which + * may apparently be arbitrarily larger than `tree`; and `tree` itself is + * too small, having at least in some cases lost its explicit type parameters. + * This logic is designed to use `tree` to pinpoint the immediately surrounding + * Apply/TypeApply/Select node, and only then creates the dynamic call. + * See SI-6731 among others. + */ + def findSelection(t: Tree): Option[(TermName, Tree)] = t match { + case Apply(fn, args) if hasStar(args) => DynamicVarArgUnsupported(tree, applyOp(args)) ; None + case Apply(fn, args) if matches(fn) => Some((applyOp(args), fn)) + case Assign(lhs, _) if matches(lhs) => Some((nme.updateDynamic, lhs)) + case _ if matches(t) => Some((nme.selectDynamic, t)) + case _ => t.children flatMap findSelection headOption } - // note: context.tree includes at most one Apply node - // thus, we can't use it to detect we're going to receive named args in expressions such as: - // qual.sel(a)(a2, arg2 = "a2") - val oper = outer match { - case Apply(q, as) if q == tree || desugaredApply => - val oper = - if (hasNamedArg(as)) nme.applyDynamicNamed - else nme.applyDynamic - // not supported: foo.bar(a1,..., an: _*) - if (treeInfo.isWildcardStarArgList(as)) { - DynamicVarArgUnsupported(tree, oper) - return Some(setError(tree)) - } else oper - case Assign(`tree`, _) => nme.updateDynamic - case _ => nme.selectDynamic + findSelection(cxTree) match { + case Some((opName, treeInfo.Applied(_, targs, _))) => + val fun = gen.mkTypeApply(Select(qual, opName), targs) + atPos(qual.pos)(Apply(fun, Literal(Constant(name.decode)) :: Nil)) + case _ => + setError(tree) } - - val dynSel = Select(qual, oper) - val tappSel = if (explicitTargs.nonEmpty) TypeApply(dynSel, explicitTargs) else dynSel - - atPos(qual.pos)(Apply(tappSel, List(Literal(Constant(name.decode))))) } } @@ -3981,7 +4104,7 @@ trait Typers extends Modes with Adaptations with Tags { silent(typeTree) match { case SilentResultValue(r) => r case SilentTypeError(err) => DynamicRewriteError(tree, err) - } + } } } @@ -4158,8 +4281,8 @@ trait Typers extends Modes with Adaptations with Tags { return fail() if (treeInfo.mayBeVarGetter(varsym)) { - treeInfo.methPart(lhs1) match { - case Select(qual, name) => + lhs1 match { + case treeInfo.Applied(Select(qual, name), _, _) => val sel = Select(qual, nme.getterToSetter(name.toTermName)) setPos lhs.pos val app = Apply(sel, List(rhs)) setPos tree.pos return typed(app, mode, pt) @@ -4577,9 +4700,9 @@ trait Typers extends Modes with Adaptations with Tags { } case Apply(fn, indices) => - treeInfo.methPart(fn) match { - case Select(table, nme.apply) => mkUpdate(table, indices) - case _ => UnexpectedTreeAssignmentConversionError(qual) + fn match { + case treeInfo.Applied(Select(table, nme.apply), _, _) => mkUpdate(table, indices) + case _ => UnexpectedTreeAssignmentConversionError(qual) } } typed1(tree1, mode, pt) @@ -4870,12 +4993,12 @@ trait Typers extends Modes with Adaptations with Tags { defSym = pre.member(defEntry.sym.name) if (defSym ne defEntry.sym) { qual = gen.mkAttributedQualifier(pre) - log(s""" + log(sm""" | !!! Overloaded package object member resolved incorrectly. | prefix: $pre | Discarded: ${defEntry.sym.defString} | Using: ${defSym.defString} - """.stripMargin) + """) } } else @@ -5222,9 +5345,9 @@ trait Typers extends Modes with Adaptations with Tags { // find out whether the programmer is trying to eta-expand a macro def // to do that we need to typecheck the tree first (we need a symbol of the eta-expandee) // that typecheck must not trigger macro expansions, so we explicitly prohibit them - // Q: "but, " - you may ask - ", `typed1` doesn't call adapt, which does macro expansion, so why explicit check?" - // A: solely for robustness reasons. this mechanism might change in the future, which might break unprotected code - val exprTyped = context.withMacrosDisabled(typed1(expr, mode, pt)) + // however we cannot do `context.withMacrosDisabled` + // because `expr` might contain nested macro calls (see SI-6673) + val exprTyped = typed1(expr updateAttachment SuppressMacroExpansionAttachment, mode, pt) exprTyped match { case macroDef if macroDef.symbol != null && macroDef.symbol.isTermMacro && !macroDef.symbol.isErroneous => MacroEtaError(exprTyped) @@ -5368,8 +5491,14 @@ trait Typers extends Modes with Adaptations with Tags { } def typedTypeTree(tree: TypeTree) = { - if (tree.original != null) - tree setType typedType(tree.original, mode).tpe + if (tree.original != null) { + val newTpt = typedType(tree.original, mode) + tree setType newTpt.tpe + newTpt match { + case tt @ TypeTree() => tree setOriginal tt.original + case _ => tree + } + } else // we should get here only when something before failed // and we try again (@see tryTypedApply). In that case we can assign @@ -5605,21 +5734,21 @@ trait Typers extends Modes with Adaptations with Tags { // enough to see those. See #3938 ConstructorPrefixError(tree, restpe) } else { - //@M fix for #2208 - // if there are no type arguments, normalization does not bypass any checks, so perform it to get rid of AnyRef - if (result.tpe.typeArgs.isEmpty) { - // minimal check: if(result.tpe.typeSymbolDirect eq AnyRefClass) { - // must expand the fake AnyRef type alias, because bootstrapping (init in Definitions) is not - // designed to deal with the cycles in the scala package (ScalaObject extends - // AnyRef, but the AnyRef type alias is entered after the scala package is - // loaded and completed, so that ScalaObject is unpickled while AnyRef is not - // yet defined ) - // !!! TODO - revisit now that ScalaObject is gone. - result setType(restpe) - } else { // must not normalize: type application must be (bounds-)checked (during RefChecks), see #2208 - // during uncurry (after refchecks), all types are normalized - result - } + //@M fix for #2208 + // if there are no type arguments, normalization does not bypass any checks, so perform it to get rid of AnyRef + if (result.tpe.typeArgs.isEmpty) { + // minimal check: if(result.tpe.typeSymbolDirect eq AnyRefClass) { + // must expand the fake AnyRef type alias, because bootstrapping (init in Definitions) is not + // designed to deal with the cycles in the scala package (ScalaObject extends + // AnyRef, but the AnyRef type alias is entered after the scala package is + // loaded and completed, so that ScalaObject is unpickled while AnyRef is not + // yet defined ) + // !!! TODO - revisit now that ScalaObject is gone. + result setType(restpe) + } else { // must not normalize: type application must be (bounds-)checked (during RefChecks), see #2208 + // during uncurry (after refchecks), all types are normalized + result + } } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala index bf44b65406..a34d7389bf 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala @@ -126,7 +126,7 @@ trait Unapplies extends ast.TreeDSL ModuleDef( Modifiers(cdef.mods.flags & AccessFlags | SYNTHETIC, cdef.mods.privateWithin), cdef.name.toTermName, - Template(parents, emptyValDef, NoMods, Nil, ListOfNil, body, cdef.impl.pos.focus)) + Template(parents, emptyValDef, NoMods, Nil, body, cdef.impl.pos.focus)) } private val caseMods = Modifiers(SYNTHETIC | CASE) diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala index 95135b84e0..0125f1b189 100644 --- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala +++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala @@ -230,7 +230,6 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => emptyValDef, NoMods, List(), - List(List()), List(methdef), NoPosition)) trace("wrapped: ")(showAttributed(moduledef, true, true, settings.Yshowsymkinds.value)) diff --git a/src/eclipse/continuations-library/.classpath b/src/eclipse/continuations-library/.classpath new file mode 100644 index 0000000000..b3ca4eeb48 --- /dev/null +++ b/src/eclipse/continuations-library/.classpath @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="library"/> + <classpathentry combineaccessrules="false" kind="src" path="/scala-library"/> + <classpathentry kind="con" path="org.scala-ide.sdt.launching.SCALA_CONTAINER"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> + <classpathentry kind="output" path="build-quick-continuations-library"/> +</classpath> diff --git a/src/eclipse/continuations-library/.project b/src/eclipse/continuations-library/.project new file mode 100644 index 0000000000..f3a53a3d97 --- /dev/null +++ b/src/eclipse/continuations-library/.project @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>continuations-library</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.scala-ide.sdt.core.scalabuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.scala-ide.sdt.core.scalanature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> + <linkedResources> + <link> + <name>build-quick-continuations-library</name> + <type>2</type> + <locationURI>SCALA_BASEDIR/build/quick/classes/continuations/library</locationURI> + </link> + <link> + <name>library</name> + <type>2</type> + <locationURI>SCALA_BASEDIR/src/continuations/library</locationURI> + </link> + </linkedResources> +</projectDescription> diff --git a/src/eclipse/continuations-library/.settings/org.scala-ide.sdt.core.prefs b/src/eclipse/continuations-library/.settings/org.scala-ide.sdt.core.prefs new file mode 100644 index 0000000000..63e1df247f --- /dev/null +++ b/src/eclipse/continuations-library/.settings/org.scala-ide.sdt.core.prefs @@ -0,0 +1,2 @@ +P=continuations\:enable +scala.compiler.useProjectSettings=true diff --git a/src/eclipse/partest/.classpath b/src/eclipse/partest/.classpath index b14e465aa6..7936d4d4b4 100644 --- a/src/eclipse/partest/.classpath +++ b/src/eclipse/partest/.classpath @@ -10,5 +10,6 @@ <classpathentry kind="lib" path="lib/jline.jar"/> <classpathentry kind="lib" path="lib/msil.jar"/> <classpathentry combineaccessrules="false" kind="src" path="/asm"/> + <classpathentry combineaccessrules="false" kind="src" path="/continuations-library"/> <classpathentry kind="output" path="build-quick-partest"/> </classpath> diff --git a/src/eclipse/reflect/.classpath b/src/eclipse/reflect/.classpath index 57a3928dc3..36e6b6adf1 100644 --- a/src/eclipse/reflect/.classpath +++ b/src/eclipse/reflect/.classpath @@ -3,5 +3,6 @@ <classpathentry kind="src" path="reflect"/> <classpathentry combineaccessrules="false" kind="src" path="/scala-library"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/> + <classpathentry combineaccessrules="false" kind="src" path="/continuations-library"/> <classpathentry kind="output" path="build-quick-reflect"/> </classpath> diff --git a/src/eclipse/scala-compiler/.classpath b/src/eclipse/scala-compiler/.classpath index 40a4ed9996..d438d3e610 100644 --- a/src/eclipse/scala-compiler/.classpath +++ b/src/eclipse/scala-compiler/.classpath @@ -9,5 +9,6 @@ <classpathentry kind="lib" path="lib/ant/ant.jar"/> <classpathentry kind="lib" path="lib/jline.jar"/> <classpathentry kind="lib" path="lib/msil.jar"/> + <classpathentry combineaccessrules="false" kind="src" path="/continuations-library"/> <classpathentry kind="output" path="build-quick-compiler"/> </classpath> diff --git a/src/eclipse/scalap/.classpath b/src/eclipse/scalap/.classpath index 2b44ad19b2..16737bd9cd 100644 --- a/src/eclipse/scalap/.classpath +++ b/src/eclipse/scalap/.classpath @@ -8,5 +8,6 @@ <classpathentry kind="lib" path="lib/ant/ant.jar"/> <classpathentry kind="lib" path="lib/jline.jar"/> <classpathentry kind="lib" path="lib/msil.jar"/> + <classpathentry combineaccessrules="false" kind="src" path="/continuations-library"/> <classpathentry kind="output" path="build-quick-scalap"/> </classpath> diff --git a/src/library/scala/StringContext.scala b/src/library/scala/StringContext.scala index 8be0cb1619..1b5fd6c8d3 100644 --- a/src/library/scala/StringContext.scala +++ b/src/library/scala/StringContext.scala @@ -100,8 +100,8 @@ case class StringContext(parts: String*) { * ''Note:'' Even when using the raw interpolator, Scala will preprocess unicode escapes. * For example: * {{{ - * scala> raw"\u0123" - * res0: String = ģ + * scala> raw"\u005cu0025" + * res0: String = # * }}} * * @param `args` The arguments to be inserted into the resulting string. @@ -191,7 +191,7 @@ object StringContext { var cur = 0 var idx = 0 def output(ch: Char) = { - bldr append str.substring (start, cur) + bldr.append(str, start, cur) bldr append ch start = idx } @@ -199,14 +199,15 @@ object StringContext { cur = idx if (str(idx) == '\\') { idx += 1 + if (idx >= len) throw new InvalidEscapeException(str, cur) if ('0' <= str(idx) && str(idx) <= '7') { val leadch = str(idx) var oct = leadch - '0' idx += 1 - if ('0' <= str(idx) && str(idx) <= '7') { + if (idx < len && '0' <= str(idx) && str(idx) <= '7') { oct = oct * 8 + str(idx) - '0' idx += 1 - if (leadch <= '3' && '0' <= str(idx) && str(idx) <= '7') { + if (idx < len && leadch <= '3' && '0' <= str(idx) && str(idx) <= '7') { oct = oct * 8 + str(idx) - '0' idx += 1 } @@ -234,6 +235,6 @@ object StringContext { } } if (start == 0) str - else (bldr append str.substring(start, idx)).toString + else bldr.append(str, start, idx).toString } } diff --git a/src/library/scala/Symbol.scala b/src/library/scala/Symbol.scala index 723c05a30c..4fead7a50c 100644 --- a/src/library/scala/Symbol.scala +++ b/src/library/scala/Symbol.scala @@ -69,6 +69,11 @@ private[scala] abstract class UniquenessCache[K, V >: Null] val res = cached() if (res != null) res else { + // If we don't remove the old String key from the map, we can + // wind up with one String as the key and a different String as + // as the name field in the Symbol, which can lead to surprising + // GC behavior and duplicate Symbols. See SI-6706. + map remove name val sym = valueFromKey(name) map.put(name, new WeakReference(sym)) sym diff --git a/src/library/scala/collection/IterableLike.scala b/src/library/scala/collection/IterableLike.scala index 8d1fa80815..540bd84b79 100644 --- a/src/library/scala/collection/IterableLike.scala +++ b/src/library/scala/collection/IterableLike.scala @@ -171,7 +171,7 @@ self => * fewer elements than size. */ def sliding(size: Int): Iterator[Repr] = sliding(size, 1) - + /** Groups elements in fixed size blocks by passing a "sliding window" * over them (as opposed to partitioning them, as is done in grouped.) * @see [[scala.collection.Iterator]], method `sliding` @@ -293,7 +293,6 @@ self => override /*TraversableLike*/ def view = new IterableView[A, Repr] { protected lazy val underlying = self.repr - override def isEmpty = self.isEmpty override def iterator = self.iterator } diff --git a/src/library/scala/collection/SeqLike.scala b/src/library/scala/collection/SeqLike.scala index 0ffd99c88c..f65e2ef9cd 100644 --- a/src/library/scala/collection/SeqLike.scala +++ b/src/library/scala/collection/SeqLike.scala @@ -22,7 +22,7 @@ import scala.math.{ min, max, Ordering } * Sequences are special cases of iterable collections of class `Iterable`. * Unlike iterables, sequences always have a defined order of elements. * Sequences provide a method `apply` for indexing. Indices range from `0` up to the `length` of - * a sequence. Sequences support a number to find occurrences of elements or subsequences, including + * a sequence. Sequences support a number of methods to find occurrences of elements or subsequences, including * `segmentLength`, `prefixLength`, `indexWhere`, `indexOf`, `lastIndexWhere`, `lastIndexOf`, * `startsWith`, `endsWith`, `indexOfSlice`. * @@ -630,7 +630,6 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[ override def view = new SeqView[A, Repr] { protected lazy val underlying = self.repr - override def isEmpty = self.isEmpty override def iterator = self.iterator override def length = self.length override def apply(idx: Int) = self.apply(idx) diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala index fc7202b96b..5f193eb211 100644 --- a/src/library/scala/collection/TraversableLike.scala +++ b/src/library/scala/collection/TraversableLike.scala @@ -86,7 +86,7 @@ trait TraversableLike[+A, +Repr] extends Any def repr: Repr = this.asInstanceOf[Repr] final def isTraversableAgain: Boolean = true - + /** The underlying collection seen as an instance of `$Coll`. * By default this is implemented as the current collection object itself, * but this can be overridden. @@ -174,7 +174,7 @@ trait TraversableLike[+A, +Repr] extends Any * * @usecase def ++:[B](that: TraversableOnce[B]): $Coll[B] * @inheritdoc - * + * * Example: * {{{ * scala> val x = List(1) @@ -660,7 +660,6 @@ trait TraversableLike[+A, +Repr] extends Any def view = new TraversableView[A, Repr] { protected lazy val underlying = self.repr override def foreach[U](f: A => U) = self foreach f - override def isEmpty = self.isEmpty } /** Creates a non-strict view of a slice of this $coll. diff --git a/src/library/scala/collection/TraversableViewLike.scala b/src/library/scala/collection/TraversableViewLike.scala index 0925fe4770..14f865c2f0 100644 --- a/src/library/scala/collection/TraversableViewLike.scala +++ b/src/library/scala/collection/TraversableViewLike.scala @@ -59,7 +59,7 @@ trait ViewMkString[+A] { * $viewInfo * * All views for traversable collections are defined by creating a new `foreach` method. - * + * * @author Martin Odersky * @version 2.8 * @since 2.8 @@ -162,7 +162,7 @@ trait TraversableViewLike[+A, // if (b.isInstanceOf[NoBuilder[_]]) newFlatMapped(f).asInstanceOf[That] // else super.flatMap[B, That](f)(bf) } - override def flatten[B](implicit asTraversable: A => /*<:<!!!*/ GenTraversableOnce[B]) = + override def flatten[B](implicit asTraversable: A => /*<:<!!!*/ GenTraversableOnce[B]) = newFlatMapped(asTraversable) private[this] implicit def asThis(xs: Transformed[A]): This = xs.asInstanceOf[This] @@ -193,15 +193,6 @@ trait TraversableViewLike[+A, override def span(p: A => Boolean): (This, This) = (newTakenWhile(p), newDroppedWhile(p)) override def splitAt(n: Int): (This, This) = (newTaken(n), newDropped(n)) - // Without this, isEmpty tests go back to the Traversable default, which - // involves starting a foreach, which can force the first element of the - // view. This is just a backstop - it's overridden at all the "def view" - // instantiation points in the collections where the Coll type is known. - override def isEmpty = underlying match { - case x: GenTraversableOnce[_] => x.isEmpty - case _ => super.isEmpty - } - override def scanLeft[B, That](z: B)(op: (B, A) => B)(implicit bf: CanBuildFrom[This, B, That]): That = newForced(thisSeq.scanLeft(z)(op)).asInstanceOf[That] diff --git a/src/library/scala/collection/convert/WrapAsJava.scala b/src/library/scala/collection/convert/WrapAsJava.scala index 9115b9e5fb..5e6126a7cf 100644 --- a/src/library/scala/collection/convert/WrapAsJava.scala +++ b/src/library/scala/collection/convert/WrapAsJava.scala @@ -10,10 +10,11 @@ package scala.collection package convert import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc } -import Wrappers._ import scala.language.implicitConversions trait WrapAsJava { + import Wrappers._ + /** * Implicitly converts a Scala Iterator to a Java Iterator. * The returned Java Iterator is backed by the provided Scala diff --git a/src/library/scala/collection/convert/WrapAsScala.scala b/src/library/scala/collection/convert/WrapAsScala.scala index 5a5d204ece..ffcca62291 100644 --- a/src/library/scala/collection/convert/WrapAsScala.scala +++ b/src/library/scala/collection/convert/WrapAsScala.scala @@ -10,11 +10,13 @@ package scala.collection package convert import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc } -import Wrappers._ import scala.language.implicitConversions trait LowPriorityWrapAsScala { this: WrapAsScala => + + import Wrappers._ + /** * Implicitly converts a Java ConcurrentMap to a Scala mutable ConcurrentMap. * The returned Scala ConcurrentMap is backed by the provided Java @@ -34,6 +36,7 @@ trait LowPriorityWrapAsScala { } trait WrapAsScala extends LowPriorityWrapAsScala { + import Wrappers._ /** * Implicitly converts a Java `Iterator` to a Scala `Iterator`. * diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala index 3b6ab81146..802e16605d 100644 --- a/src/library/scala/collection/immutable/Range.scala +++ b/src/library/scala/collection/immutable/Range.scala @@ -33,7 +33,6 @@ import scala.collection.parallel.immutable.ParRange * @see [[http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#ranges "Scala's Collection Library overview"]] * section on `Ranges` for more information. * - * @define Coll Range * @define coll range * @define mayNotTerminateInf * @define willNotTerminateInf diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala index 426ab6f0fb..be2cd91c68 100644 --- a/src/library/scala/collection/immutable/Stream.scala +++ b/src/library/scala/collection/immutable/Stream.scala @@ -937,7 +937,6 @@ self => override def view = new StreamView[A, Stream[A]] { protected lazy val underlying = self.repr - override def isEmpty = self.isEmpty override def iterator = self.iterator override def length = self.length override def apply(idx: Int) = self.apply(idx) diff --git a/src/library/scala/collection/mutable/FlatHashTable.scala b/src/library/scala/collection/mutable/FlatHashTable.scala index c0299479f3..91e95e039b 100644 --- a/src/library/scala/collection/mutable/FlatHashTable.scala +++ b/src/library/scala/collection/mutable/FlatHashTable.scala @@ -110,24 +110,23 @@ trait FlatHashTable[A] extends FlatHashTable.HashUtils[A] { /** Finds an entry in the hash table if such an element exists. */ protected def findEntry(elem: A): Option[A] = { - var h = index(elemHashCode(elem)) - var entry = table(h) - while (null != entry && entry != elem) { - h = (h + 1) % table.length - entry = table(h) - } + val entry = findEntryImpl(elem) if (null == entry) None else Some(entry.asInstanceOf[A]) } /** Checks whether an element is contained in the hash table. */ protected def containsEntry(elem: A): Boolean = { + null != findEntryImpl(elem) + } + + private def findEntryImpl(elem: A): AnyRef = { var h = index(elemHashCode(elem)) var entry = table(h) while (null != entry && entry != elem) { h = (h + 1) % table.length entry = table(h) } - null != entry + entry } /** Add entry if not yet in table. diff --git a/src/library/scala/collection/mutable/IndexedSeqLike.scala b/src/library/scala/collection/mutable/IndexedSeqLike.scala index 21cff70473..f0c31ec7fb 100644 --- a/src/library/scala/collection/mutable/IndexedSeqLike.scala +++ b/src/library/scala/collection/mutable/IndexedSeqLike.scala @@ -53,7 +53,6 @@ trait IndexedSeqLike[A, +Repr] extends Any with scala.collection.IndexedSeqLike[ */ override def view = new IndexedSeqView[A, Repr] { protected lazy val underlying = self.repr - override def isEmpty = self.isEmpty override def iterator = self.iterator override def length = self.length override def apply(idx: Int) = self.apply(idx) diff --git a/src/library/scala/collection/mutable/MutableList.scala b/src/library/scala/collection/mutable/MutableList.scala index 183de5b727..fd92d2e555 100644 --- a/src/library/scala/collection/mutable/MutableList.scala +++ b/src/library/scala/collection/mutable/MutableList.scala @@ -56,12 +56,16 @@ extends AbstractSeq[A] /** Returns the rest of this list */ override def tail: MutableList[A] = { - require(nonEmpty, "tail of empty list") val tl = new MutableList[A] + tailImpl(tl) + tl + } + + protected final def tailImpl(tl: MutableList[A]) { + require(nonEmpty, "tail of empty list") tl.first0 = first0.tail - tl.last0 = last0 tl.len = len - 1 - tl + tl.last0 = if (tl.len == 0) tl.first0 else last0 } /** Prepends a single element to this list. This operation takes constant diff --git a/src/library/scala/collection/mutable/Queue.scala b/src/library/scala/collection/mutable/Queue.scala index 5ea012eb9f..b947fa3cca 100644 --- a/src/library/scala/collection/mutable/Queue.scala +++ b/src/library/scala/collection/mutable/Queue.scala @@ -66,7 +66,7 @@ extends MutableList[A] else { val res = first0.elem first0 = first0.next - len -= 1 + decrementLength() res } @@ -82,11 +82,11 @@ extends MutableList[A] else if (p(first0.elem)) { val res: Option[A] = Some(first0.elem) first0 = first0.next - len -= 1 + decrementLength() res } else { val optElem = removeFromList(p) - if (optElem != None) len -= 1 + if (optElem != None) decrementLength() optElem } @@ -119,7 +119,7 @@ extends MutableList[A] while ((first0.nonEmpty) && p(first0.elem)) { res += first0.elem first0 = first0.next - len -= 1 + decrementLength() } if (first0.isEmpty) res else removeAllFromList(p, res) @@ -130,10 +130,10 @@ extends MutableList[A] var leftlst = first0 while (leftlst.next.nonEmpty) { if (p(leftlst.next.elem)) { - res += leftlst.next.elem - if (leftlst.next eq last0) last0 = leftlst - leftlst.next = leftlst.next.next - len -= 1 + res += leftlst.next.elem + if (leftlst.next eq last0) last0 = leftlst + leftlst.next = leftlst.next.next + decrementLength() } else leftlst = leftlst.next } res @@ -154,7 +154,7 @@ extends MutableList[A] else { val res: Option[LinkedList[A]] = Some(cell.next) cell.next = cell.next.next - len -= 1 + decrementLength() res } } @@ -170,11 +170,8 @@ extends MutableList[A] // TODO - Don't override this just for new to create appropriate type.... override def tail: Queue[A] = { - require(nonEmpty, "tail of empty list") val tl = new Queue[A] - tl.first0 = first0.tail - tl.last0 = last0 - tl.len = len - 1 + tailImpl(tl) tl } @@ -183,6 +180,11 @@ extends MutableList[A] bf ++= seq bf.result } + + private[this] def decrementLength() { + len -= 1 + if (len == 0) last0 = first0 + } } diff --git a/src/library/scala/collection/parallel/ParIterableLike.scala b/src/library/scala/collection/parallel/ParIterableLike.scala index 9825587b0e..0f06ff37af 100644 --- a/src/library/scala/collection/parallel/ParIterableLike.scala +++ b/src/library/scala/collection/parallel/ParIterableLike.scala @@ -171,9 +171,9 @@ self: ParIterableLike[T, Repr, Sequential] => /** The task support object which is responsible for scheduling and * load-balancing tasks to processors. - * + * * @see [[scala.collection.parallel.TaskSupport]] - */ + */ def tasksupport = { val ts = _tasksupport if (ts eq null) { @@ -188,18 +188,18 @@ self: ParIterableLike[T, Repr, Sequential] => * A task support object can be changed in a parallel collection after it * has been created, but only during a quiescent period, i.e. while there * are no concurrent invocations to parallel collection methods. - * - * Here is a way to change the task support of a parallel collection: - * - * {{{ - * import scala.collection.parallel._ - * val pc = mutable.ParArray(1, 2, 3) - * pc.tasksupport = new ForkJoinTaskSupport( - * new scala.concurrent.forkjoin.ForkJoinPool(2)) - * }}} + * + * Here is a way to change the task support of a parallel collection: + * + * {{{ + * import scala.collection.parallel._ + * val pc = mutable.ParArray(1, 2, 3) + * pc.tasksupport = new ForkJoinTaskSupport( + * new scala.concurrent.forkjoin.ForkJoinPool(2)) + * }}} * * @see [[scala.collection.parallel.TaskSupport]] - */ + */ def tasksupport_=(ts: TaskSupport) = _tasksupport = ts def seq: Sequential @@ -848,7 +848,6 @@ self: ParIterableLike[T, Repr, Sequential] => override def seq = self.seq.view def splitter = self.splitter def size = splitter.remaining - override def isEmpty = size == 0 } override def toArray[U >: T: ClassTag]: Array[U] = { @@ -878,13 +877,13 @@ self: ParIterableLike[T, Repr, Sequential] => override def toSet[U >: T]: immutable.ParSet[U] = toParCollection[U, immutable.ParSet[U]](() => immutable.ParSet.newCombiner[U]) override def toMap[K, V](implicit ev: T <:< (K, V)): immutable.ParMap[K, V] = toParMap[K, V, immutable.ParMap[K, V]](() => immutable.ParMap.newCombiner[K, V]) - + override def toVector: Vector[T] = to[Vector] override def to[Col[_]](implicit cbf: CanBuildFrom[Nothing, T, Col[T @uncheckedVariance]]): Col[T @uncheckedVariance] = if (cbf().isCombiner) { toParCollection[T, Col[T]](() => cbf().asCombiner) } else seq.to(cbf) - + /* tasks */ protected trait StrictSplitterCheckTask[R, Tp] extends Task[R, Tp] { diff --git a/src/library/scala/collection/parallel/ParSeqLike.scala b/src/library/scala/collection/parallel/ParSeqLike.scala index 4f1c3fa7a2..201b624c72 100644 --- a/src/library/scala/collection/parallel/ParSeqLike.scala +++ b/src/library/scala/collection/parallel/ParSeqLike.scala @@ -44,7 +44,7 @@ trait ParSeqLike[+T, +Repr <: ParSeq[T], +Sequential <: Seq[T] with SeqLike[T, S extends scala.collection.GenSeqLike[T, Repr] with ParIterableLike[T, Repr, Sequential] { self => - + type SuperParIterator = IterableSplitter[T] /** A more refined version of the iterator found in the `ParallelIterable` trait, @@ -330,7 +330,6 @@ self => def apply(idx: Int) = self(idx) override def seq = self.seq.view def splitter = self.splitter - override def isEmpty = size == 0 } /* tasks */ diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala index 320a4f22b8..4b9e74708d 100644 --- a/src/library/scala/concurrent/Future.scala +++ b/src/library/scala/concurrent/Future.scala @@ -522,29 +522,6 @@ trait Future[+T] extends Awaitable[T] { p.future } - /** Creates a new future which holds the result of either this future or `that` future, depending on - * which future was completed first. - * - * $nonDeterministic - * - * Example: - * {{{ - * val f = future { sys.error("failed") } - * val g = future { 5 } - * val h = f either g - * await(h, 0) // evaluates to either 5 or throws a runtime exception - * }}} - */ - def either[U >: T](that: Future[U]): Future[U] = { - val p = Promise[U]() - val completePromise: PartialFunction[Try[U], _] = { case result => p tryComplete result } - - this onComplete completePromise - that onComplete completePromise - - p.future - } - } diff --git a/src/library/scala/concurrent/package.scala b/src/library/scala/concurrent/package.scala index f7c732b851..3e849f1722 100644 --- a/src/library/scala/concurrent/package.scala +++ b/src/library/scala/concurrent/package.scala @@ -29,13 +29,12 @@ package object concurrent { */ def future[T](body: =>T)(implicit execctx: ExecutionContext): Future[T] = Future[T](body) - /** Creates a promise object which can be completed with a value. + /** Creates a promise object which can be completed with a value or an exception. * * @tparam T the type of the value in the promise - * @param execctx the execution context on which the promise is created on * @return the newly created `Promise` object */ - def promise[T]()(implicit execctx: ExecutionContext): Promise[T] = Promise[T]() + def promise[T](): Promise[T] = Promise[T]() /** Used to designate a piece of code which potentially blocks, allowing the current [[BlockContext]] to adjust * the runtime's behavior. diff --git a/src/library/scala/util/Random.scala b/src/library/scala/util/Random.scala index 24c4cd7a32..2b11594f66 100644 --- a/src/library/scala/util/Random.scala +++ b/src/library/scala/util/Random.scala @@ -17,7 +17,7 @@ import scala.language.{implicitConversions, higherKinds} * @author Stephane Micheloud * */ -class Random(val self: java.util.Random) { +class Random(val self: java.util.Random) extends AnyRef with Serializable { /** Creates a new random number generator using a single long seed. */ def this(seed: Long) = this(new java.util.Random(seed)) diff --git a/src/partest/scala/tools/partest/DirectTest.scala b/src/partest/scala/tools/partest/DirectTest.scala index 554e7848c7..8c18809ad6 100644 --- a/src/partest/scala/tools/partest/DirectTest.scala +++ b/src/partest/scala/tools/partest/DirectTest.scala @@ -8,6 +8,7 @@ package scala.tools.partest import scala.tools.nsc._ import io.Directory import util.{BatchSourceFile, CommandLineParser} +import reporters.{Reporter, ConsoleReporter} /** A class for testing code which is embedded as a string. * It allows for more complete control over settings, compiler @@ -38,9 +39,12 @@ abstract class DirectTest extends App { // new compiler def newCompiler(args: String*): Global = { val settings = newSettings((CommandLineParser tokenize ("-d \"" + testOutput.path + "\" " + extraSettings)) ++ args.toList) - if (settings.Yrangepos.value) new Global(settings) with interactive.RangePositions - else new Global(settings) + if (settings.Yrangepos.value) new Global(settings, reporter(settings)) with interactive.RangePositions + else new Global(settings, reporter(settings)) } + + def reporter(settings: Settings): Reporter = new ConsoleReporter(settings) + def newSources(sourceCodes: String*) = sourceCodes.toList.zipWithIndex map { case (src, idx) => new BatchSourceFile("newSource" + (idx + 1), src) } diff --git a/src/partest/scala/tools/partest/StoreReporterDirectTest.scala b/src/partest/scala/tools/partest/StoreReporterDirectTest.scala new file mode 100644 index 0000000000..7f3604c86c --- /dev/null +++ b/src/partest/scala/tools/partest/StoreReporterDirectTest.scala @@ -0,0 +1,15 @@ +package scala.tools.partest + +import scala.tools.nsc.Settings +import scala.tools.nsc.reporters.StoreReporter +import scala.collection.mutable + +trait StoreReporterDirectTest extends DirectTest { + lazy val storeReporter: StoreReporter = new scala.tools.nsc.reporters.StoreReporter() + + /** Discards all but the first message issued at a given position. */ + def filteredInfos: Seq[storeReporter.Info] = storeReporter.infos.groupBy(_.pos).map(_._2.head).toList + + /** Hook into [[scala.tools.partest.DirectTest]] to install the custom reporter */ + override def reporter(settings: Settings) = storeReporter +} diff --git a/src/reflect/scala/reflect/api/BuildUtils.scala b/src/reflect/scala/reflect/api/BuildUtils.scala index 0c8e81a220..8f256aa1f5 100644 --- a/src/reflect/scala/reflect/api/BuildUtils.scala +++ b/src/reflect/scala/reflect/api/BuildUtils.scala @@ -59,8 +59,6 @@ private[reflect] trait BuildUtils { self: Universe => def flagsFromBits(bits: Long): FlagSet - def emptyValDef: ValDef - def This(sym: Symbol): Tree def Select(qualifier: Tree, sym: Symbol): Select diff --git a/src/reflect/scala/reflect/api/Trees.scala b/src/reflect/scala/reflect/api/Trees.scala index c98107f9b5..cfa6315797 100644 --- a/src/reflect/scala/reflect/api/Trees.scala +++ b/src/reflect/scala/reflect/api/Trees.scala @@ -75,11 +75,26 @@ trait Trees { self: Universe => def isDef: Boolean /** Is this tree one of the empty trees? + * * Empty trees are: the `EmptyTree` null object, `TypeTree` instances that don't carry a type * and the special `emptyValDef` singleton. + * + * In the compiler the `isEmpty` check and the derived `orElse` method are mostly used + * as a check for a tree being a null object (`EmptyTree` for term trees and empty TypeTree for type trees). + * + * Unfortunately `emptyValDef` is also considered to be `isEmpty`, but this is deemed to be + * a conceptual mistake pending a fix in https://issues.scala-lang.org/browse/SI-6762. + * + * @see `canHaveAttrs` */ def isEmpty: Boolean + /** Can this tree carry attributes (i.e. symbols, types or positions)? + * Typically the answer is yes, except for the `EmptyTree` null object and + * two special singletons: `emptyValDef` and `pendingSuperCall`. + */ + def canHaveAttrs: Boolean + /** The canonical way to test if a Tree represents a term. */ def isTerm: Boolean @@ -1611,14 +1626,23 @@ trait Trees { self: Universe => * This node always occurs in the following context: * * (`new` tpt).<init>[targs](args) + * + * For example, an AST representation of: + * + * new Example[Int](2)(3) + * + * is the following code: + * + * Apply( + * Apply( + * TypeApply( + * Select(New(TypeTree(typeOf[Example])), nme.CONSTRUCTOR) + * TypeTree(typeOf[Int])), + * List(Literal(Constant(2)))), + * List(Literal(Constant(3)))) * @group Extractors */ abstract class NewExtractor { - /** A user level `new`. - * One should always use this factory method to build a user level `new`. - * - * @param tpt a class type - */ def apply(tpt: Tree): New def unapply(new_ : New): Option[Tree] } @@ -1720,6 +1744,16 @@ trait Trees { self: Universe => * This AST node corresponds to the following Scala code: * * fun[args] + * + * Should only be used with `fun` nodes which are terms, i.e. which have `isTerm` returning `true`. + * Otherwise `AppliedTypeTree` should be used instead. + * + * def foo[T] = ??? + * foo[Int] // represented as TypeApply(Ident(<foo>), List(TypeTree(<Int>))) + * + * List[Int] as in `val x: List[Int] = ???` + * // represented as AppliedTypeTree(Ident(<List>), List(TypeTree(<Int>))) + * * @group Extractors */ abstract class TypeApplyExtractor { @@ -1890,6 +1924,12 @@ trait Trees { self: Universe => * This AST node corresponds to the following Scala code: * * qualifier.selector + * + * Should only be used with `qualifier` nodes which are terms, i.e. which have `isTerm` returning `true`. + * Otherwise `SelectFromTypeTree` should be used instead. + * + * foo.Bar // represented as Select(Ident(<foo>), <Bar>) + * Foo#Bar // represented as SelectFromTypeTree(Ident(<Foo>), <Bar>) * @group Extractors */ abstract class SelectExtractor { @@ -2122,7 +2162,6 @@ trait Trees { self: Universe => * @group Trees * @template */ - // [Eugene++] don't see why we need it, when we have Select type SelectFromTypeTree >: Null <: TypTree with RefTree with SelectFromTypeTreeApi /** A tag that preserves the identity of the `SelectFromTypeTree` abstract type from erasure. @@ -2142,6 +2181,12 @@ trait Trees { self: Universe => * qualifier # selector * * Note: a path-dependent type p.T is expressed as p.type # T + * + * Should only be used with `qualifier` nodes which are types, i.e. which have `isType` returning `true`. + * Otherwise `Select` should be used instead. + * + * Foo#Bar // represented as SelectFromTypeTree(Ident(<Foo>), <Bar>) + * foo.Bar // represented as Select(Ident(<foo>), <Bar>) * @group Extractors */ abstract class SelectFromTypeTreeExtractor { @@ -2217,6 +2262,15 @@ trait Trees { self: Universe => * This AST node corresponds to the following Scala code: * * tpt[args] + * + * Should only be used with `tpt` nodes which are types, i.e. which have `isType` returning `true`. + * Otherwise `TypeApply` should be used instead. + * + * List[Int] as in `val x: List[Int] = ???` + * // represented as AppliedTypeTree(Ident(<List>), List(TypeTree(<Int>))) + * + * def foo[T] = ??? + * foo[Int] // represented as TypeApply(Ident(<foo>), List(TypeTree(<Int>))) * @group Extractors */ abstract class AppliedTypeTreeExtractor { @@ -2366,123 +2420,155 @@ trait Trees { self: Universe => */ val emptyValDef: ValDef + /** An empty superclass constructor call corresponding to: + * super.<init>() + * This is used as a placeholder in the primary constructor body in class templates + * to denote the insertion point of a call to superclass constructor after the typechecker + * figures out the superclass of a given template. + * @group Trees + */ + val pendingSuperCall: Apply + // ---------------------- factories ---------------------------------------------- /** A factory method for `ClassDef` nodes. * @group Factories */ + @deprecated("Use the canonical ClassDef constructor to create a class and then initialize its position and symbol manually", "2.10.1") def ClassDef(sym: Symbol, impl: Template): ClassDef /** A factory method for `ModuleDef` nodes. * @group Factories */ + @deprecated("Use the canonical ModuleDef constructor to create an object and then initialize its position and symbol manually", "2.10.1") def ModuleDef(sym: Symbol, impl: Template): ModuleDef /** A factory method for `ValDef` nodes. * @group Factories */ + @deprecated("Use the canonical ValDef constructor to create a val and then initialize its position and symbol manually", "2.10.1") def ValDef(sym: Symbol, rhs: Tree): ValDef /** A factory method for `ValDef` nodes. * @group Factories */ + @deprecated("Use the canonical ValDef constructor to create a val with an empty right-hand side and then initialize its position and symbol manually", "2.10.1") def ValDef(sym: Symbol): ValDef /** A factory method for `ValDef` nodes. * @group Factories */ + @deprecated("Use the canonical DefDef constructor to create a method and then initialize its position and symbol manually", "2.10.1") def DefDef(sym: Symbol, mods: Modifiers, vparamss: List[List[ValDef]], rhs: Tree): DefDef /** A factory method for `ValDef` nodes. * @group Factories */ + @deprecated("Use the canonical DefDef constructor to create a method and then initialize its position and symbol manually", "2.10.1") def DefDef(sym: Symbol, vparamss: List[List[ValDef]], rhs: Tree): DefDef /** A factory method for `ValDef` nodes. * @group Factories */ + @deprecated("Use the canonical DefDef constructor to create a method and then initialize its position and symbol manually", "2.10.1") def DefDef(sym: Symbol, mods: Modifiers, rhs: Tree): DefDef /** A factory method for `ValDef` nodes. * @group Factories */ + @deprecated("Use the canonical DefDef constructor to create a method and then initialize its position and symbol manually", "2.10.1") def DefDef(sym: Symbol, rhs: Tree): DefDef /** A factory method for `ValDef` nodes. * @group Factories */ + @deprecated("Use the canonical DefDef constructor to create a method and then initialize its position and symbol manually", "2.10.1") def DefDef(sym: Symbol, rhs: List[List[Symbol]] => Tree): DefDef /** A factory method for `TypeDef` nodes. * @group Factories */ + @deprecated("Use the canonical TypeDef constructor to create a type alias and then initialize its position and symbol manually", "2.10.1") def TypeDef(sym: Symbol, rhs: Tree): TypeDef /** A factory method for `TypeDef` nodes. * @group Factories */ + @deprecated("Use the canonical TypeDef constructor to create an abstract type or type parameter and then initialize its position and symbol manually", "2.10.1") def TypeDef(sym: Symbol): TypeDef /** A factory method for `LabelDef` nodes. * @group Factories */ + @deprecated("Use the canonical LabelDef constructor to create a label and then initialize its position and symbol manually", "2.10.1") def LabelDef(sym: Symbol, params: List[Symbol], rhs: Tree): LabelDef /** A factory method for `Block` nodes. * Flattens directly nested blocks. * @group Factories */ + @deprecated("Use the canonical Block constructor, explicitly specifying its expression if necessary. Flatten directly nested blocks manually if needed", "2.10.1") def Block(stats: Tree*): Block /** A factory method for `CaseDef` nodes. * @group Factories */ + @deprecated("Use the canonical CaseDef constructor passing EmptyTree for guard", "2.10.1") def CaseDef(pat: Tree, body: Tree): CaseDef /** A factory method for `Bind` nodes. * @group Factories */ + @deprecated("Use the canonical Bind constructor to create a bind and then initialize its symbol manually", "2.10.1") def Bind(sym: Symbol, body: Tree): Bind /** A factory method for `Try` nodes. * @group Factories */ + @deprecated("Use canonical CaseDef constructors to to create exception catching expressions and then wrap them in Try", "2.10.1") def Try(body: Tree, cases: (Tree, Tree)*): Try /** A factory method for `Throw` nodes. * @group Factories */ + @deprecated("Use the canonical New constructor to create an object instantiation expression and then wrap it in Throw", "2.10.1") def Throw(tpe: Type, args: Tree*): Throw /** Factory method for object creation `new tpt(args_1)...(args_n)` * A `New(t, as)` is expanded to: `(new t).<init>(as)` * @group Factories */ + @deprecated("Use Apply(...Apply(Select(New(tpt), nme.CONSTRUCTOR), args1)...argsN) instead", "2.10.1") def New(tpt: Tree, argss: List[List[Tree]]): Tree /** 0-1 argument list new, based on a type. * @group Factories */ + @deprecated("Use New(TypeTree(tpe), args.toList) instead", "2.10.1") def New(tpe: Type, args: Tree*): Tree /** 0-1 argument list new, based on a symbol. * @group Factories */ + @deprecated("Use New(sym.toType, args) instead", "2.10.1") def New(sym: Symbol, args: Tree*): Tree /** A factory method for `Apply` nodes. * @group Factories */ + @deprecated("Use Apply(Ident(sym), args.toList) instead", "2.10.1") def Apply(sym: Symbol, args: Tree*): Tree /** 0-1 argument list new, based on a type tree. * @group Factories */ + @deprecated("Use Apply(Select(New(tpt), nme.CONSTRUCTOR), args) instead", "2.10.1") def ApplyConstructor(tpt: Tree, args: List[Tree]): Tree /** A factory method for `Super` nodes. * @group Factories */ + @deprecated("Use Super(This(sym), mix) instead", "2.10.1") def Super(sym: Symbol, mix: TypeName): Tree /** A factory method for `This` nodes. @@ -2494,6 +2580,7 @@ trait Trees { self: Universe => * The string `name` argument is assumed to represent a [[scala.reflect.api.Names#TermName `TermName`]]. * @group Factories */ + @deprecated("Use Select(tree, newTermName(name)) instead", "2.10.1") def Select(qualifier: Tree, name: String): Select /** A factory method for `Select` nodes. @@ -2504,6 +2591,7 @@ trait Trees { self: Universe => /** A factory method for `Ident` nodes. * @group Factories */ + @deprecated("Use Ident(newTermName(name)) instead", "2.10.1") def Ident(name: String): Ident /** A factory method for `Ident` nodes. @@ -2843,7 +2931,8 @@ trait Trees { self: Universe => trees mapConserve (tree => transform(tree).asInstanceOf[TypeDef]) /** Transforms a `ValDef`. */ def transformValDef(tree: ValDef): ValDef = - if (tree.isEmpty) tree else transform(tree).asInstanceOf[ValDef] + if (tree eq emptyValDef) tree + else transform(tree).asInstanceOf[ValDef] /** Transforms a list of `ValDef` nodes. */ def transformValDefs(trees: List[ValDef]): List[ValDef] = trees mapConserve (transformValDef(_)) diff --git a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala index d72f08674e..3c2b128c52 100644 --- a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala +++ b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala @@ -60,7 +60,7 @@ trait BaseTypeSeqs { elems(i) match { case rtp @ RefinedType(variants, decls) => // can't assert decls.isEmpty; see t0764 - //if (!decls.isEmpty) assert(false, "computing closure of "+this+":"+this.isInstanceOf[RefinedType]+"/"+closureCache(j)) + //if (!decls.isEmpty) abort("computing closure of "+this+":"+this.isInstanceOf[RefinedType]+"/"+closureCache(j)) //Console.println("compute closure of "+this+" => glb("+variants+")") pending += i try { diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala index 9f41f0336e..b1b0c5b60b 100644 --- a/src/reflect/scala/reflect/internal/BuildUtils.scala +++ b/src/reflect/scala/reflect/internal/BuildUtils.scala @@ -47,8 +47,6 @@ trait BuildUtils { self: SymbolTable => def flagsFromBits(bits: Long): FlagSet = bits - def emptyValDef: ValDef = self.emptyValDef - def This(sym: Symbol): Tree = self.This(sym) def Select(qualifier: Tree, sym: Symbol): Select = self.Select(qualifier, sym) diff --git a/src/reflect/scala/reflect/internal/Importers.scala b/src/reflect/scala/reflect/internal/Importers.scala index 43902c1930..2f2b02975c 100644 --- a/src/reflect/scala/reflect/internal/Importers.scala +++ b/src/reflect/scala/reflect/internal/Importers.scala @@ -334,6 +334,8 @@ trait Importers extends api.Importers { self: SymbolTable => new ModuleDef(importModifiers(mods), importName(name).toTermName, importTemplate(impl)) case from.emptyValDef => emptyValDef + case from.pendingSuperCall => + pendingSuperCall case from.ValDef(mods, name, tpt, rhs) => new ValDef(importModifiers(mods), importName(name).toTermName, importTree(tpt), importTree(rhs)) case from.DefDef(mods, name, tparams, vparamss, tpt, rhs) => diff --git a/src/reflect/scala/reflect/internal/Positions.scala b/src/reflect/scala/reflect/internal/Positions.scala index faa161d6b1..f8c670827a 100644 --- a/src/reflect/scala/reflect/internal/Positions.scala +++ b/src/reflect/scala/reflect/internal/Positions.scala @@ -38,7 +38,7 @@ trait Positions extends api.Positions { self: SymbolTable => protected class DefaultPosAssigner extends PosAssigner { var pos: Position = _ override def traverse(t: Tree) { - if (t eq EmptyTree) () + if (!t.canHaveAttrs) () else if (t.pos == NoPosition) { t.setPos(pos) super.traverse(t) // TODO: bug? shouldn't the traverse be outside of the if? diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala index 80d247c0ea..a8085a4c58 100644 --- a/src/reflect/scala/reflect/internal/Printers.scala +++ b/src/reflect/scala/reflect/internal/Printers.scala @@ -435,7 +435,7 @@ trait Printers extends api.Printers { self: SymbolTable => case tree => xprintTree(this, tree) } - if (printTypes && tree.isTerm && !tree.isEmpty) { + if (printTypes && tree.isTerm && tree.canHaveAttrs) { print("{", if (tree.tpe eq null) "<null>" else tree.tpe.toString, "}") } } @@ -542,8 +542,10 @@ trait Printers extends api.Printers { self: SymbolTable => print(")") case EmptyTree => print("EmptyTree") - case emptyValDef: AnyRef if emptyValDef eq self.emptyValDef => + case self.emptyValDef => print("emptyValDef") + case self.pendingSuperCall => + print("pendingSuperCall") case tree: Tree => val hasSymbol = tree.hasSymbol && tree.symbol != NoSymbol val isError = hasSymbol && tree.symbol.name.toString == nme.ERROR.toString diff --git a/src/reflect/scala/reflect/internal/StdAttachments.scala b/src/reflect/scala/reflect/internal/StdAttachments.scala index 9fe443bf50..1df91a67b0 100644 --- a/src/reflect/scala/reflect/internal/StdAttachments.scala +++ b/src/reflect/scala/reflect/internal/StdAttachments.scala @@ -19,9 +19,26 @@ trait StdAttachments { def setPos(newpos: Position): this.type = { pos = newpos; this } } + /** When present, indicates that the host `Ident` has been created from a backquoted identifier. + */ case object BackquotedIdentifierAttachment + /** Stores the trees that give rise to a refined type to be used in reification. + * Unfortunately typed `CompoundTypeTree` is lacking essential info, and the reifier cannot use `CompoundTypeTree.tpe`. + * Therefore we need this hack (see `Reshape.toPreTyperTypeTree` for a detailed explanation). + */ case class CompoundTypeTreeOriginalAttachment(parents: List[Tree], stats: List[Tree]) + /** Is added by the macro engine to the results of macro expansions. + * Stores the original expandee as it entered the `macroExpand` function. + */ case class MacroExpansionAttachment(original: Tree) + + /** When present, suppresses macro expansion for the host. + * This is occasionally necessary, e.g. to prohibit eta-expansion of macros. + * + * Does not affect expandability of child nodes, there's context.withMacrosDisabled for that + * (but think thrice before using that API - see the discussion at https://github.com/scala/scala/pull/1639). + */ + case object SuppressMacroExpansionAttachment } diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index 5e7f5777b2..c870d8972d 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -730,6 +730,7 @@ trait StdNames { val null_ : NameType = "null" val ofDim: NameType = "ofDim" val origin: NameType = "origin" + val pendingSuperCall: NameType = "pendingSuperCall" val prefix : NameType = "prefix" val productArity: NameType = "productArity" val productElement: NameType = "productElement" diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala index 554acf9c0b..02ac59a461 100644 --- a/src/reflect/scala/reflect/internal/SymbolTable.scala +++ b/src/reflect/scala/reflect/internal/SymbolTable.scala @@ -345,6 +345,12 @@ abstract class SymbolTable extends macros.Universe /** Is this symbol table a part of a compiler universe? */ def isCompilerUniverse = false + + /** + * Adds the `sm` String interpolator to a [[scala.StringContext]]. + */ + implicit val StringContextStripMarginOps: StringContext => StringContextStripMarginOps = util.StringContextStripMarginOps + } object SymbolTableStats { diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 9254cc9ac9..a4287fb181 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -79,7 +79,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => def isImplementationArtifact: Boolean = (this hasFlag BRIDGE) || (this hasFlag VBRIDGE) || (this hasFlag ARTIFACT) def isJava: Boolean = isJavaDefined def isVal: Boolean = isTerm && !isModule && !isMethod && !isMutable - def isVar: Boolean = isTerm && !isModule && !isMethod && isMutable + def isVar: Boolean = isTerm && !isModule && !isMethod && !isLazy && isMutable def newNestedSymbol(name: Name, pos: Position, newFlags: Long, isClass: Boolean): Symbol = name match { case n: TermName => newTermSymbol(n, pos, newFlags) @@ -423,9 +423,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => * failure to the point when that name is used for something, which is * often to the point of never. */ - def newStubSymbol(name: Name): Symbol = name match { - case n: TypeName => new StubClassSymbol(this, n) - case _ => new StubTermSymbol(this, name.toTermName) + def newStubSymbol(name: Name, missingMessage: String): Symbol = name match { + case n: TypeName => new StubClassSymbol(this, n, missingMessage) + case _ => new StubTermSymbol(this, name.toTermName, missingMessage) } @deprecated("Use the other signature", "2.10.0") @@ -1349,6 +1349,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => } } + /** Raises a `MissingRequirementError` if this symbol is a `StubSymbol` */ + def failIfStub() {} + /** Initialize the symbol */ final def initialize: this.type = { if (!isInitialized) info @@ -3087,7 +3090,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => class RefinementClassSymbol protected[Symbols] (owner0: Symbol, pos0: Position) extends ClassSymbol(owner0, pos0, tpnme.REFINE_CLASS_NAME) { override def name_=(name: Name) { - assert(false, "Cannot set name of RefinementClassSymbol to " + name) + abort("Cannot set name of RefinementClassSymbol to " + name) super.name_=(name) } override def isRefinementClass = true @@ -3105,14 +3108,18 @@ trait Symbols extends api.Symbols { self: SymbolTable => ) } trait StubSymbol extends Symbol { - protected def stubWarning = { - val from = if (associatedFile == null) "" else s" - referenced from ${associatedFile.canonicalPath}" - s"$kindString $nameString$locationString$from (a classfile may be missing)" - } + protected def missingMessage: String + + /** Fail the stub by throwing a [[scala.reflect.internal.MissingRequirementError]]. */ + override final def failIfStub() = {MissingRequirementError.signal(missingMessage)} // + + /** Fail the stub by reporting an error to the reporter, setting the IS_ERROR flag + * on this symbol, and returning the dummy value `alt`. + */ private def fail[T](alt: T): T = { // Avoid issuing lots of redundant errors if (!hasFlag(IS_ERROR)) { - globalError(s"bad symbolic reference to " + stubWarning) + globalError(missingMessage) if (settings.debug.value) (new Throwable).printStackTrace @@ -3129,12 +3136,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def rawInfo = fail(NoType) override def companionSymbol = fail(NoSymbol) - locally { - debugwarn("creating stub symbol for " + stubWarning) - } + debugwarn("creating stub symbol to defer error: " + missingMessage) } - class StubClassSymbol(owner0: Symbol, name0: TypeName) extends ClassSymbol(owner0, owner0.pos, name0) with StubSymbol - class StubTermSymbol(owner0: Symbol, name0: TermName) extends TermSymbol(owner0, owner0.pos, name0) with StubSymbol + class StubClassSymbol(owner0: Symbol, name0: TypeName, protected val missingMessage: String) extends ClassSymbol(owner0, owner0.pos, name0) with StubSymbol + class StubTermSymbol(owner0: Symbol, name0: TermName, protected val missingMessage: String) extends TermSymbol(owner0, owner0.pos, name0) with StubSymbol trait FreeSymbol extends Symbol { def origin: String diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala index 38e55a3c01..8908036442 100644 --- a/src/reflect/scala/reflect/internal/TreeInfo.scala +++ b/src/reflect/scala/reflect/internal/TreeInfo.scala @@ -159,7 +159,7 @@ abstract class TreeInfo { * Also accounts for varargs. */ private def applyMethodParameters(fn: Tree): List[Symbol] = { - val depth = applyDepth(fn) + val depth = dissectApplied(fn).applyDepth // There could be applies which go beyond the parameter list(s), // being applied to the result of the method call. // !!! Note that this still doesn't seem correct, although it should @@ -195,29 +195,26 @@ abstract class TreeInfo { def isGetter = mayBeVarGetter(sym) && sym.owner.info.member(nme.getterToSetter(sym.name.toTermName)) != NoSymbol tree match { - case Ident(_) => isVar - case Select(_, _) => isVar || isGetter - case _ => - methPart(tree) match { - case Select(qual, nme.apply) => qual.tpe.member(nme.update) != NoSymbol - case _ => false - } + case Ident(_) => isVar + case Select(_, _) => isVar || isGetter + case Applied(Select(qual, nme.apply), _, _) => qual.tpe.member(nme.update) != NoSymbol + case _ => false } } /** Is tree a self constructor call this(...)? I.e. a call to a constructor of the * same object? */ - def isSelfConstrCall(tree: Tree): Boolean = methPart(tree) match { - case Ident(nme.CONSTRUCTOR) - | Select(This(_), nme.CONSTRUCTOR) => true + def isSelfConstrCall(tree: Tree): Boolean = tree match { + case Applied(Ident(nme.CONSTRUCTOR), _, _) => true + case Applied(Select(This(_), nme.CONSTRUCTOR), _, _) => true case _ => false } /** Is tree a super constructor call? */ - def isSuperConstrCall(tree: Tree): Boolean = methPart(tree) match { - case Select(Super(_, _), nme.CONSTRUCTOR) => true + def isSuperConstrCall(tree: Tree): Boolean = tree match { + case Applied(Select(Super(_, _), nme.CONSTRUCTOR), _, _) => true case _ => false } @@ -245,6 +242,68 @@ abstract class TreeInfo { isSelfConstrCall(tree1) || isSuperConstrCall(tree1) } + /** + * Does this tree represent an irrefutable pattern match + * in the position `for { <tree> <- expr }` based only + * on information at the `parser` phase? To qualify, there + * may be no subtree that will be interpreted as a + * Stable Identifier Pattern. + * + * For instance: + * + * {{{ + * foo @ (bar, (baz, quux)) + * }}} + * + * is a variable pattern; if the structure matches, + * then the remainder is inevitable. + * + * The following are not variable patterns. + * + * {{{ + * foo @ (bar, (`baz`, quux)) // back quoted ident, not at top level + * foo @ (bar, Quux) // UpperCase ident, not at top level + * }}} + * + * If the pattern is a simple identifier, it is always + * a variable pattern. For example, the following + * introduce new bindings: + * + * {{{ + * for { X <- xs } yield X + * for { `backquoted` <- xs } yield `backquoted` + * }}} + * + * Note that this differs from a case clause: + * + * {{{ + * object X + * scrut match { + * case X => // case _ if scrut == X + * } + * }}} + * + * Background: [[https://groups.google.com/d/msg/scala-internals/qwa_XOw_7Ks/IktkeTBYqg0J]] + * + */ + def isVarPatternDeep(tree: Tree): Boolean = { + def isVarPatternDeep0(tree: Tree): Boolean = { + tree match { + case Bind(name, pat) => isVarPatternDeep0(pat) + case Ident(name) => isVarPattern(tree) + case Apply(sel, args) => + ( isReferenceToScalaMember(sel, TupleClass(args.size).name.toTermName) + && (args forall isVarPatternDeep0) + ) + case _ => false + } + } + tree match { + case Ident(name) => true + case _ => isVarPatternDeep0(tree) + } + } + /** Is tree a variable pattern? */ def isVarPattern(pat: Tree): Boolean = pat match { case x: Ident => !x.isBackquoted && nme.isVariableName(x.name) @@ -271,6 +330,9 @@ abstract class TreeInfo { def preSuperFields(stats: List[Tree]): List[ValDef] = stats collect { case vd: ValDef if isEarlyValDef(vd) => vd } + def hasUntypedPreSuperFields(stats: List[Tree]): Boolean = + preSuperFields(stats) exists (_.tpt.isEmpty) + def isEarlyDef(tree: Tree) = tree match { case TypeDef(mods, _, _, _) => mods hasFlag PRESUPER case ValDef(mods, _, _, _) => mods hasFlag PRESUPER @@ -330,24 +392,6 @@ abstract class TreeInfo { case _ => false } - /** Is this tree comprised of nothing but identifiers, - * but possibly in bindings or tuples? For instance - * - * foo @ (bar, (baz, quux)) - * - * is a variable pattern; if the structure matches, - * then the remainder is inevitable. - */ - def isVariablePattern(tree: Tree): Boolean = tree match { - case Bind(name, pat) => isVariablePattern(pat) - case Ident(name) => true - case Apply(sel, args) => - ( isReferenceToScalaMember(sel, TupleClass(args.size).name.toTermName) - && (args forall isVariablePattern) - ) - case _ => false - } - /** Is this argument node of the form <expr> : _* ? */ def isWildcardStarArg(tree: Tree): Boolean = tree match { @@ -355,22 +399,6 @@ abstract class TreeInfo { case _ => false } - /** If this tree represents a type application (after unwrapping - * any applies) the first type argument. Otherwise, EmptyTree. - */ - def firstTypeArg(tree: Tree): Tree = tree match { - case Apply(fn, _) => firstTypeArg(fn) - case TypeApply(_, targ :: _) => targ - case _ => EmptyTree - } - - /** If this tree represents a type application the type arguments. Otherwise Nil. - */ - def typeArguments(tree: Tree): List[Tree] = tree match { - case TypeApply(_, targs) => targs - case _ => Nil - } - /** If this tree has type parameters, those. Otherwise Nil. */ def typeParameters(tree: Tree): List[TypeDef] = tree match { @@ -469,31 +497,126 @@ abstract class TreeInfo { def isSynthCaseSymbol(sym: Symbol) = sym hasAllFlags SYNTH_CASE_FLAGS def hasSynthCaseSymbol(t: Tree) = t.symbol != null && isSynthCaseSymbol(t.symbol) + def isTraitRef(tree: Tree): Boolean = { + val sym = if (tree.tpe != null) tree.tpe.typeSymbol else null + ((sym ne null) && sym.initialize.isTrait) + } - /** The method part of an application node + /** Applications in Scala can have one of the following shapes: + * + * 1) naked core: Ident(_) or Select(_, _) or basically anything else + * 2) naked core with targs: TypeApply(core, targs) or AppliedTypeTree(core, targs) + * 3) apply or several applies wrapping a core: Apply(core, _), or Apply(Apply(core, _), _), etc + * + * This class provides different ways to decompose applications and simplifies their analysis. + * + * ***Examples*** + * (TypeApply in the examples can be replaced with AppliedTypeTree) + * + * Ident(foo): + * * callee = Ident(foo) + * * core = Ident(foo) + * * targs = Nil + * * argss = Nil + * + * TypeApply(foo, List(targ1, targ2...)) + * * callee = TypeApply(foo, List(targ1, targ2...)) + * * core = foo + * * targs = List(targ1, targ2...) + * * argss = Nil + * + * Apply(foo, List(arg1, arg2...)) + * * callee = foo + * * core = foo + * * targs = Nil + * * argss = List(List(arg1, arg2...)) + * + * Apply(Apply(foo, List(arg21, arg22, ...)), List(arg11, arg12...)) + * * callee = foo + * * core = foo + * * targs = Nil + * * argss = List(List(arg11, arg12...), List(arg21, arg22, ...)) + * + * Apply(Apply(TypeApply(foo, List(targs1, targs2, ...)), List(arg21, arg22, ...)), List(arg11, arg12...)) + * * callee = TypeApply(foo, List(targs1, targs2, ...)) + * * core = foo + * * targs = Nil + * * argss = List(List(arg11, arg12...), List(arg21, arg22, ...)) */ - def methPart(tree: Tree): Tree = tree match { - case Apply(fn, _) => methPart(fn) - case TypeApply(fn, _) => methPart(fn) - case AppliedTypeTree(fn, _) => methPart(fn) - case _ => tree + class Applied(val tree: Tree) { + /** The tree stripped of the possibly nested applications. + * The original tree if it's not an application. + */ + def callee: Tree = { + def loop(tree: Tree): Tree = tree match { + case Apply(fn, _) => loop(fn) + case tree => tree + } + loop(tree) + } + + /** The `callee` unwrapped from type applications. + * The original `callee` if it's not a type application. + */ + def core: Tree = callee match { + case TypeApply(fn, _) => fn + case AppliedTypeTree(fn, _) => fn + case tree => tree + } + + /** The type arguments of the `callee`. + * `Nil` if the `callee` is not a type application. + */ + def targs: List[Tree] = callee match { + case TypeApply(_, args) => args + case AppliedTypeTree(_, args) => args + case _ => Nil + } + + /** (Possibly multiple lists of) value arguments of an application. + * `Nil` if the `callee` is not an application. + */ + def argss: List[List[Tree]] = { + def loop(tree: Tree): List[List[Tree]] = tree match { + case Apply(fn, args) => loop(fn) :+ args + case _ => Nil + } + loop(tree) + } + + /** The depth of the nested applies: e.g. Apply(Apply(Apply(_, _), _), _) + * has depth 3. Continues through type applications (without counting them.) + */ + def applyDepth: Int = { + def loop(tree: Tree): Int = tree match { + case Apply(fn, _) => 1 + loop(fn) + case TypeApply(fn, _) => loop(fn) + case AppliedTypeTree(fn, _) => loop(fn) + case _ => 0 + } + loop(tree) + } } - /** The depth of the nested applies: e.g. Apply(Apply(Apply(_, _), _), _) - * has depth 3. Continues through type applications (without counting them.) + /** Returns a wrapper that knows how to destructure and analyze applications. */ - def applyDepth(tree: Tree): Int = tree match { - case Apply(fn, _) => 1 + applyDepth(fn) - case TypeApply(fn, _) => applyDepth(fn) - case AppliedTypeTree(fn, _) => applyDepth(fn) - case _ => 0 - } - def firstArgument(tree: Tree): Tree = tree match { - case Apply(fn, args) => - val f = firstArgument(fn) - if (f == EmptyTree && !args.isEmpty) args.head else f - case _ => - EmptyTree + def dissectApplied(tree: Tree) = new Applied(tree) + + /** Destructures applications into important subparts described in `Applied` class, + * namely into: core, targs and argss (in the specified order). + * + * Trees which are not applications are also accepted. Their callee and core will + * be equal to the input, while targs and argss will be Nil. + * + * The provided extractors don't expose all the API of the `Applied` class. + * For advanced use, call `dissectApplied` explicitly and use its methods instead of pattern matching. + */ + object Applied { + def unapply(applied: Applied): Option[(Tree, List[Tree], List[List[Tree]])] = + Some((applied.core, applied.targs, applied.argss)) + + def unapply(tree: Tree): Option[(Tree, List[Tree], List[List[Tree]])] = + unapply(dissectApplied(tree)) } /** Does list of trees start with a definition of @@ -590,7 +713,7 @@ abstract class TreeInfo { } def unapply(tree: Tree) = refPart(tree) match { - case ref: RefTree => Some((ref.qualifier.symbol, ref.symbol, typeArguments(tree))) + case ref: RefTree => Some((ref.qualifier.symbol, ref.symbol, dissectApplied(tree).targs)) case _ => None } } diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index 74bde132cb..dceec18e57 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -36,6 +36,7 @@ trait Trees extends api.Trees { self: SymbolTable => def isDef = false def isEmpty = false + def canHaveAttrs = true /** The canonical way to test if a Tree represents a term. */ @@ -228,14 +229,6 @@ trait Trees extends api.Trees { self: SymbolTable => override def isDef = true } - case object EmptyTree extends TermTree { - val asList = List(this) - super.tpe_=(NoType) - override def tpe_=(t: Type) = - if (t != NoType) throw new UnsupportedOperationException("tpe_=("+t+") inapplicable for <empty>") - override def isEmpty = true - } - abstract class MemberDef extends DefTree with MemberDefApi { def mods: Modifiers def keyword: String = this match { @@ -391,6 +384,9 @@ trait Trees extends api.Trees { self: SymbolTable => case class TypeApply(fun: Tree, args: List[Tree]) extends GenericApply with TypeApplyApi { + + assert(fun.isTerm, fun) + override def symbol: Symbol = fun.symbol override def symbol_=(sym: Symbol) { fun.symbol = sym } } @@ -426,7 +422,11 @@ trait Trees extends api.Trees { self: SymbolTable => object This extends ThisExtractor case class Select(qualifier: Tree, name: Name) - extends RefTree with SelectApi + extends RefTree with SelectApi { + + // !!! assert disabled due to test case pos/annotDepMethType.scala triggering it. + // assert(qualifier.isTerm, qualifier) + } object Select extends SelectExtractor case class Ident(name: Name) extends RefTree with IdentContextApi { @@ -458,7 +458,10 @@ trait Trees extends api.Trees { self: SymbolTable => object SingletonTypeTree extends SingletonTypeTreeExtractor case class SelectFromTypeTree(qualifier: Tree, name: TypeName) - extends RefTree with TypTree with SelectFromTypeTreeApi + extends RefTree with TypTree with SelectFromTypeTreeApi { + + assert(qualifier.isType, qualifier) + } object SelectFromTypeTree extends SelectFromTypeTreeExtractor case class CompoundTypeTree(templ: Template) @@ -467,6 +470,9 @@ trait Trees extends api.Trees { self: SymbolTable => case class AppliedTypeTree(tpt: Tree, args: List[Tree]) extends TypTree with AppliedTypeTreeApi { + + assert(tpt.isType, tpt) + override def symbol: Symbol = tpt.symbol override def symbol_=(sym: Symbol) { tpt.symbol = sym } } @@ -482,6 +488,10 @@ trait Trees extends api.Trees { self: SymbolTable => case class TypeTree() extends TypTree with TypeTreeContextApi { private var orig: Tree = null + /** Was this type tree originally empty? That is, does it now contain + * an inferred type that must be forgotten in `resetAttrs` to + * enable retyping. + */ private[scala] var wasEmpty: Boolean = false override def symbol = typeTreeSymbol(this) // if (tpe == null) null else tpe.typeSymbol @@ -502,6 +512,15 @@ trait Trees extends api.Trees { self: SymbolTable => wasEmpty = isEmpty setType(tp) } + + override private[scala] def copyAttrs(tree: Tree) = { + super.copyAttrs(tree) + tree match { + case other: TypeTree => wasEmpty = other.wasEmpty // SI-6648 Critical for correct operation of `resetAttrs`. + case _ => + } + this + } } object TypeTree extends TypeTreeExtractor @@ -573,6 +592,7 @@ trait Trees extends api.Trees { self: SymbolTable => case _: ApplyToImplicitArgs => new ApplyToImplicitArgs(fun, args) case _: ApplyImplicitView => new ApplyImplicitView(fun, args) // TODO: ApplyConstructor ??? + case self.pendingSuperCall => self.pendingSuperCall case _ => new Apply(fun, args) }).copyAttrs(tree) def ApplyDynamic(tree: Tree, qual: Tree, args: List[Tree]) = @@ -935,12 +955,23 @@ trait Trees extends api.Trees { self: SymbolTable => def ValDef(sym: Symbol): ValDef = ValDef(sym, EmptyTree) - object emptyValDef extends ValDef(Modifiers(PRIVATE), nme.WILDCARD, TypeTree(NoType), EmptyTree) { - override def isEmpty = true + trait CannotHaveAttrs extends Tree { + override def canHaveAttrs = false + + private def unsupported(what: String, args: Any*) = + throw new UnsupportedOperationException(s"$what($args) inapplicable for "+self.toString) + super.setPos(NoPosition) - override def setPos(pos: Position) = { assert(false); this } + override def setPos(pos: Position) = unsupported("setPos", pos) + + super.setType(NoType) + override def tpe_=(t: Type) = if (t != NoType) unsupported("tpe_=", t) } + case object EmptyTree extends TermTree with CannotHaveAttrs { override def isEmpty = true; val asList = List(this) } + object emptyValDef extends ValDef(Modifiers(PRIVATE), nme.WILDCARD, TypeTree(NoType), EmptyTree) with CannotHaveAttrs + object pendingSuperCall extends Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List()) with CannotHaveAttrs + def DefDef(sym: Symbol, mods: Modifiers, vparamss: List[List[ValDef]], rhs: Tree): DefDef = atPos(sym.pos) { assert(sym != NoSymbol) @@ -1008,6 +1039,9 @@ trait Trees extends api.Trees { self: SymbolTable => def New(tpe: Type, args: Tree*): Tree = ApplyConstructor(TypeTree(tpe), args.toList) + def New(tpe: Type, argss: List[List[Tree]]): Tree = + New(TypeTree(tpe), argss) + def New(sym: Symbol, args: Tree*): Tree = New(sym.tpe, args: _*) @@ -1088,7 +1122,7 @@ trait Trees extends api.Trees { self: SymbolTable => traverse(annot); traverse(arg) case Template(parents, self, body) => traverseTrees(parents) - if (!self.isEmpty) traverse(self) + if (self ne emptyValDef) traverse(self) traverseStats(body, tree.symbol) case Block(stats, expr) => traverseTrees(stats); traverse(expr) @@ -1301,7 +1335,7 @@ trait Trees extends api.Trees { self: SymbolTable => class ChangeOwnerTraverser(val oldowner: Symbol, val newowner: Symbol) extends Traverser { final def change(sym: Symbol) = { - if (sym != NoSymbol && sym.owner == oldowner) + if (sym != NoSymbol && sym.owner == oldowner) sym.owner = newowner } override def traverse(tree: Tree) { diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 6df6ed4417..d82692000d 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -1398,7 +1398,12 @@ trait Types extends api.Types { self: SymbolTable => /** A class for this-types of the form <sym>.this.type */ abstract case class ThisType(sym: Symbol) extends SingletonType with ThisTypeApi { - assert(sym.isClass, sym) + if (!sym.isClass) { + // SI-6640 allow StubSymbols to reveal what's missing from the classpath before we trip the assertion. + sym.failIfStub() + abort(s"ThisType($sym) for sym which is not a class") + } + //assert(sym.isClass && !sym.isModuleClass || sym.isRoot, sym) override def isTrivial: Boolean = sym.isPackageClass override def isNotNull = true @@ -7062,7 +7067,7 @@ trait Types extends api.Types { self: SymbolTable => case ExistentialType(tparams, quantified) :: rest => mergePrefixAndArgs(quantified :: rest, variance, depth) map (existentialAbstraction(tparams, _)) case _ => - assert(false, tps); None + abort(s"mergePrefixAndArgs($tps, $variance, $depth): unsupported tps") } def addMember(thistp: Type, tp: Type, sym: Symbol): Unit = addMember(thistp, tp, sym, AnyDepth) diff --git a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala index 43b982a8a4..603fff4f1c 100644 --- a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala +++ b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala @@ -20,7 +20,7 @@ import scala.annotation.switch /** @author Martin Odersky * @version 1.0 */ -abstract class UnPickler /*extends scala.reflect.generic.UnPickler*/ { +abstract class UnPickler { val global: SymbolTable import global._ @@ -233,7 +233,12 @@ abstract class UnPickler /*extends scala.reflect.generic.UnPickler*/ { // (4) Call the mirror's "missing" hook. adjust(mirrorThatLoaded(owner).missingHook(owner, name)) orElse { // (5) Create a stub symbol to defer hard failure a little longer. - owner.newStubSymbol(name) + val missingMessage = + s"""|bad symbolic reference. A signature in $filename refers to ${name.longString} + |in ${owner.kindString} ${owner.fullName} which is not available. + |It may be completely missing from the current classpath, or the version on + |the classpath might be incompatible with the version used when compiling $filename.""".stripMargin + owner.newStubSymbol(name, missingMessage) } } } @@ -304,7 +309,7 @@ abstract class UnPickler /*extends scala.reflect.generic.UnPickler*/ { if (isModuleRoot) moduleRoot setFlag pflags else owner.newLinkedModule(clazz, pflags) case VALsym => - if (isModuleRoot) { assert(false); NoSymbol } + if (isModuleRoot) { abort(s"VALsym at module root: owner = $owner, name = $name") } else owner.newTermSymbol(name.toTermName, NoPosition, pflags) case _ => @@ -827,11 +832,6 @@ abstract class UnPickler /*extends scala.reflect.generic.UnPickler*/ { protected def errorBadSignature(msg: String) = throw new RuntimeException("malformed Scala signature of " + classRoot.name + " at " + readIndex + "; " + msg) - protected def errorMissingRequirement(name: Name, owner: Symbol): Symbol = - mirrorThatLoaded(owner).missingHook(owner, name) orElse MissingRequirementError.signal( - s"bad reference while unpickling $filename: ${name.longString} not found in ${owner.tpe.widen}" - ) - def inferMethodAlternative(fun: Tree, argtpes: List[Type], restpe: Type) {} // can't do it; need a compiler for that. def newLazyTypeRef(i: Int): LazyType = new LazyTypeRef(i) diff --git a/src/reflect/scala/reflect/internal/transform/UnCurry.scala b/src/reflect/scala/reflect/internal/transform/UnCurry.scala index 0c1640ceb9..6dc6a0f7b8 100644 --- a/src/reflect/scala/reflect/internal/transform/UnCurry.scala +++ b/src/reflect/scala/reflect/internal/transform/UnCurry.scala @@ -19,8 +19,7 @@ trait UnCurry { case MethodType(params, MethodType(params1, restpe)) => apply(MethodType(params ::: params1, restpe)) case MethodType(params, ExistentialType(tparams, restpe @ MethodType(_, _))) => - assert(false, "unexpected curried method types with intervening existential") - tp0 + abort("unexpected curried method types with intervening existential") case MethodType(h :: t, restpe) if h.isImplicit => apply(MethodType(h.cloneSymbol.resetFlag(IMPLICIT) :: t, restpe)) case NullaryMethodType(restpe) => diff --git a/src/reflect/scala/reflect/internal/util/Position.scala b/src/reflect/scala/reflect/internal/util/Position.scala index 0725e9775b..3d10d4c9ce 100644 --- a/src/reflect/scala/reflect/internal/util/Position.scala +++ b/src/reflect/scala/reflect/internal/util/Position.scala @@ -7,6 +7,7 @@ package scala.reflect.internal.util import scala.reflect.ClassTag +import scala.reflect.internal.FatalError import scala.reflect.macros.Attachments object Position { @@ -269,7 +270,7 @@ class OffsetPosition(override val source: SourceFile, override val point: Int) e /** new for position ranges */ class RangePosition(source: SourceFile, override val start: Int, point: Int, override val end: Int) extends OffsetPosition(source, point) { - if (start > end) assert(false, "bad position: "+show) + if (start > end) sys.error("bad position: "+show) override def isRange: Boolean = true override def isOpaqueRange: Boolean = true override def startOrPoint: Int = start diff --git a/src/reflect/scala/reflect/internal/util/StripMarginInterpolator.scala b/src/reflect/scala/reflect/internal/util/StripMarginInterpolator.scala new file mode 100644 index 0000000000..e7579229b2 --- /dev/null +++ b/src/reflect/scala/reflect/internal/util/StripMarginInterpolator.scala @@ -0,0 +1,40 @@ +package scala.reflect +package internal +package util + +trait StripMarginInterpolator { + def stringContext: StringContext + + /** + * A safe combination of `[[scala.collection.immutable.StringLike#stripMargin]] + * and [[scala.StringContext#raw]]. + * + * The margin of each line is defined by whitespace leading up to a '|' character. + * This margin is stripped '''before''' the arguments are interpolated into to string. + * + * String escape sequences are '''not''' processed; this interpolater is designed to + * be used with triple quoted Strings. + * + * {{{ + * scala> val foo = "f|o|o" + * foo: String = f|o|o + * scala> sm"""|${foo} + * |""" + * res0: String = + * "f|o|o + * " + * }}} + */ + final def sm(args: Any*): String = { + def isLineBreak(c: Char) = c == '\n' || c == '\f' // compatible with StringLike#isLineBreak + def stripTrailingPart(s: String) = { + val (pre, post) = s.span(c => !isLineBreak(c)) + pre + post.stripMargin + } + val stripped: List[String] = stringContext.parts.toList match { + case head :: tail => head.stripMargin :: (tail map stripTrailingPart) + case Nil => Nil + } + new StringContext(stripped: _*).raw(args: _*) + } +} diff --git a/src/reflect/scala/reflect/internal/util/package.scala b/src/reflect/scala/reflect/internal/util/package.scala new file mode 100644 index 0000000000..6d77235db6 --- /dev/null +++ b/src/reflect/scala/reflect/internal/util/package.scala @@ -0,0 +1,9 @@ +package scala.reflect +package internal + +package object util { + /** + * Adds the `sm` String interpolator to a [[scala.StringContext]]. + */ + implicit class StringContextStripMarginOps(val stringContext: StringContext) extends StripMarginInterpolator +} diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index 2d08cd887b..d110bd4273 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -129,11 +129,10 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni private def ErrorStaticModule(sym: Symbol) = throw new ScalaReflectionException(s"$sym is a static module, use reflectModule on a RuntimeMirror to obtain its ModuleMirror") private def ErrorNotMember(sym: Symbol, owner: Symbol) = throw new ScalaReflectionException(s"expected a member of $owner, you provided ${sym.kindString} ${sym.fullName}") private def ErrorNotField(sym: Symbol) = throw new ScalaReflectionException(s"expected a field or an accessor method symbol, you provided $sym") - private def ErrorNonExistentField(sym: Symbol) = throw new ScalaReflectionException(s""" - |Scala field ${sym.name} isn't represented as a Java field, neither it has a Java accessor method - |note that private parameters of class constructors don't get mapped onto fields and/or accessors, - |unless they are used outside of their declaring constructors. - """.trim.stripMargin) + private def ErrorNonExistentField(sym: Symbol) = throw new ScalaReflectionException( + sm"""Scala field ${sym.name} isn't represented as a Java field, neither it has a Java accessor method + |note that private parameters of class constructors don't get mapped onto fields and/or accessors, + |unless they are used outside of their declaring constructors.""") private def ErrorSetImmutableField(sym: Symbol) = throw new ScalaReflectionException(s"cannot set an immutable field ${sym.name}") private def ErrorNotConstructor(sym: Symbol, owner: Symbol) = throw new ScalaReflectionException(s"expected a constructor of $owner, you provided $sym") private def ErrorFree(member: Symbol, freeType: Symbol) = throw new ScalaReflectionException(s"cannot reflect ${member.kindString} ${member.name}, because it's a member of a weak type ${freeType.name}") @@ -417,7 +416,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni case sym if sym.owner.isPrimitiveValueClass => invokePrimitiveMethod case sym if sym == Predef_classOf => fail("Predef.classOf is a compile-time function") case sym if sym.isTermMacro => fail(s"${symbol.fullName} is a macro, i.e. a compile-time function") - case _ => assert(false, this) + case _ => abort(s"unsupported symbol $symbol when invoking $this") } } } @@ -541,8 +540,8 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni val result = anns find (_.annotationType == annotClass) if (result.isEmpty && (anns exists (_.annotationType.getName == name))) throw new ClassNotFoundException( - s"""Mirror classloader mismatch: $jclazz (loaded by ${ReflectionUtils.show(jclazz.getClassLoader)}) - |is unrelated to the mirror's classloader: (${ReflectionUtils.show(classLoader)})""".stripMargin) + sm"""Mirror classloader mismatch: $jclazz (loaded by ${ReflectionUtils.show(jclazz.getClassLoader)}) + |is unrelated to the mirror's classloader: (${ReflectionUtils.show(classLoader)})""") result } def loadBytes[T: ClassTag](name: String): Option[T] = @@ -955,8 +954,8 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni javaTypeToValueClass(jclazz) orElse lookupClass assert (cls.isType, - s"""${if (cls == NoSymbol) "not a type: symbol" else "no symbol could be"} - | loaded from $jclazz in $owner with name $simpleName and classloader $classLoader""".stripMargin) + sm"""${if (cls == NoSymbol) "not a type: symbol" else "no symbol could be"} + | loaded from $jclazz in $owner with name $simpleName and classloader $classLoader""") cls.asClass } diff --git a/test/files/jvm/serialization.scala b/test/files/jvm/serialization.scala index 34b64938b4..f2c47aad77 100644 --- a/test/files/jvm/serialization.scala +++ b/test/files/jvm/serialization.scala @@ -604,6 +604,7 @@ object Test { Test7 Test8 Test9_parallel + Test10_util } } @@ -669,3 +670,17 @@ object Test9_parallel { throw e } } + +//############################################################################ +// Test classes in package scala.util + +object Test10_util { + import scala.util.Random + def rep[A](n: Int)(f: => A) { if (n > 0) { f; rep(n-1)(f) } } + + try { + val random = new Random(345) + val random2: Random = read(write(random)) + rep(5) { assert(random.nextInt == random2.nextInt) } + } +} diff --git a/test/files/neg/anyval-anyref-parent.check b/test/files/neg/anyval-anyref-parent.check index fe20e5de81..8c2aa36583 100644 --- a/test/files/neg/anyval-anyref-parent.check +++ b/test/files/neg/anyval-anyref-parent.check @@ -3,7 +3,7 @@ trait Foo2 extends AnyVal // fail ^ anyval-anyref-parent.scala:5: error: Any does not have a constructor class Bar1 extends Any // fail - ^ + ^ anyval-anyref-parent.scala:6: error: value class needs to have exactly one public val parameter class Bar2(x: Int) extends AnyVal // fail ^ diff --git a/test/files/neg/case-collision.check b/test/files/neg/case-collision.check new file mode 100644 index 0000000000..4edc6f1205 --- /dev/null +++ b/test/files/neg/case-collision.check @@ -0,0 +1,10 @@ +case-collision.scala:5: error: Class foo.BIPPY differs only in case from foo.Bippy. Such classes will overwrite one another on case-insensitive filesystems. +class BIPPY + ^ +case-collision.scala:11: error: Class foo.HyRaX$ differs only in case from foo.Hyrax$. Such classes will overwrite one another on case-insensitive filesystems. +object HyRaX + ^ +case-collision.scala:8: error: Class foo.DINGO$ differs only in case from foo.Dingo$. Such classes will overwrite one another on case-insensitive filesystems. +object DINGO + ^ +three errors found diff --git a/test/files/neg/case-collision.flags b/test/files/neg/case-collision.flags new file mode 100644 index 0000000000..85d8eb2ba2 --- /dev/null +++ b/test/files/neg/case-collision.flags @@ -0,0 +1 @@ +-Xfatal-warnings diff --git a/test/files/neg/case-collision.scala b/test/files/neg/case-collision.scala new file mode 100644 index 0000000000..241169a77a --- /dev/null +++ b/test/files/neg/case-collision.scala @@ -0,0 +1,11 @@ +package foo + +class Bippy + +class BIPPY + +object Dingo +object DINGO + +case class Hyrax() +object HyRaX diff --git a/test/files/neg/cyclics-import.check b/test/files/neg/cyclics-import.check index ef355fab0a..be09fca374 100644 --- a/test/files/neg/cyclics-import.check +++ b/test/files/neg/cyclics-import.check @@ -3,13 +3,4 @@ Note: this is often due in part to a class depending on a definition nested with If applicable, you may wish to try moving some members into another object. import User.UserStatus._ ^ -cyclics-import.scala:12: error: not found: type Value - type UserStatus = Value - ^ -cyclics-import.scala:14: error: not found: value Value - val Active = Value("1") - ^ -cyclics-import.scala:15: error: not found: value Value - val Disabled = Value("2") - ^ -four errors found +one error found diff --git a/test/files/neg/gadts1.check b/test/files/neg/gadts1.check index 44d2b114d6..a5e3e0de10 100644 --- a/test/files/neg/gadts1.check +++ b/test/files/neg/gadts1.check @@ -3,9 +3,9 @@ gadts1.scala:15: error: type mismatch; required: a case NumTerm(n) => c.x = Double(1.0) ^ -gadts1.scala:20: error: class Cell of type Test.Cell does not take type parameters. +gadts1.scala:20: error: Test.Cell[a] does not take parameters case Cell[a](x: Int) => c.x = 5 - ^ + ^ gadts1.scala:20: error: type mismatch; found : Int(5) required: a diff --git a/test/files/neg/macro-invalidsig-implicit-params/Impls_Macros_1.scala b/test/files/neg/macro-invalidsig-implicit-params/Impls_Macros_1.scala index 845a168ff2..7a7293422e 100644 --- a/test/files/neg/macro-invalidsig-implicit-params/Impls_Macros_1.scala +++ b/test/files/neg/macro-invalidsig-implicit-params/Impls_Macros_1.scala @@ -5,10 +5,10 @@ object Impls { def foo_targs[T, U: c.WeakTypeTag](c: Ctx)(implicit x: c.Expr[Int]) = { import c.{prefix => prefix} import c.universe._ - val body = Block( + val body = Block(List( Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("invoking foo_targs...")))), Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("type of prefix is: " + prefix.staticType)))), - Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("U is: " + implicitly[c.WeakTypeTag[U]].tpe)))), + Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("U is: " + implicitly[c.WeakTypeTag[U]].tpe))))), Literal(Constant(()))) c.Expr[Unit](body) } diff --git a/test/files/neg/names-defaults-neg.check b/test/files/neg/names-defaults-neg.check index f3c45a6aa0..6f9dc7d127 100644 --- a/test/files/neg/names-defaults-neg.check +++ b/test/files/neg/names-defaults-neg.check @@ -100,7 +100,7 @@ Error occurred in an application involving default arguments. ^ names-defaults-neg.scala:86: error: module extending its companion class cannot use default constructor arguments object C extends C() - ^ + ^ names-defaults-neg.scala:90: error: deprecated parameter name x has to be distinct from any other parameter name (deprecated or not). def deprNam1(x: Int, @deprecatedName('x) y: String) = 0 ^ diff --git a/test/files/neg/protected-constructors.check b/test/files/neg/protected-constructors.check index f137158ed6..e295917050 100644 --- a/test/files/neg/protected-constructors.check +++ b/test/files/neg/protected-constructors.check @@ -19,7 +19,4 @@ protected-constructors.scala:15: error: class Foo3 in object Ding cannot be acce object Ding in package dingus where target is defined class Bar3 extends Ding.Foo3("abc") ^ -protected-constructors.scala:15: error: too many arguments for constructor Object: ()Object - class Bar3 extends Ding.Foo3("abc") - ^ -5 errors found +four errors found diff --git a/test/files/neg/t1672b.check b/test/files/neg/t1672b.check new file mode 100644 index 0000000000..60ccf77174 --- /dev/null +++ b/test/files/neg/t1672b.check @@ -0,0 +1,16 @@ +t1672b.scala:3: error: could not optimize @tailrec annotated method bar: it contains a recursive call not in tail position + def bar : Nothing = { + ^ +t1672b.scala:14: error: could not optimize @tailrec annotated method baz: it contains a recursive call not in tail position + def baz : Nothing = { + ^ +t1672b.scala:29: error: could not optimize @tailrec annotated method boz: it contains a recursive call not in tail position + case _: Throwable => boz; ??? + ^ +t1672b.scala:34: error: could not optimize @tailrec annotated method bez: it contains a recursive call not in tail position + def bez : Nothing = { + ^ +t1672b.scala:46: error: could not optimize @tailrec annotated method bar: it contains a recursive call not in tail position + else 1 + (try { + ^ +5 errors found diff --git a/test/files/neg/t1672b.scala b/test/files/neg/t1672b.scala new file mode 100644 index 0000000000..0ccdd03633 --- /dev/null +++ b/test/files/neg/t1672b.scala @@ -0,0 +1,52 @@ +object Test { + @annotation.tailrec + def bar : Nothing = { + try { + throw new RuntimeException + } catch { + case _: Throwable => bar + } finally { + bar + } + } + + @annotation.tailrec + def baz : Nothing = { + try { + throw new RuntimeException + } catch { + case _: Throwable => baz + } finally { + ??? + } + } + + @annotation.tailrec + def boz : Nothing = { + try { + throw new RuntimeException + } catch { + case _: Throwable => boz; ??? + } + } + + @annotation.tailrec + def bez : Nothing = { + try { + bez + } finally { + ??? + } + } + + // the `liftedTree` local method will prevent a tail call here. + @annotation.tailrec + def bar(i : Int) : Int = { + if (i == 0) 0 + else 1 + (try { + throw new RuntimeException + } catch { + case _: Throwable => bar(i - 1) + }) + } +} diff --git a/test/files/neg/t2148.check b/test/files/neg/t2148.check index 5113b48e51..27b5dce507 100644 --- a/test/files/neg/t2148.check +++ b/test/files/neg/t2148.check @@ -1,4 +1,4 @@ -t2148.scala:9: error: type A is not a stable prefix +t2148.scala:9: error: A is not a legal prefix for a constructor val b = new A with A#A1 ^ one error found diff --git a/test/files/neg/t409.check b/test/files/neg/t409.check index 433d64d25d..0edc0d03cd 100644 --- a/test/files/neg/t409.check +++ b/test/files/neg/t409.check @@ -1,4 +1,4 @@ -t409.scala:6: error: traits or objects may not have parameters +t409.scala:6: error: class Case1 needs to be a trait to be mixed in class Toto extends Expr with Case1(12); - ^ + ^ one error found diff --git a/test/files/neg/t5148.check b/test/files/neg/t5148.check index 6edfdf2b1e..25107c4dbe 100644 --- a/test/files/neg/t5148.check +++ b/test/files/neg/t5148.check @@ -1,3 +1,9 @@ -error: bad symbolic reference to value global in class IMain - referenced from t5148.scala (a classfile may be missing) -error: bad symbolic reference to value memberHandlers in class IMain - referenced from t5148.scala (a classfile may be missing) +error: bad symbolic reference. A signature in Imports.class refers to term global +in class scala.tools.nsc.interpreter.IMain which is not available. +It may be completely missing from the current classpath, or the version on +the classpath might be incompatible with the version used when compiling Imports.class. +error: bad symbolic reference. A signature in Imports.class refers to term memberHandlers +in class scala.tools.nsc.interpreter.IMain which is not available. +It may be completely missing from the current classpath, or the version on +the classpath might be incompatible with the version used when compiling Imports.class. two errors found diff --git a/test/files/neg/t5529.check b/test/files/neg/t5529.check index 5d2175fa79..da3f84e1ec 100644 --- a/test/files/neg/t5529.check +++ b/test/files/neg/t5529.check @@ -4,7 +4,4 @@ t5529.scala:12: error: File is already defined as class File t5529.scala:10: error: class type required but test.Test.File found sealed class Dir extends File { } ^ -t5529.scala:10: error: test.Test.File does not have a constructor - sealed class Dir extends File { } - ^ -three errors found +two errors found diff --git a/test/files/neg/t5696.check b/test/files/neg/t5696.check index 72b7781fc4..e0fb61b839 100644 --- a/test/files/neg/t5696.check +++ b/test/files/neg/t5696.check @@ -15,5 +15,5 @@ t5696.scala:38: error: too many argument lists for constructor invocation ^ t5696.scala:46: error: too many argument lists for constructor invocation object x extends G(1)(2) {} - ^ + ^ 6 errors found diff --git a/test/files/neg/t5753.check b/test/files/neg/t5753.check new file mode 100644 index 0000000000..76602de17d --- /dev/null +++ b/test/files/neg/t5753.check @@ -0,0 +1,4 @@ +Test_2.scala:9: error: macro implementation not found: foo (the most common reason for that is that you cannot use macro implementations in the same compilation run that defines them) + println(foo(42)) + ^ +one error found diff --git a/test/files/neg/t5753.flags b/test/files/neg/t5753.flags new file mode 100644 index 0000000000..cd66464f2f --- /dev/null +++ b/test/files/neg/t5753.flags @@ -0,0 +1 @@ +-language:experimental.macros
\ No newline at end of file diff --git a/test/files/neg/t5753/Impls$class.class b/test/files/neg/t5753/Impls$class.class Binary files differnew file mode 100644 index 0000000000..476329174e --- /dev/null +++ b/test/files/neg/t5753/Impls$class.class diff --git a/test/files/neg/t5753/Impls.class b/test/files/neg/t5753/Impls.class Binary files differnew file mode 100644 index 0000000000..dfcf89ed44 --- /dev/null +++ b/test/files/neg/t5753/Impls.class diff --git a/test/files/neg/t5753/Impls_Macros_1.scala b/test/files/neg/t5753/Impls_Macros_1.scala new file mode 100644 index 0000000000..1d9c26458c --- /dev/null +++ b/test/files/neg/t5753/Impls_Macros_1.scala @@ -0,0 +1,6 @@ +import scala.reflect.macros.{Context => Ctx} + +trait Impls { +def impl(c: Ctx)(x: c.Expr[Any]) = x +} + diff --git a/test/files/neg/t5753/Test_2.scala b/test/files/neg/t5753/Test_2.scala new file mode 100644 index 0000000000..2369b18e76 --- /dev/null +++ b/test/files/neg/t5753/Test_2.scala @@ -0,0 +1,11 @@ +import scala.reflect.macros.{Context => Ctx} + +object Macros extends Impls { + def foo(x: Any) = macro impl +} + +object Test extends App { + import Macros._ + println(foo(42)) +} + diff --git a/test/files/neg/t6260.check b/test/files/neg/t6260.check index 2b7f1a8bfb..46e9bd1dfc 100644 --- a/test/files/neg/t6260.check +++ b/test/files/neg/t6260.check @@ -1,10 +1,10 @@ -t6260.scala:3: error: bridge generated for member method apply: (x$1: Box[X])Box[Y] in anonymous class $anonfun +t6260.scala:3: error: bridge generated for member method apply: (bx: Box[X])Box[Y] in anonymous class $anonfun which overrides method apply: (v1: T1)R in trait Function1 clashes with definition of the member itself; both have erased type (v1: Object)Object ((bx: Box[X]) => new Box(f(bx.x)))(this) ^ -t6260.scala:8: error: bridge generated for member method apply: (x$1: Box[X])Box[Y] in anonymous class $anonfun +t6260.scala:8: error: bridge generated for member method apply: (bx: Box[X])Box[Y] in anonymous class $anonfun which overrides method apply: (v1: T1)R in trait Function1 clashes with definition of the member itself; both have erased type (v1: Object)Object diff --git a/test/files/neg/t6357.check b/test/files/neg/t6357.check new file mode 100644 index 0000000000..a534d1439a --- /dev/null +++ b/test/files/neg/t6357.check @@ -0,0 +1,4 @@ +t6357.scala:3: error: value class may not be a local class + final class Y(val j: Int) extends AnyVal + ^ +one error found diff --git a/test/files/neg/t6357.scala b/test/files/neg/t6357.scala new file mode 100644 index 0000000000..47f5629638 --- /dev/null +++ b/test/files/neg/t6357.scala @@ -0,0 +1,6 @@ +object K { + def q = { + final class Y(val j: Int) extends AnyVal + 3 + } +} diff --git a/test/files/neg/t6535.check b/test/files/neg/t6535.check new file mode 100644 index 0000000000..1225ea70db --- /dev/null +++ b/test/files/neg/t6535.check @@ -0,0 +1,6 @@ +t6535.scala:2: error: encountered unrecoverable cycle resolving import. +Note: this is often due in part to a class depending on a definition nested within its companion. +If applicable, you may wish to try moving some members into another object. + import Bs.B._ + ^ +one error found diff --git a/test/files/neg/t6535.scala b/test/files/neg/t6535.scala new file mode 100644 index 0000000000..30a750311c --- /dev/null +++ b/test/files/neg/t6535.scala @@ -0,0 +1,15 @@ +object As { + import Bs.B._ + + object A + extends scala.AnyRef // needed for the cycle; + // replacing with a locally defined closs doesn't + // hit the locked import and hence doesn't cycle. +} + +object Bs { + import As.A._ + + object B + extends scala.AnyRef // scala.Immutable, ... +} diff --git a/test/files/neg/t6558.check b/test/files/neg/t6558.check new file mode 100644 index 0000000000..1b39ef9986 --- /dev/null +++ b/test/files/neg/t6558.check @@ -0,0 +1,10 @@ +t6558.scala:19: error: not found: type classs + @classs + ^ +t6558.scala:22: error: not found: type typeparam + class D[@typeparam T] + ^ +t6558.scala:25: error: not found: type valueparam + @valueparam x: Any + ^ +three errors found diff --git a/test/files/neg/t6558.scala b/test/files/neg/t6558.scala new file mode 100644 index 0000000000..bdc441698f --- /dev/null +++ b/test/files/neg/t6558.scala @@ -0,0 +1,27 @@ +class AnnotNotFound { + def foo(a: Any) = () + + foo { + // Not yet issued in the context of this file, see SI-6758 + // This error is issued in t6558b.scala + @inargument + def foo = 0 + foo + } + + () => { + // As per above + @infunction + def foo = 0 + () + } + + @classs + class C + + class D[@typeparam T] + + class E( + @valueparam x: Any + ) +} diff --git a/test/files/neg/t6558b.check b/test/files/neg/t6558b.check new file mode 100644 index 0000000000..cfa384fc08 --- /dev/null +++ b/test/files/neg/t6558b.check @@ -0,0 +1,7 @@ +t6558b.scala:5: error: not found: type inargument + @inargument + ^ +t6558b.scala:11: error: not found: type infunction + @infunction + ^ +two errors found diff --git a/test/files/neg/t6558b.scala b/test/files/neg/t6558b.scala new file mode 100644 index 0000000000..2aa06f69cf --- /dev/null +++ b/test/files/neg/t6558b.scala @@ -0,0 +1,15 @@ +class AnnotNotFound { + def foo(a: Any) = () + + foo { + @inargument + def foo = 0 + foo + } + + () => { + @infunction + def foo = 0 + () + } +} diff --git a/test/files/neg/t6667.check b/test/files/neg/t6667.check new file mode 100644 index 0000000000..43313fa4fe --- /dev/null +++ b/test/files/neg/t6667.check @@ -0,0 +1,13 @@ +t6667.scala:8: error: ambiguous implicit values: + both value inScope1 in object Test of type => C + and value inScope2 in object Test of type => C + match expected type C + implicitly[C]: Unit // C.companion was used; whereas the ambiguity should abort the implicit search. + ^ +t6667.scala:9: error: ambiguous implicit values: + both value inScope1 in object Test of type => C + and value inScope2 in object Test of type => C + match expected type C + implicitly[C] // ambiguity reported, rather than falling back to C.companion + ^ +two errors found diff --git a/test/files/neg/t6667.scala b/test/files/neg/t6667.scala new file mode 100644 index 0000000000..fb857ebd33 --- /dev/null +++ b/test/files/neg/t6667.scala @@ -0,0 +1,10 @@ +class C +object C { + implicit def companion = new C +} + +object Test { + implicit val inScope1, inScope2 = new C + implicitly[C]: Unit // C.companion was used; whereas the ambiguity should abort the implicit search. + implicitly[C] // ambiguity reported, rather than falling back to C.companion +} diff --git a/test/files/neg/t6667b.check b/test/files/neg/t6667b.check new file mode 100644 index 0000000000..99cea9a47c --- /dev/null +++ b/test/files/neg/t6667b.check @@ -0,0 +1,13 @@ +t6667b.scala:16: error: ambiguous implicit values: + both value a in object Test of type => Test.Box + and value b of type Test.Box + match expected type Test.Box + new Test() + ^ +t6667b.scala:19: error: ambiguous implicit values: + both value a in object Test of type => Test.Box + and value b of type Test.Box + match expected type Test.Box + new Test() + ^ +two errors found diff --git a/test/files/neg/t6667b.scala b/test/files/neg/t6667b.scala new file mode 100644 index 0000000000..4e64e1af17 --- /dev/null +++ b/test/files/neg/t6667b.scala @@ -0,0 +1,25 @@ +object Test { + abstract class Box { + val value: Int + } + + implicit val a: Box = new Box { + val value= 1 + } + + def main(args: Array[String]) { + implicit val b: Box= new Box { + val value= 2 + } + + new Object { + new Test() + } + // compare with: + new Test() + } +} + +class Test()(implicit x: Test.Box) { + println(x.value) +} diff --git a/test/files/neg/t667.check b/test/files/neg/t667.check index d4367bc87b..e68c6dea00 100644 --- a/test/files/neg/t667.check +++ b/test/files/neg/t667.check @@ -1,4 +1,4 @@ -t667.scala:8: error: class Ni inherits itself +t667.scala:8: error: illegal cyclic reference involving class Ni class Ni extends super.Ni with Ni; - ^ + ^ one error found diff --git a/test/files/neg/t877.check b/test/files/neg/t877.check index 5f25bd439c..c3d4ab6584 100644 --- a/test/files/neg/t877.check +++ b/test/files/neg/t877.check @@ -1,7 +1,7 @@ t877.scala:3: error: Invalid literal number trait Foo extends A(22A, Bug!) {} ^ -t877.scala:3: error: parents of traits may not have parameters +t877.scala:3: error: ')' expected but eof found. trait Foo extends A(22A, Bug!) {} - ^ + ^ two errors found diff --git a/test/files/pos/t1672.scala b/test/files/pos/t1672.scala new file mode 100644 index 0000000000..5ee6bb1759 --- /dev/null +++ b/test/files/pos/t1672.scala @@ -0,0 +1,10 @@ +object Test { + @annotation.tailrec + def bar : Nothing = { + try { + throw new RuntimeException + } catch { + case _: Throwable => bar + } + } +} diff --git a/test/files/pos/t5726.scala b/test/files/pos/t5726.scala new file mode 100644 index 0000000000..b28ebd8674 --- /dev/null +++ b/test/files/pos/t5726.scala @@ -0,0 +1,17 @@ +import scala.language.dynamics + +class DynamicTest extends Dynamic { + def selectDynamic(name: String) = s"value of $name" + def updateDynamic(name: String)(value: Any) { + println(s"You have just updated property '$name' with value: $value") + } +} + +object MyApp extends App { + def testing() { + val test = new DynamicTest + test.firstName = "John" + } + + testing() +} diff --git a/test/files/pos/t5877.scala b/test/files/pos/t5877.scala new file mode 100644 index 0000000000..c7827df99f --- /dev/null +++ b/test/files/pos/t5877.scala @@ -0,0 +1,14 @@ +package foo { + class Foo + + object Test { + new Foo().huzzah + } +} + +package object foo { + // Crasher: No synthetics for method PimpedFoo2: synthetics contains + implicit class PimpedFoo2(value: Foo) { + def huzzah = "" + } +} diff --git a/test/files/pos/t5877b.scala b/test/files/pos/t5877b.scala new file mode 100644 index 0000000000..6b8cbd473e --- /dev/null +++ b/test/files/pos/t5877b.scala @@ -0,0 +1,13 @@ +package foo + +class Foo + +object Test { + new Foo().huzzah +} + +object `package` { + implicit class PimpedFoo2(value: Foo) { + def huzzah = "" + } +} diff --git a/test/files/pos/t6547.flags b/test/files/pos/t6547.flags new file mode 100644 index 0000000000..c9b68d70dc --- /dev/null +++ b/test/files/pos/t6547.flags @@ -0,0 +1 @@ +-optimise diff --git a/test/files/pos/t6547.scala b/test/files/pos/t6547.scala new file mode 100644 index 0000000000..53bd798219 --- /dev/null +++ b/test/files/pos/t6547.scala @@ -0,0 +1,6 @@ +trait ConfigurableDefault[@specialized V] { + def fillArray(arr: Array[V], v: V) = (arr: Any) match { + case x: Array[Int] => null + case x: Array[Long] => v.asInstanceOf[Long] + } +} diff --git a/test/files/pos/t6551.scala b/test/files/pos/t6551.scala index fb68663809..8bb396a19f 100644 --- a/test/files/pos/t6551.scala +++ b/test/files/pos/t6551.scala @@ -1,4 +1,4 @@ -import language.dynamics +import scala.language.dynamics object Test { def main(args: Array[String]) { diff --git a/test/files/pos/t6624.scala b/test/files/pos/t6624.scala new file mode 100644 index 0000000000..1a92b92d53 --- /dev/null +++ b/test/files/pos/t6624.scala @@ -0,0 +1,28 @@ +sealed trait KList[+M[_]] + +case class KCons[M[_], +T <: KList[M]]( + tail: T +) extends KList[M] + +case class KNil[M[_]]() extends KList[M] + +object Test { + val klist: KCons[Option, KCons[Option, KCons[Option, KNil[Nothing]]]] = ??? + + // crashes with + // "Exception in thread "main" scala.reflect.internal.Types$TypeError: value _1 is not a member + // of KCons[Option,KCons[Option,KNil[Nothing]]]" + klist match { + case KCons(KCons(KCons(_))) => + } + + // fails with a similar message as an error, rather than a crash. + klist match { + case KCons(KCons(_)) => + } + + // succeeds + klist match { + case KCons(_) => + } +}
\ No newline at end of file diff --git a/test/files/pos/t6648.scala b/test/files/pos/t6648.scala new file mode 100644 index 0000000000..9593ebfee9 --- /dev/null +++ b/test/files/pos/t6648.scala @@ -0,0 +1,24 @@ +abstract class Node extends NodeSeq +trait NodeSeq extends Seq[Node] +object NodeSeq { + implicit def seqToNodeSeq(ns: Seq[Node]): NodeSeq = ??? + def foo[B, That](f: Seq[B])(implicit bf: scala.collection.generic.CanBuildFrom[Seq[Int], B, That]): That = ??? +} + +class Transformer { + def apply(nodes: Any): Any = ??? +} + +object transformer1 extends Transformer { + // Adding explicit type arguments, or making the impilcit view + // seqToNodeSeq explicit avoids the crash + NodeSeq.foo { + // These both avoid the crash: + // val t = new Transformer {}; t.apply(null) + // new Transformer().apply(null) + new Transformer {}.apply(null) + + null: NodeSeq + }: NodeSeq +} + diff --git a/test/files/pos/t6712.scala b/test/files/pos/t6712.scala new file mode 100644 index 0000000000..3c96eb14fb --- /dev/null +++ b/test/files/pos/t6712.scala @@ -0,0 +1,5 @@ +class H { + object O + + def foo() { object O } +} diff --git a/test/files/pos/t6722.scala b/test/files/pos/t6722.scala new file mode 100644 index 0000000000..576746c915 --- /dev/null +++ b/test/files/pos/t6722.scala @@ -0,0 +1,11 @@ +import scala.language.dynamics + +class Dyn extends Dynamic { + def selectDynamic(s: String): Dyn = new Dyn + def get[T]: T = null.asInstanceOf[T] +} + +object Foo { + val dyn = new Dyn + dyn.foo.bar.baz.get[String] +} diff --git a/test/files/run/idempotency-case-classes.check b/test/files/run/idempotency-case-classes.check new file mode 100644 index 0000000000..d2fb8169cb --- /dev/null +++ b/test/files/run/idempotency-case-classes.check @@ -0,0 +1,52 @@ +C(2,3) +() +{ + case class C extends AnyRef with Product with Serializable { + <caseaccessor> <paramaccessor> private[this] val x: Int = _; + <stable> <caseaccessor> <accessor> <paramaccessor> def x: Int = C.this.x; + <caseaccessor> <paramaccessor> private[this] val y: Int = _; + <stable> <caseaccessor> <accessor> <paramaccessor> def y: Int = C.this.y; + def <init>(x: Int, y: Int): C = { + C.super.<init>(); + () + }; + <synthetic> def copy(x: Int = x, y: Int = y): C = new C(x, y); + <synthetic> def copy$default$1: Int = C.this.x; + <synthetic> def copy$default$2: Int = C.this.y; + override <synthetic> def productPrefix: String = "C"; + <synthetic> def productArity: Int = 2; + <synthetic> def productElement(x$1: Int): Any = x$1 match { + case 0 => C.this.x + case 1 => C.this.y + case _ => throw new IndexOutOfBoundsException(x$1.toString()) + }; + override <synthetic> def productIterator: Iterator[Any] = runtime.this.ScalaRunTime.typedProductIterator[Any](C.this); + <synthetic> def canEqual(x$1: Any): Boolean = x$1.$isInstanceOf[C](); + override <synthetic> def hashCode(): Int = { + <synthetic> var acc: Int = -889275714; + acc = Statics.this.mix(acc, x); + acc = Statics.this.mix(acc, y); + Statics.this.finalizeHash(acc, 2) + }; + override <synthetic> def toString(): String = ScalaRunTime.this._toString(C.this); + override <synthetic> def equals(x$1: Any): Boolean = C.this.eq(x$1.asInstanceOf[Object]).||(x$1.isInstanceOf[C].&&({ + <synthetic> val C$1: C = x$1.asInstanceOf[C]; + C.this.x.==(C$1.x).&&(C.this.y.==(C$1.y)).&&(C$1.canEqual(C.this)) + })) + }; + <synthetic> object C extends scala.runtime.AbstractFunction2[Int,Int,C] with Serializable { + def <init>(): C.type = { + C.super.<init>(); + () + }; + final override def toString(): String = "C"; + case <synthetic> def apply(x: Int, y: Int): C = new C(x, y); + case <synthetic> def unapply(x$0: C): Option[(Int, Int)] = if (x$0.==(null)) + scala.this.None + else + Some.apply[(Int, Int)](Tuple2.apply[Int, Int](x$0.x, x$0.y)); + <synthetic> private def readResolve(): Object = C + }; + scala.this.Predef.println(C.apply(2, 3)) +} +error! diff --git a/test/files/run/idempotency-case-classes.scala b/test/files/run/idempotency-case-classes.scala new file mode 100644 index 0000000000..4da8393cb6 --- /dev/null +++ b/test/files/run/idempotency-case-classes.scala @@ -0,0 +1,22 @@ +import scala.reflect.runtime.universe._ +import scala.reflect.runtime.{currentMirror => cm} +import scala.tools.reflect.{ToolBox, ToolBoxError} +import scala.tools.reflect.Eval + +object Test extends App { + val casee = reify { + case class C(x: Int, y: Int) + println(C(2, 3)) + } + println(casee.eval) + val tb = cm.mkToolBox() + val tcasee = tb.typeCheck(casee.tree) + println(tcasee) + val rtcasee = tb.resetAllAttrs(tcasee) + try { + println(tb.eval(rtcasee)) + } catch { + // this is the current behaviour, rather than the desired behavior; see SI-5467 + case _: ToolBoxError => println("error!") + } +}
\ No newline at end of file diff --git a/test/files/run/idempotency-extractors.check b/test/files/run/idempotency-extractors.check new file mode 100644 index 0000000000..fcd50faa79 --- /dev/null +++ b/test/files/run/idempotency-extractors.check @@ -0,0 +1,5 @@ +2 +2 match { + case Test.this.Extractor.unapply(<unapply-selector>) <unapply> ((x @ _)) => x +} +error! diff --git a/test/files/run/idempotency-extractors.scala b/test/files/run/idempotency-extractors.scala new file mode 100644 index 0000000000..fe033295f5 --- /dev/null +++ b/test/files/run/idempotency-extractors.scala @@ -0,0 +1,22 @@ +import scala.reflect.runtime.universe._ +import scala.reflect.runtime.{currentMirror => cm} +import scala.tools.reflect.{ToolBox, ToolBoxError} +import scala.tools.reflect.Eval + +object Test extends App { + object Extractor { def unapply(x: Int): Option[Int] = Some(x) } + val extractor = reify { + 2 match { case Extractor(x) => x } + } + println(extractor.eval) + val tb = cm.mkToolBox() + val textractor = tb.typeCheck(extractor.tree) + println(textractor) + val rtextractor = tb.resetAllAttrs(textractor) + try { + println(tb.eval(rtextractor)) + } catch { + // this is the current behaviour, rather than the desired behavior; see SI-5465 + case _: ToolBoxError => println("error!") + } +}
\ No newline at end of file diff --git a/test/files/run/idempotency-labels.check b/test/files/run/idempotency-labels.check new file mode 100644 index 0000000000..8709efeb43 --- /dev/null +++ b/test/files/run/idempotency-labels.check @@ -0,0 +1,15 @@ +2 +{ + var x: Int = 0; + while$1(){ + if (x.<(2)) + { + x = x.+(1); + while$1() + } + else + () + }; + x +} +2 diff --git a/test/files/run/idempotency-labels.scala b/test/files/run/idempotency-labels.scala new file mode 100644 index 0000000000..82d009751a --- /dev/null +++ b/test/files/run/idempotency-labels.scala @@ -0,0 +1,22 @@ +import scala.reflect.runtime.universe._ +import scala.reflect.runtime.{currentMirror => cm} +import scala.tools.reflect.{ToolBox, ToolBoxError} +import scala.tools.reflect.Eval + +object Test extends App { + val label = reify { + var x = 0 + while (x < 2) { x += 1 } + x + } + println(label.eval) + val tb = cm.mkToolBox() + val tlabel = tb.typeCheck(label.tree) + println(tlabel) + val rtlabel = tb.resetAllAttrs(tlabel) + try { + println(tb.eval(rtlabel)) + } catch { + case _: ToolBoxError => println("error!") + } +}
\ No newline at end of file diff --git a/test/files/run/idempotency-lazy-vals.check b/test/files/run/idempotency-lazy-vals.check new file mode 100644 index 0000000000..4dcbf96184 --- /dev/null +++ b/test/files/run/idempotency-lazy-vals.check @@ -0,0 +1,23 @@ +6 +{ + class C extends AnyRef { + def <init>(): C = { + C.super.<init>(); + () + }; + lazy private[this] val x: Int = _; + <stable> <accessor> lazy def x: Int = { + C.this.x = 2; + C.this.x + }; + lazy private[this] val y: Int = _; + implicit <stable> <accessor> lazy def y: Int = { + C.this.y = 3; + C.this.y + } + }; + val c: C = new C(); + import c._; + c.x.*(scala.this.Predef.implicitly[Int](c.y)) +} +error! diff --git a/test/files/run/idempotency-lazy-vals.scala b/test/files/run/idempotency-lazy-vals.scala new file mode 100644 index 0000000000..3531f9ff4b --- /dev/null +++ b/test/files/run/idempotency-lazy-vals.scala @@ -0,0 +1,27 @@ +import scala.reflect.runtime.universe._ +import scala.reflect.runtime.{currentMirror => cm} +import scala.tools.reflect.{ToolBox, ToolBoxError} +import scala.tools.reflect.Eval + +object Test extends App { + val lazee = reify { + class C { + lazy val x = 2 + implicit lazy val y = 3 + } + val c = new C() + import c._ + x * implicitly[Int] + } + println(lazee.eval) + val tb = cm.mkToolBox() + val tlazee = tb.typeCheck(lazee.tree) + println(tlazee) + val rtlazee = tb.resetAllAttrs(tlazee) + try { + println(tb.eval(rtlazee)) + } catch { + // this is the current behaviour, rather than the desired behavior; see SI-5466 + case _: ToolBoxError => println("error!") + } +}
\ No newline at end of file diff --git a/test/files/run/idempotency-partial-functions.check b/test/files/run/idempotency-partial-functions.check new file mode 100644 index 0000000000..5c8a411655 --- /dev/null +++ b/test/files/run/idempotency-partial-functions.check @@ -0,0 +1,2 @@ +error!! +error! diff --git a/test/files/run/idempotency-partial-functions.scala b/test/files/run/idempotency-partial-functions.scala new file mode 100644 index 0000000000..dd5f1167f1 --- /dev/null +++ b/test/files/run/idempotency-partial-functions.scala @@ -0,0 +1,25 @@ +import scala.reflect.runtime.universe._ +import scala.reflect.runtime.{currentMirror => cm} +import scala.tools.reflect.{ToolBox, ToolBoxError} +import scala.tools.reflect.Eval + +object Test extends App { + val partials = reify { + List((false,true)) collect { case (x,true) => x } + } + try { + println(partials.eval) + } catch { + case _: ToolBoxError => println("error!!") + } + try { + val tb = cm.mkToolBox() + val tpartials = tb.typeCheck(partials.tree) + println(tpartials) + val rtpartials = tb.resetAllAttrs(tpartials) + println(tb.eval(rtpartials)) + } catch { + // this is the current behaviour, rather than the desired behavior; see SI-6187 + case _: ToolBoxError => println("error!") + } +}
\ No newline at end of file diff --git a/test/files/run/idempotency-this.check b/test/files/run/idempotency-this.check new file mode 100644 index 0000000000..08738c4565 --- /dev/null +++ b/test/files/run/idempotency-this.check @@ -0,0 +1,4 @@ +List() +immutable.this.List.apply[String]("") +Apply(TypeApply(Select(Select(This(newTypeName("immutable")), scala.collection.immutable.List), newTermName("apply")), List(TypeTree().setOriginal(Ident(newTypeName("String"))))), List(Literal(Constant("")))) +error! diff --git a/test/files/run/idempotency-this.scala b/test/files/run/idempotency-this.scala new file mode 100644 index 0000000000..5cd4226326 --- /dev/null +++ b/test/files/run/idempotency-this.scala @@ -0,0 +1,22 @@ +import scala.reflect.runtime.universe._ +import scala.reflect.runtime.{currentMirror => cm} +import scala.tools.reflect.{ToolBox, ToolBoxError} +import scala.tools.reflect.Eval + +object Test extends App { + val thiss = reify { + List[String]("") + } + println(thiss.eval) + val tb = cm.mkToolBox() + val tthiss = tb.typeCheck(thiss.tree) + println(tthiss) + println(showRaw(tthiss)) + val rtthiss = tb.resetAllAttrs(tthiss) + try { + println(tb.eval(rtthiss)) + } catch { + // this is the current behaviour, rather than the desired behavior; see SI-5705 + case _: ToolBoxError => println("error!") + } +}
\ No newline at end of file diff --git a/test/files/run/macro-abort-fresh/Test_2.scala b/test/files/run/macro-abort-fresh/Test_2.scala index 15c498efb0..0b9986e9f6 100644 --- a/test/files/run/macro-abort-fresh/Test_2.scala +++ b/test/files/run/macro-abort-fresh/Test_2.scala @@ -2,7 +2,7 @@ object Test extends App { import scala.reflect.runtime.universe._ import scala.reflect.runtime.{currentMirror => cm} import scala.tools.reflect.ToolBox - val tree = Select(Ident("Macros"), newTermName("foo")) + val tree = Select(Ident(newTermName("Macros")), newTermName("foo")) try cm.mkToolBox().eval(tree) catch { case ex: Throwable => println(ex.getMessage) } }
\ No newline at end of file diff --git a/test/files/run/macro-declared-in-class-class/Impls_1.scala b/test/files/run/macro-declared-in-class-class/Impls_1.scala index 1f8f3cbd5a..6f06f6d3f0 100644 --- a/test/files/run/macro-declared-in-class-class/Impls_1.scala +++ b/test/files/run/macro-declared-in-class-class/Impls_1.scala @@ -5,7 +5,7 @@ object Impls { import c.{prefix => prefix} import c.universe._ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix)))) - val body = Block(printPrefix, Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works"))))) + val body = Block(List(printPrefix), Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works"))))) c.Expr[Unit](body) } }
\ No newline at end of file diff --git a/test/files/run/macro-declared-in-class-object/Impls_1.scala b/test/files/run/macro-declared-in-class-object/Impls_1.scala index 1f8f3cbd5a..6f06f6d3f0 100644 --- a/test/files/run/macro-declared-in-class-object/Impls_1.scala +++ b/test/files/run/macro-declared-in-class-object/Impls_1.scala @@ -5,7 +5,7 @@ object Impls { import c.{prefix => prefix} import c.universe._ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix)))) - val body = Block(printPrefix, Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works"))))) + val body = Block(List(printPrefix), Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works"))))) c.Expr[Unit](body) } }
\ No newline at end of file diff --git a/test/files/run/macro-declared-in-class/Impls_1.scala b/test/files/run/macro-declared-in-class/Impls_1.scala index 1f8f3cbd5a..6f06f6d3f0 100644 --- a/test/files/run/macro-declared-in-class/Impls_1.scala +++ b/test/files/run/macro-declared-in-class/Impls_1.scala @@ -5,7 +5,7 @@ object Impls { import c.{prefix => prefix} import c.universe._ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix)))) - val body = Block(printPrefix, Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works"))))) + val body = Block(List(printPrefix), Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works"))))) c.Expr[Unit](body) } }
\ No newline at end of file diff --git a/test/files/run/macro-declared-in-implicit-class/Impls_Macros_1.scala b/test/files/run/macro-declared-in-implicit-class/Impls_Macros_1.scala index d506de4252..837b306976 100644 --- a/test/files/run/macro-declared-in-implicit-class/Impls_Macros_1.scala +++ b/test/files/run/macro-declared-in-implicit-class/Impls_Macros_1.scala @@ -5,7 +5,7 @@ object Impls { import c.{prefix => prefix} import c.universe._ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix)))) - val body = Block(printPrefix, Apply(Ident(definitions.SomeModule), List(Select(Select(prefix.tree, newTermName("x")), newTermName("toInt"))))) + val body = Block(List(printPrefix), Apply(Ident(definitions.SomeModule), List(Select(Select(prefix.tree, newTermName("x")), newTermName("toInt"))))) c.Expr[Option[Int]](body) } } diff --git a/test/files/run/macro-declared-in-method/Impls_1.scala b/test/files/run/macro-declared-in-method/Impls_1.scala index 1f8f3cbd5a..6f06f6d3f0 100644 --- a/test/files/run/macro-declared-in-method/Impls_1.scala +++ b/test/files/run/macro-declared-in-method/Impls_1.scala @@ -5,7 +5,7 @@ object Impls { import c.{prefix => prefix} import c.universe._ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix)))) - val body = Block(printPrefix, Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works"))))) + val body = Block(List(printPrefix), Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works"))))) c.Expr[Unit](body) } }
\ No newline at end of file diff --git a/test/files/run/macro-declared-in-object-class/Impls_1.scala b/test/files/run/macro-declared-in-object-class/Impls_1.scala index 1f8f3cbd5a..6f06f6d3f0 100644 --- a/test/files/run/macro-declared-in-object-class/Impls_1.scala +++ b/test/files/run/macro-declared-in-object-class/Impls_1.scala @@ -5,7 +5,7 @@ object Impls { import c.{prefix => prefix} import c.universe._ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix)))) - val body = Block(printPrefix, Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works"))))) + val body = Block(List(printPrefix), Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works"))))) c.Expr[Unit](body) } }
\ No newline at end of file diff --git a/test/files/run/macro-declared-in-object-object/Impls_1.scala b/test/files/run/macro-declared-in-object-object/Impls_1.scala index 1f8f3cbd5a..6f06f6d3f0 100644 --- a/test/files/run/macro-declared-in-object-object/Impls_1.scala +++ b/test/files/run/macro-declared-in-object-object/Impls_1.scala @@ -5,7 +5,7 @@ object Impls { import c.{prefix => prefix} import c.universe._ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix)))) - val body = Block(printPrefix, Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works"))))) + val body = Block(List(printPrefix), Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works"))))) c.Expr[Unit](body) } }
\ No newline at end of file diff --git a/test/files/run/macro-declared-in-object/Impls_1.scala b/test/files/run/macro-declared-in-object/Impls_1.scala index 1f8f3cbd5a..6f06f6d3f0 100644 --- a/test/files/run/macro-declared-in-object/Impls_1.scala +++ b/test/files/run/macro-declared-in-object/Impls_1.scala @@ -5,7 +5,7 @@ object Impls { import c.{prefix => prefix} import c.universe._ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix)))) - val body = Block(printPrefix, Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works"))))) + val body = Block(List(printPrefix), Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works"))))) c.Expr[Unit](body) } }
\ No newline at end of file diff --git a/test/files/run/macro-declared-in-package-object/Impls_1.scala b/test/files/run/macro-declared-in-package-object/Impls_1.scala index 1f8f3cbd5a..6f06f6d3f0 100644 --- a/test/files/run/macro-declared-in-package-object/Impls_1.scala +++ b/test/files/run/macro-declared-in-package-object/Impls_1.scala @@ -5,7 +5,7 @@ object Impls { import c.{prefix => prefix} import c.universe._ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix)))) - val body = Block(printPrefix, Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works"))))) + val body = Block(List(printPrefix), Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works"))))) c.Expr[Unit](body) } }
\ No newline at end of file diff --git a/test/files/run/macro-declared-in-refinement/Impls_1.scala b/test/files/run/macro-declared-in-refinement/Impls_1.scala index 1f8f3cbd5a..6f06f6d3f0 100644 --- a/test/files/run/macro-declared-in-refinement/Impls_1.scala +++ b/test/files/run/macro-declared-in-refinement/Impls_1.scala @@ -5,7 +5,7 @@ object Impls { import c.{prefix => prefix} import c.universe._ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix)))) - val body = Block(printPrefix, Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works"))))) + val body = Block(List(printPrefix), Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works"))))) c.Expr[Unit](body) } }
\ No newline at end of file diff --git a/test/files/run/macro-declared-in-trait/Impls_1.scala b/test/files/run/macro-declared-in-trait/Impls_1.scala index 1f8f3cbd5a..6f06f6d3f0 100644 --- a/test/files/run/macro-declared-in-trait/Impls_1.scala +++ b/test/files/run/macro-declared-in-trait/Impls_1.scala @@ -5,7 +5,7 @@ object Impls { import c.{prefix => prefix} import c.universe._ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix)))) - val body = Block(printPrefix, Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works"))))) + val body = Block(List(printPrefix), Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works"))))) c.Expr[Unit](body) } }
\ No newline at end of file diff --git a/test/files/run/macro-def-infer-return-type-b/Test_2.scala b/test/files/run/macro-def-infer-return-type-b/Test_2.scala index ef2920a432..ea0fd4bbff 100644 --- a/test/files/run/macro-def-infer-return-type-b/Test_2.scala +++ b/test/files/run/macro-def-infer-return-type-b/Test_2.scala @@ -2,7 +2,7 @@ object Test extends App { import scala.reflect.runtime.universe._ import scala.reflect.runtime.{currentMirror => cm} import scala.tools.reflect.ToolBox - val tree = Apply(Select(Ident("Macros"), newTermName("foo")), List(Literal(Constant(42)))) + val tree = Apply(Select(Ident(newTermName("Macros")), newTermName("foo")), List(Literal(Constant(42)))) try cm.mkToolBox().eval(tree) catch { case ex: Throwable => println(ex.getMessage) } } diff --git a/test/files/run/macro-expand-implicit-argument/Macros_1.scala b/test/files/run/macro-expand-implicit-argument/Macros_1.scala index b1665256cd..d9fd5b8cb0 100644 --- a/test/files/run/macro-expand-implicit-argument/Macros_1.scala +++ b/test/files/run/macro-expand-implicit-argument/Macros_1.scala @@ -43,16 +43,16 @@ object Macros { val n = as.length val arr = newTermName("arr") - val create = Apply(Select(ct.tree, "newArray"), List(const(n))) + val create = Apply(Select(ct.tree, newTermName("newArray")), List(const(n))) val arrtpe = TypeTree(implicitly[c.WeakTypeTag[Array[A]]].tpe) val valdef = ValDef(Modifiers(), arr, arrtpe, create) val updates = (0 until n).map { - i => Apply(Select(Ident(arr), "update"), List(const(i), as(i).tree)) + i => Apply(Select(Ident(arr), newTermName("update")), List(const(i), as(i).tree)) } - val exprs = Seq(valdef) ++ updates ++ Seq(Ident(arr)) - val block = Block(exprs:_*) + val exprs = (Seq(valdef) ++ updates ++ Seq(Ident(arr))).toList + val block = Block(exprs.init, exprs.last) c.Expr[Array[A]](block) } diff --git a/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-bad/Macros_Test_2.scala b/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-bad/Macros_Test_2.scala index 16d2c1e6ac..c832826d64 100644 --- a/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-bad/Macros_Test_2.scala +++ b/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-bad/Macros_Test_2.scala @@ -6,7 +6,7 @@ object Test extends App { import scala.reflect.runtime.universe._ import scala.reflect.runtime.{currentMirror => cm} import scala.tools.reflect.ToolBox - val tree = Apply(Select(Ident("Macros"), newTermName("foo")), List(Typed(Apply(Ident(definitions.ListModule), List(Literal(Constant(1)), Literal(Constant(2)))), Ident(tpnme.WILDCARD_STAR)))) + val tree = Apply(Select(Ident(newTermName("Macros")), newTermName("foo")), List(Typed(Apply(Ident(definitions.ListModule), List(Literal(Constant(1)), Literal(Constant(2)))), Ident(tpnme.WILDCARD_STAR)))) try cm.mkToolBox().eval(tree) catch { case ex: Throwable => println(ex.getMessage) } }
\ No newline at end of file diff --git a/test/files/run/macro-impl-default-params/Impls_Macros_1.scala b/test/files/run/macro-impl-default-params/Impls_Macros_1.scala index db77b1923a..7c40045c0f 100644 --- a/test/files/run/macro-impl-default-params/Impls_Macros_1.scala +++ b/test/files/run/macro-impl-default-params/Impls_Macros_1.scala @@ -6,11 +6,11 @@ object Impls { import c.{prefix => prefix} import c.universe._ val U = implicitly[c.WeakTypeTag[U]] - val body = Block( + val body = Block(List( Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("invoking foo_targs...")))), Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("type of prefix is: " + prefix.staticType)))), Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("type of prefix tree is: " + prefix.tree.tpe)))), - Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("U is: " + U.tpe)))), + Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("U is: " + U.tpe))))), Literal(Constant(()))) c.Expr[Unit](body) } diff --git a/test/files/run/macro-impl-rename-context/Impls_Macros_1.scala b/test/files/run/macro-impl-rename-context/Impls_Macros_1.scala index 537f1db8c6..56c23f5faf 100644 --- a/test/files/run/macro-impl-rename-context/Impls_Macros_1.scala +++ b/test/files/run/macro-impl-rename-context/Impls_Macros_1.scala @@ -3,8 +3,8 @@ import scala.reflect.macros.{Context => Ctx} object Impls { def foo(unconventionalName: Ctx)(x: unconventionalName.Expr[Int]) = { import unconventionalName.universe._ - val body = Block( - Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("invoking foo...")))), + val body = Block(List( + Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("invoking foo..."))))), Literal(Constant(()))) unconventionalName.Expr[Unit](body) } diff --git a/test/files/run/macro-invalidret-doesnt-conform-to-def-rettype/Test_2.scala b/test/files/run/macro-invalidret-doesnt-conform-to-def-rettype/Test_2.scala index 15c498efb0..0b9986e9f6 100644 --- a/test/files/run/macro-invalidret-doesnt-conform-to-def-rettype/Test_2.scala +++ b/test/files/run/macro-invalidret-doesnt-conform-to-def-rettype/Test_2.scala @@ -2,7 +2,7 @@ object Test extends App { import scala.reflect.runtime.universe._ import scala.reflect.runtime.{currentMirror => cm} import scala.tools.reflect.ToolBox - val tree = Select(Ident("Macros"), newTermName("foo")) + val tree = Select(Ident(newTermName("Macros")), newTermName("foo")) try cm.mkToolBox().eval(tree) catch { case ex: Throwable => println(ex.getMessage) } }
\ No newline at end of file diff --git a/test/files/run/macro-invalidret-nontypeable/Impls_Macros_1.scala b/test/files/run/macro-invalidret-nontypeable/Impls_Macros_1.scala index 405ae7024f..fb0d55208c 100644 --- a/test/files/run/macro-invalidret-nontypeable/Impls_Macros_1.scala +++ b/test/files/run/macro-invalidret-nontypeable/Impls_Macros_1.scala @@ -3,7 +3,7 @@ import scala.reflect.macros.{Context => Ctx} object Impls { def foo(c: Ctx) = { import c.universe._ - val body = Ident("IDoNotExist") + val body = Ident(newTermName("IDoNotExist")) c.Expr[Int](body) } } diff --git a/test/files/run/macro-invalidret-nontypeable/Test_2.scala b/test/files/run/macro-invalidret-nontypeable/Test_2.scala index 15c498efb0..0daee49a08 100644 --- a/test/files/run/macro-invalidret-nontypeable/Test_2.scala +++ b/test/files/run/macro-invalidret-nontypeable/Test_2.scala @@ -1,8 +1,8 @@ -object Test extends App { + object Test extends App { import scala.reflect.runtime.universe._ import scala.reflect.runtime.{currentMirror => cm} import scala.tools.reflect.ToolBox - val tree = Select(Ident("Macros"), newTermName("foo")) + val tree = Select(Ident(newTermName("Macros")), newTermName("foo")) try cm.mkToolBox().eval(tree) catch { case ex: Throwable => println(ex.getMessage) } }
\ No newline at end of file diff --git a/test/files/run/macro-invalidusage-badret/Test_2.scala b/test/files/run/macro-invalidusage-badret/Test_2.scala index f3a76f3fff..5cb0be5ddd 100644 --- a/test/files/run/macro-invalidusage-badret/Test_2.scala +++ b/test/files/run/macro-invalidusage-badret/Test_2.scala @@ -2,7 +2,7 @@ object Test extends App { import scala.reflect.runtime.universe._ import scala.reflect.runtime.{currentMirror => cm} import scala.tools.reflect.ToolBox - val tree = Typed(Apply(Select(Ident("Macros"), newTermName("foo")), List(Literal(Constant(42)))), Ident(newTypeName("String"))) + val tree = Typed(Apply(Select(Ident(newTermName("Macros")), newTermName("foo")), List(Literal(Constant(42)))), Ident(newTypeName("String"))) try cm.mkToolBox().eval(tree) catch { case ex: Throwable => println(ex.getMessage) } } diff --git a/test/files/run/macro-invalidusage-partialapplication-with-tparams/Test_2.scala b/test/files/run/macro-invalidusage-partialapplication-with-tparams/Test_2.scala index c91fd7d380..e453d0b70c 100644 --- a/test/files/run/macro-invalidusage-partialapplication-with-tparams/Test_2.scala +++ b/test/files/run/macro-invalidusage-partialapplication-with-tparams/Test_2.scala @@ -2,7 +2,7 @@ object Test extends App { import scala.reflect.runtime.universe._ import scala.reflect.runtime.{currentMirror => cm} import scala.tools.reflect.ToolBox - val tree = Select(Ident("Macros"), newTermName("foo")) + val tree = Select(Ident(newTermName("Macros")), newTermName("foo")) try cm.mkToolBox().eval(tree) catch { case ex: Throwable => println(ex.getMessage) } } diff --git a/test/files/run/macro-invalidusage-partialapplication/Test_2.scala b/test/files/run/macro-invalidusage-partialapplication/Test_2.scala index cbfee725e2..dc48c127f4 100644 --- a/test/files/run/macro-invalidusage-partialapplication/Test_2.scala +++ b/test/files/run/macro-invalidusage-partialapplication/Test_2.scala @@ -2,7 +2,7 @@ object Test extends App { import scala.reflect.runtime.universe._ import scala.reflect.runtime.{currentMirror => cm} import scala.tools.reflect.ToolBox - val tree = Apply(Select(Ident("Macros"), newTermName("foo")), List(Literal(Constant(40)))) + val tree = Apply(Select(Ident(newTermName("Macros")), newTermName("foo")), List(Literal(Constant(40)))) try cm.mkToolBox().eval(tree) catch { case ex: Throwable => println(ex.getMessage) } } diff --git a/test/files/run/macro-reflective-ma-normal-mdmi/Test_2.scala b/test/files/run/macro-reflective-ma-normal-mdmi/Test_2.scala index 373c6a6fca..2e64c01e35 100644 --- a/test/files/run/macro-reflective-ma-normal-mdmi/Test_2.scala +++ b/test/files/run/macro-reflective-ma-normal-mdmi/Test_2.scala @@ -2,6 +2,6 @@ object Test extends App { import scala.reflect.runtime.universe._ import scala.reflect.runtime.{currentMirror => cm} import scala.tools.reflect.ToolBox - val tree = Apply(Select(Ident("Macros"), newTermName("foo")), List(Literal(Constant(42)))) + val tree = Apply(Select(Ident(newTermName("Macros")), newTermName("foo")), List(Literal(Constant(42)))) println(cm.mkToolBox().eval(tree)) } diff --git a/test/files/run/macro-reflective-mamd-normal-mi/Macros_Test_2.scala b/test/files/run/macro-reflective-mamd-normal-mi/Macros_Test_2.scala index adecfcff17..70560009b1 100644 --- a/test/files/run/macro-reflective-mamd-normal-mi/Macros_Test_2.scala +++ b/test/files/run/macro-reflective-mamd-normal-mi/Macros_Test_2.scala @@ -11,10 +11,10 @@ object Test extends App { val macrobody = Select(Ident(newTermName("Impls")), newTermName("foo")) val macroparam = ValDef(NoMods, newTermName("x"), TypeTree(definitions.IntClass.toType), EmptyTree) val macrodef = DefDef(Modifiers(MACRO), newTermName("foo"), Nil, List(List(macroparam)), TypeTree(), macrobody) - val modulector = DefDef(NoMods, nme.CONSTRUCTOR, Nil, List(List()), TypeTree(), Block(Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List()))) + val modulector = DefDef(NoMods, nme.CONSTRUCTOR, Nil, List(List()), TypeTree(), Block(List(Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List())), Literal(Constant(())))) val module = ModuleDef(NoMods, newTermName("Macros"), Template(Nil, emptyValDef, List(modulector, macrodef))) - val macroapp = Apply(Select(Ident("Macros"), newTermName("foo")), List(Literal(Constant(42)))) - val tree = Block(macrodef, module, macroapp) + val macroapp = Apply(Select(Ident(newTermName("Macros")), newTermName("foo")), List(Literal(Constant(42)))) + val tree = Block(List(macrodef, module), macroapp) val toolbox = cm.mkToolBox(options = "-language:experimental.macros") println(toolbox.eval(tree)) } diff --git a/test/files/run/macro-reify-freevars/Test_2.scala b/test/files/run/macro-reify-freevars/Test_2.scala index e24758cfb4..7af9d89bdb 100644 --- a/test/files/run/macro-reify-freevars/Test_2.scala +++ b/test/files/run/macro-reify-freevars/Test_2.scala @@ -2,8 +2,8 @@ object Test extends App { import scala.reflect.runtime.universe._ import scala.reflect.runtime.{currentMirror => cm} import scala.tools.reflect.ToolBox - val q = New(AppliedTypeTree(Select(Select(Select(Ident("scala"), newTermName("collection")), newTermName("slick")), newTypeName("Queryable")), List(Ident("Int")))) - val x = ValDef(NoMods, newTermName("x"), Ident("Int"), EmptyTree) + val q = New(AppliedTypeTree(Select(Select(Select(Ident(newTermName("scala")), newTermName("collection")), newTermName("slick")), newTypeName("Queryable")), List(Ident(newTermName("Int"))))) + val x = ValDef(NoMods, newTermName("x"), Ident(newTermName("Int")), EmptyTree) val fn = Function(List(x), Apply(Select(Ident(newTermName("x")), newTermName("$plus")), List(Literal(Constant("5"))))) val tree = Apply(Select(q, newTermName("map")), List(fn)) try cm.mkToolBox().eval(tree) diff --git a/test/files/run/macro-reify-splice-outside-reify/Test_2.scala b/test/files/run/macro-reify-splice-outside-reify/Test_2.scala index 8f96ea199d..54bd03fcd2 100644 --- a/test/files/run/macro-reify-splice-outside-reify/Test_2.scala +++ b/test/files/run/macro-reify-splice-outside-reify/Test_2.scala @@ -2,7 +2,7 @@ object Test extends App { import scala.reflect.runtime.universe._ import scala.reflect.runtime.{currentMirror => cm} import scala.tools.reflect.ToolBox - val tree = Apply(Select(Ident("Macros"), newTermName("foo")), List(Literal(Constant(42)))) + val tree = Apply(Select(Ident(newTermName("Macros")), newTermName("foo")), List(Literal(Constant(42)))) try println(cm.mkToolBox().eval(tree)) catch { case ex: Throwable => println(ex.getMessage) } } diff --git a/test/files/run/macro-reify-tagless-a/Test_2.scala b/test/files/run/macro-reify-tagless-a/Test_2.scala index 1bb3945ece..584c4bdf5b 100644 --- a/test/files/run/macro-reify-tagless-a/Test_2.scala +++ b/test/files/run/macro-reify-tagless-a/Test_2.scala @@ -6,9 +6,9 @@ object Test extends App { import scala.reflect.runtime.{currentMirror => cm} import scala.tools.reflect.ToolBox val tpt = AppliedTypeTree(Ident(definitions.ListClass), List(Ident(definitions.StringClass))) - val rhs = Apply(Select(Ident("Macros"), newTermName("foo")), List(Literal(Constant("hello world")))) + val rhs = Apply(Select(Ident(newTermName("Macros")), newTermName("foo")), List(Literal(Constant("hello world")))) val list = ValDef(NoMods, newTermName("list"), tpt, rhs) - val tree = Block(list, Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Ident(list.name)))) + val tree = Block(List(list), Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Ident(list.name)))) try cm.mkToolBox().eval(tree) catch { case ex: Throwable => println(ex.getMessage) } } diff --git a/test/files/run/rawstrings.check b/test/files/run/rawstrings.check index 36e63594df..2b6c40725a 100644 --- a/test/files/run/rawstrings.check +++ b/test/files/run/rawstrings.check @@ -1 +1 @@ -[\n\t'"$] +[\n\t'"$\n] diff --git a/test/files/run/rawstrings.scala b/test/files/run/rawstrings.scala index 9df64f6625..b4d6e0c40a 100644 --- a/test/files/run/rawstrings.scala +++ b/test/files/run/rawstrings.scala @@ -1,3 +1,3 @@ object Test extends App { - println(raw"[\n\t'${'"'}$$]") + println(raw"[\n\t'${'"'}$$\n]") } diff --git a/test/files/run/reify_renamed_term_basic.check b/test/files/run/reify_renamed_term_basic.check new file mode 100644 index 0000000000..e78f94fffd --- /dev/null +++ b/test/files/run/reify_renamed_term_basic.check @@ -0,0 +1 @@ +((),(),()) diff --git a/test/files/run/reify_renamed_term_basic.scala b/test/files/run/reify_renamed_term_basic.scala new file mode 100644 index 0000000000..cd76def395 --- /dev/null +++ b/test/files/run/reify_renamed_term_basic.scala @@ -0,0 +1,20 @@ +import scala.reflect.runtime.universe._ +import scala.tools.reflect.Eval + +object A { + object B { + val c = () + } +} + +object Test extends App { + import A.{B => X} + import A.B.{c => y} + import X.{c => z} + + val expr = reify ( + X.c, y, z + ) + + println(expr.eval) +}
\ No newline at end of file diff --git a/test/files/run/reify_renamed_term_local_to_reifee.check b/test/files/run/reify_renamed_term_local_to_reifee.check new file mode 100644 index 0000000000..e78f94fffd --- /dev/null +++ b/test/files/run/reify_renamed_term_local_to_reifee.check @@ -0,0 +1 @@ +((),(),()) diff --git a/test/files/run/reify_renamed_term_local_to_reifee.scala b/test/files/run/reify_renamed_term_local_to_reifee.scala new file mode 100644 index 0000000000..1860316a5b --- /dev/null +++ b/test/files/run/reify_renamed_term_local_to_reifee.scala @@ -0,0 +1,20 @@ +import scala.reflect.runtime.universe._ +import scala.tools.reflect.Eval + +object A { + object B { + val c = () + } +} + +object Test extends App { + val expr = reify { + import A.{B => X} + import A.B.{c => y} + import X.{c => z} + + (X.c, y, z) + } + + println(expr.eval) +}
\ No newline at end of file diff --git a/test/files/run/reify_renamed_term_overloaded_method.check b/test/files/run/reify_renamed_term_overloaded_method.check new file mode 100644 index 0000000000..48082f72f0 --- /dev/null +++ b/test/files/run/reify_renamed_term_overloaded_method.check @@ -0,0 +1 @@ +12 diff --git a/test/files/run/reify_renamed_term_overloaded_method.scala b/test/files/run/reify_renamed_term_overloaded_method.scala new file mode 100644 index 0000000000..3ef442d203 --- /dev/null +++ b/test/files/run/reify_renamed_term_overloaded_method.scala @@ -0,0 +1,17 @@ +import scala.reflect.runtime.universe._ +import scala.tools.reflect.Eval + +object O { + def show(i: Int) = i.toString + def show(s: String) = s +} + +object Test extends App { + import O.{show => s} + + val expr = reify { + s("1") + s(2) + } + + println(expr.eval) +}
\ No newline at end of file diff --git a/test/files/run/reify_renamed_term_si5841.check b/test/files/run/reify_renamed_term_si5841.check new file mode 100644 index 0000000000..6031277b76 --- /dev/null +++ b/test/files/run/reify_renamed_term_si5841.check @@ -0,0 +1 @@ +class scala.reflect.runtime.JavaUniverse diff --git a/test/files/run/reify_renamed_term_si5841.scala b/test/files/run/reify_renamed_term_si5841.scala new file mode 100644 index 0000000000..ef18d650bf --- /dev/null +++ b/test/files/run/reify_renamed_term_si5841.scala @@ -0,0 +1,7 @@ +import scala.reflect.runtime.universe._ +import scala.reflect.runtime.{universe => ru} +import scala.tools.reflect.Eval + +object Test extends App { + println(reify{ru}.eval.getClass) +}
\ No newline at end of file diff --git a/test/files/run/reify_renamed_type_basic.check b/test/files/run/reify_renamed_type_basic.check new file mode 100644 index 0000000000..6a452c185a --- /dev/null +++ b/test/files/run/reify_renamed_type_basic.check @@ -0,0 +1 @@ +() diff --git a/test/files/run/reify_renamed_type_basic.scala b/test/files/run/reify_renamed_type_basic.scala new file mode 100644 index 0000000000..23729e5c54 --- /dev/null +++ b/test/files/run/reify_renamed_type_basic.scala @@ -0,0 +1,16 @@ +import scala.reflect.runtime.universe._ +import scala.tools.reflect.Eval + +object O { + type A = Unit +} + +object Test extends App { + import O.{A => X} + + def expr = reify { + val a: X = () + } + + println(expr.eval) +}
\ No newline at end of file diff --git a/test/files/run/reify_renamed_type_local_to_reifee.check b/test/files/run/reify_renamed_type_local_to_reifee.check new file mode 100644 index 0000000000..6a452c185a --- /dev/null +++ b/test/files/run/reify_renamed_type_local_to_reifee.check @@ -0,0 +1 @@ +() diff --git a/test/files/run/reify_renamed_type_local_to_reifee.scala b/test/files/run/reify_renamed_type_local_to_reifee.scala new file mode 100644 index 0000000000..ed1bad239e --- /dev/null +++ b/test/files/run/reify_renamed_type_local_to_reifee.scala @@ -0,0 +1,24 @@ +import scala.reflect.runtime.universe._ +import scala.tools.reflect.Eval + +object O { + type A = Unit +} + +object Test extends App { + val expr = reify { + import O.{A => X} + + val a: X = () + + object P { + type B = Unit + } + + import P.{B => Y} + + val b: Y = () + } + + println(expr.eval) +}
\ No newline at end of file diff --git a/test/files/run/reify_renamed_type_spliceable.check b/test/files/run/reify_renamed_type_spliceable.check new file mode 100644 index 0000000000..6a452c185a --- /dev/null +++ b/test/files/run/reify_renamed_type_spliceable.check @@ -0,0 +1 @@ +() diff --git a/test/files/run/reify_renamed_type_spliceable.scala b/test/files/run/reify_renamed_type_spliceable.scala new file mode 100644 index 0000000000..9c2cff5199 --- /dev/null +++ b/test/files/run/reify_renamed_type_spliceable.scala @@ -0,0 +1,21 @@ +import scala.reflect.runtime.universe._ +import scala.tools.reflect.Eval + +abstract class C { + type T >: Null +} + +object Test extends App { + def foo(c: C) = { + import c.{T => U} + reify { + val x: U = null + } + } + + val expr = foo(new C { + type T = AnyRef + }) + + println(expr.eval) +}
\ No newline at end of file diff --git a/test/files/run/showraw_aliases.check b/test/files/run/showraw_aliases.check index 1838bf9bec..aebd354031 100644 --- a/test/files/run/showraw_aliases.check +++ b/test/files/run/showraw_aliases.check @@ -1,2 +1,2 @@ -Block(List(Import(Select(Select(Ident(scala), scala.reflect), scala.reflect.runtime), List(ImportSelector(newTermName("universe"), 52, newTermName("ru"), 64)))), Select(Select(Select(Select(Ident(scala), scala.reflect), scala.reflect.runtime), scala.reflect.runtime.package), [newTermName("universe") aka newTermName("ru")])) -Block(List(Import(Select(Select(Ident(scala#<id>), scala.reflect#<id>), scala.reflect.runtime#<id>), List(ImportSelector(newTermName("universe"), 52, newTermName("ru"), 64)))), Select(Select(Select(Select(Ident(scala#<id>), scala.reflect#<id>), scala.reflect.runtime#<id>), scala.reflect.runtime.package#<id>), [newTermName("universe")#<id> aka newTermName("ru")])) +Block(List(Import(Select(Select(Ident(scala), scala.reflect), scala.reflect.runtime), List(ImportSelector(newTermName("universe"), <offset>, newTermName("ru"), <offset>)))), Select(Select(Select(Select(Ident(scala), scala.reflect), scala.reflect.runtime), scala.reflect.runtime.package), [newTermName("universe") aka newTermName("ru")])) +Block(List(Import(Select(Select(Ident(scala#<id>), scala.reflect#<id>), scala.reflect.runtime#<id>), List(ImportSelector(newTermName("universe"), <offset>, newTermName("ru"), <offset>)))), Select(Select(Select(Select(Ident(scala#<id>), scala.reflect#<id>), scala.reflect.runtime#<id>), scala.reflect.runtime.package#<id>), [newTermName("universe")#<id> aka newTermName("ru")])) diff --git a/test/files/run/showraw_aliases.scala b/test/files/run/showraw_aliases.scala index 3a68ca37b2..65b4fcb1cd 100644 --- a/test/files/run/showraw_aliases.scala +++ b/test/files/run/showraw_aliases.scala @@ -9,7 +9,9 @@ object Test extends App { """) val ttree = tb.typeCheck(tree) - def stabilize(s: String) = """#\d+""".r.replaceAllIn(s, "#<id>") - println(showRaw(ttree)) + def stabilizeIds(s: String) = """#\d+""".r.replaceAllIn(s, "#<id>") + def stabilizePositions(s: String) = """\d+""".r.replaceAllIn(s, "<offset>") + def stabilize(s: String) = stabilizePositions(stabilizeIds(s)) + println(stabilize(showRaw(ttree))) println(stabilize(showRaw(ttree, printIds = true))) }
\ No newline at end of file diff --git a/test/files/run/sm-interpolator.scala b/test/files/run/sm-interpolator.scala new file mode 100644 index 0000000000..7f7b9f061a --- /dev/null +++ b/test/files/run/sm-interpolator.scala @@ -0,0 +1,41 @@ +object Test extends App { + import scala.reflect.internal.util.StringContextStripMarginOps + def check(actual: Any, expected: Any) = if (actual != expected) sys.error(s"expected: [$expected], actual: [$actual])") + + val bar = "|\n ||" + + check( + sm"""|ab + |de + |${bar} | ${1}""", + "ab \nde\n|\n || | 1") + + check( + sm"|", + "") + + check( + sm"${0}", + "0") + + check( + sm"${0}", + "0") + + check( + sm"""${0}|${1} + |""", + "0|1\n") + + check( + sm""" ||""", + "|") + + check( + sm""" ${" "} ||""", + " ||") + + check( + sm"\n", + raw"\n".stripMargin) +} diff --git a/test/files/run/t1672.scala b/test/files/run/t1672.scala new file mode 100644 index 0000000000..ee025b9031 --- /dev/null +++ b/test/files/run/t1672.scala @@ -0,0 +1,28 @@ +object Test { + @annotation.tailrec + def bar(i : Int) : Int = { + if (i == 0) 0 + else try { + throw new RuntimeException + } catch { + case _: Throwable => bar(i - 1) + } + } + + @annotation.tailrec + def nestedTry1(i : Int) : Int = { + if (i == 0) 0 + else try { + throw new RuntimeException + } catch { + case _: Throwable => + try { ??? } catch { case _: Throwable => nestedTry1(i - 1) } + } + } + + def main(args: Array[String]) { + assert(bar(2) == 0) + + assert(nestedTry1(2) == 0) + } +} diff --git a/test/files/run/t5064.check b/test/files/run/t5064.check index 077006abd9..61ccfd16e7 100644 --- a/test/files/run/t5064.check +++ b/test/files/run/t5064.check @@ -1,6 +1,6 @@ -[12] T5064.super.<init>() -[12] T5064.super.<init> -[12] this +[53] T5064.super.<init>() +[53] T5064.super.<init> +[53] this [16:23] immutable.this.List.apply(scala.this.Predef.wrapIntArray(Array[Int]{1})) [16:20] immutable.this.List.apply <16:20> immutable.this.List diff --git a/test/files/run/t5603.check b/test/files/run/t5603.check index 5127d3c1c7..3b2eb55313 100644 --- a/test/files/run/t5603.check +++ b/test/files/run/t5603.check @@ -12,7 +12,7 @@ [95:101]<paramaccessor> private[this] val i: [98:101]Int = _; <119:139>def <init>([95]i: [98]Int) = <119:139>{ <119:139>val nameElse = <134:139>"Bob"; - [94][94][94]super.<init>(); + [NoPosition][NoPosition][NoPosition]super.<init>(); [94]() }; [168:184]val name = [179:184]"avc"; @@ -20,7 +20,7 @@ }; [215:241]object Test extends [227:241][235:238]App { [227]def <init>() = [227]{ - [227][227][227]super.<init>(); + [NoPosition][NoPosition][NoPosition]super.<init>(); [227]() }; [NoPosition]<empty> diff --git a/test/files/run/t5733.check b/test/files/run/t5733.check new file mode 100644 index 0000000000..e697046a94 --- /dev/null +++ b/test/files/run/t5733.check @@ -0,0 +1,2 @@ +Running ABTest asserts +Done diff --git a/test/files/run/t5733.scala b/test/files/run/t5733.scala new file mode 100644 index 0000000000..360264e4ed --- /dev/null +++ b/test/files/run/t5733.scala @@ -0,0 +1,53 @@ +import scala.language.dynamics + +object A extends Dynamic { + var a = "a" + + def selectDynamic(method:String): String = a + + def updateDynamic(method:String)(v:String) { a = v } +} + +class B extends Dynamic { + var b = "b" + + def selectDynamic(method:String): String = b + + def updateDynamic(method:String)(v:String) { b = v } +} + +object Test extends App { + assert( A.foo == "a" ) + assert( A.bar == "a" ) + A.aaa = "aaa" + assert( A.bar == "aaa" ) + + val b = new B + assert( b.foo == "b" ) + assert( b.bar == "b" ) + b.bbb = "bbb" + assert( b.bar == "bbb" ) + + { + println("Running ABTest asserts") + A.a = "a" + (new ABTest).test() + } + + println("Done") +} + +class ABTest { + def test() { + assert( A.foo == "a" ) + assert( A.bar == "a" ) + A.aaa = "aaa" + assert( A.bar == "aaa" ) + + val b = new B + assert( b.foo == "b" ) + assert( b.bar == "b" ) + b.bbb = "bbb" + assert( b.bar == "bbb" ) + } +} diff --git a/test/files/run/t5753_1.check b/test/files/run/t5753_1.check new file mode 100644 index 0000000000..f70d7bba4a --- /dev/null +++ b/test/files/run/t5753_1.check @@ -0,0 +1 @@ +42
\ No newline at end of file diff --git a/test/files/run/t5753_1.flags b/test/files/run/t5753_1.flags new file mode 100644 index 0000000000..cd66464f2f --- /dev/null +++ b/test/files/run/t5753_1.flags @@ -0,0 +1 @@ +-language:experimental.macros
\ No newline at end of file diff --git a/test/files/run/t5753_1/Impls_Macros_1.scala b/test/files/run/t5753_1/Impls_Macros_1.scala new file mode 100644 index 0000000000..1664301f5f --- /dev/null +++ b/test/files/run/t5753_1/Impls_Macros_1.scala @@ -0,0 +1,10 @@ +import scala.reflect.macros.Context +import language.experimental.macros + +trait Impls { + def impl(c: Context)(x: c.Expr[Any]) = x +} + +object Macros extends Impls { + def foo(x: Any) = macro impl +}
\ No newline at end of file diff --git a/test/files/run/t5753_1/Test_2.scala b/test/files/run/t5753_1/Test_2.scala new file mode 100644 index 0000000000..a2777638bc --- /dev/null +++ b/test/files/run/t5753_1/Test_2.scala @@ -0,0 +1,4 @@ +object Test extends App { + import Macros._ + println(foo(42)) +}
\ No newline at end of file diff --git a/test/files/run/t5753_2.check b/test/files/run/t5753_2.check new file mode 100644 index 0000000000..f70d7bba4a --- /dev/null +++ b/test/files/run/t5753_2.check @@ -0,0 +1 @@ +42
\ No newline at end of file diff --git a/test/files/run/t5753_2.flags b/test/files/run/t5753_2.flags new file mode 100644 index 0000000000..cd66464f2f --- /dev/null +++ b/test/files/run/t5753_2.flags @@ -0,0 +1 @@ +-language:experimental.macros
\ No newline at end of file diff --git a/test/files/run/t5753_2/Impls_Macros_1.scala b/test/files/run/t5753_2/Impls_Macros_1.scala new file mode 100644 index 0000000000..e23c0b938b --- /dev/null +++ b/test/files/run/t5753_2/Impls_Macros_1.scala @@ -0,0 +1,10 @@ +import scala.reflect.macros.{Context => Ctx} + +trait Macro_T { + def foo[T](c: Ctx)(s: c.Expr[T]) = s +} + +object Macros { + def foo[T](s: T) = macro Impls.foo[T] + object Impls extends Macro_T +} diff --git a/test/files/run/t5753_2/Test_2.scala b/test/files/run/t5753_2/Test_2.scala new file mode 100644 index 0000000000..a2777638bc --- /dev/null +++ b/test/files/run/t5753_2/Test_2.scala @@ -0,0 +1,4 @@ +object Test extends App { + import Macros._ + println(foo(42)) +}
\ No newline at end of file diff --git a/test/files/run/t5789.check b/test/files/run/t5789.check new file mode 100644 index 0000000000..ea8d4966b1 --- /dev/null +++ b/test/files/run/t5789.check @@ -0,0 +1,14 @@ +Type in expressions to have them evaluated. +Type :help for more information. + +scala> + +scala> val n = 2 +n: Int = 2 + +scala> () => n +res0: () => Int = <function0> + +scala> + +scala> diff --git a/test/files/run/t5789.scala b/test/files/run/t5789.scala new file mode 100644 index 0000000000..461f6a4aae --- /dev/null +++ b/test/files/run/t5789.scala @@ -0,0 +1,14 @@ + +import scala.tools.nsc._ +import interpreter.ILoop +import scala.tools.partest.ReplTest + + +object Test extends ReplTest { + override def extraSettings = "-Yinline" + def code = """ + val n = 2 + () => n + """ +} + diff --git a/test/files/run/t5894.scala b/test/files/run/t5894.scala new file mode 100644 index 0000000000..abeec32365 --- /dev/null +++ b/test/files/run/t5894.scala @@ -0,0 +1,17 @@ +import language.experimental.macros + +class Test + +object Test { + def foo = macro fooImpl + def fooImpl(c: reflect.macros.Context) = c.literalUnit + + def main(args: Array[String]) { + try { + val method = classOf[Test].getMethod("foo") + sys.error("Static forwarder generated for macro: " + method) + } catch { + case _: NoSuchMethodException => // okay + } + } +} diff --git a/test/files/run/t6023.check b/test/files/run/t6023.check new file mode 100644 index 0000000000..ee93565234 --- /dev/null +++ b/test/files/run/t6023.check @@ -0,0 +1,12 @@ +{ + abstract trait Foo extends AnyRef { + <stable> <accessor> def a: Int + }; + () +} +{ + abstract trait Foo extends AnyRef { + <stable> <accessor> def a: Int + }; + () +} diff --git a/test/files/run/t6023.scala b/test/files/run/t6023.scala new file mode 100644 index 0000000000..07af3685a5 --- /dev/null +++ b/test/files/run/t6023.scala @@ -0,0 +1,17 @@ +import scala.reflect.runtime.universe._ +import scala.reflect.runtime.{currentMirror => cm} +import scala.tools.reflect.ToolBox + +object Test extends App { + // test 1: reify + val tree = reify{ trait Foo { val a: Int } }.tree + println(tree.toString) + + // test 2: import and typecheck + val toolbox = cm.mkToolBox() + val ttree = toolbox.typeCheck(tree) + println(ttree.toString) + + // test 3: import and compile + toolbox.eval(tree) +} diff --git a/test/files/run/t6320.check b/test/files/run/t6320.check new file mode 100644 index 0000000000..e56bacd223 --- /dev/null +++ b/test/files/run/t6320.check @@ -0,0 +1,17 @@ +Type in expressions to have them evaluated. +Type :help for more information. + +scala> + +scala> import scala.language.dynamics +import scala.language.dynamics + +scala> class Dyn(m: Map[String, Any]) extends Dynamic { def selectDynamic[T](s: String): T = m(s).asInstanceOf[T] } +defined class Dyn + +scala> new Dyn(Map("foo" -> 10)).foo[Int] +res0: Int = 10 + +scala> + +scala> diff --git a/test/files/run/t6320.scala b/test/files/run/t6320.scala new file mode 100644 index 0000000000..26085a3d7d --- /dev/null +++ b/test/files/run/t6320.scala @@ -0,0 +1,9 @@ +import scala.tools.partest.ReplTest + +object Test extends ReplTest { + def code = """ +import scala.language.dynamics +class Dyn(m: Map[String, Any]) extends Dynamic { def selectDynamic[T](s: String): T = m(s).asInstanceOf[T] } +new Dyn(Map("foo" -> 10)).foo[Int] + """ +} diff --git a/test/files/run/t6440.check b/test/files/run/t6440.check index b5684daee4..69c253eab4 100644 --- a/test/files/run/t6440.check +++ b/test/files/run/t6440.check @@ -1 +1,4 @@ -Stream((), ?) +pos: source-newSource1,line-9,offset=109 bad symbolic reference. A signature in U.class refers to term pack1 +in package <root> which is not available. +It may be completely missing from the current classpath, or the version on +the classpath might be incompatible with the version used when compiling U.class. ERROR diff --git a/test/files/run/t6440.scala b/test/files/run/t6440.scala index 2b690f31e1..5a3a4150d9 100644 --- a/test/files/run/t6440.scala +++ b/test/files/run/t6440.scala @@ -1,7 +1,48 @@ -object Test { +import scala.tools.partest._ +import java.io.File - def main(args: Array[String]): Unit = { - println(Stream.continually(()).filterNot(_ => false).take(2)) +object Test extends StoreReporterDirectTest { + def code = ??? + + def compileCode(code: String) = { + val classpath = List(sys.props("partest.lib"), testOutput.path) mkString sys.props("path.separator") + compileString(newCompiler("-cp", classpath, "-d", testOutput.path))(code) } + def library1 = """ + package pack1 + trait T + """ + + def library2 = """ + package pack2 + trait U extends pack1.T + """ + + def app = """ + package pack3 + object X { + trait U + } + import X._ + import pack2._ + + trait V extends U + """ + + def show(): Unit = { + Seq(library1, library2) foreach compileCode + assert(filteredInfos.isEmpty, filteredInfos) + + // blow away the entire package + val pack1 = new File(testOutput.path, "pack1") + val tClass = new File(pack1, "T.class") + assert(tClass.exists) + assert(tClass.delete()) + assert(pack1.delete()) + + // bad symbolic reference error expected (but no stack trace!) + compileCode(app) + println(filteredInfos.mkString("\n")) + } } diff --git a/test/files/run/t6440b.check b/test/files/run/t6440b.check new file mode 100644 index 0000000000..9771ce5efb --- /dev/null +++ b/test/files/run/t6440b.check @@ -0,0 +1,4 @@ +pos: NoPosition bad symbolic reference. A signature in U.class refers to type T +in package pack1 which is not available. +It may be completely missing from the current classpath, or the version on +the classpath might be incompatible with the version used when compiling U.class. ERROR diff --git a/test/files/run/t6440b.scala b/test/files/run/t6440b.scala new file mode 100644 index 0000000000..974aca2844 --- /dev/null +++ b/test/files/run/t6440b.scala @@ -0,0 +1,61 @@ +import scala.tools.partest._ +import java.io.File + +object Test extends StoreReporterDirectTest { + def code = ??? + + def compileCode(code: String) = { + val classpath = List(sys.props("partest.lib"), testOutput.path) mkString sys.props("path.separator") + compileString(newCompiler("-cp", classpath, "-d", testOutput.path))(code) + } + + def library1 = """ + package pack1 + trait T + class U { + def t = new T {} + def one = 1 + } + """ + + def library2 = """ + package pack2 + object V { + def u = new pack1.U + } + """ + + def app1 = """ + package pack3 + object Test { + pack2.V.u.one // okay + } + """ + + def app2 = """ + package pack3 + object Test { + pack2.V.u.t // we have to fail if T.class is misisng + } + """ + + def show(): Unit = { + compileCode(library1) + val pack1 = new File(testOutput.path, "pack1") + val tClass = new File(pack1, "T.class") + assert(tClass.exists) + assert(tClass.delete()) + + // allowed to compile, no direct reference to `T` + compileCode(library2) + assert(filteredInfos.isEmpty, filteredInfos) + + // allowed to compile, no direct reference to `T` + compileCode(app1) + assert(filteredInfos.isEmpty, filteredInfos) + + // bad symbolic reference error expected (but no stack trace!) + compileCode(app2) + println(filteredInfos.mkString("\n")) + } +} diff --git a/test/files/run/t6549.check b/test/files/run/t6549.check new file mode 100644 index 0000000000..bc78aac741 --- /dev/null +++ b/test/files/run/t6549.check @@ -0,0 +1,32 @@ +Type in expressions to have them evaluated. +Type :help for more information. + +scala> + +scala> case class `X"`(var xxx: Any) +defined class X$u0022 + +scala> val m = Map(("": Any) -> `X"`("\""), ('s: Any) -> `X"`("\"")) +m: scala.collection.immutable.Map[Any,X"] = Map("" -> X"("), 's -> X"(")) + +scala> m("") +res0: X" = X"(") + +scala> m("").xxx +res1: Any = " + +scala> m("").xxx = 0 +m("").xxx: Any = 0 + +scala> m("").xxx = "\"" +m("").xxx: Any = " + +scala> m('s).xxx = 's +m(scala.Symbol("s")).xxx: Any = 's + +scala> val `"` = 0 +": Int = 0 + +scala> + +scala> diff --git a/test/files/run/t6549.scala b/test/files/run/t6549.scala new file mode 100644 index 0000000000..7335661dc7 --- /dev/null +++ b/test/files/run/t6549.scala @@ -0,0 +1,22 @@ +import scala.tools.partest.ReplTest + +// Check that the fragments of code generated in +// in the REPL correctly escape values added to +// literal strings. +// +// Before, we saw: +// scala> m("").x = 77 +// <console>:10: error: ')' expected but string literal found. +// + "m("").x: Int = " + `$ires8` + "\n" +object Test extends ReplTest { + def code = """ + |case class `X"`(var xxx: Any) + |val m = Map(("": Any) -> `X"`("\""), ('s: Any) -> `X"`("\"")) + |m("") + |m("").xxx + |m("").xxx = 0 + |m("").xxx = "\"" + |m('s).xxx = 's + |val `"` = 0 + """.stripMargin +} diff --git a/test/files/run/t6555.check b/test/files/run/t6555.check new file mode 100644 index 0000000000..04117b7c2f --- /dev/null +++ b/test/files/run/t6555.check @@ -0,0 +1,22 @@ +[[syntax trees at end of specialize]] // newSource1 +package <empty> { + class Foo extends Object { + def <init>(): Foo = { + Foo.super.<init>(); + () + }; + private[this] val f: Int => Int = { + @SerialVersionUID(0) final <synthetic> class $anonfun extends scala.runtime.AbstractFunction1$mcII$sp with Serializable { + def <init>(): anonymous class $anonfun = { + $anonfun.super.<init>(); + () + }; + final def apply(param: Int): Int = $anonfun.this.apply$mcII$sp(param); + <specialized> def apply$mcII$sp(param: Int): Int = param + }; + (new anonymous class $anonfun(): Int => Int) + }; + <stable> <accessor> def f(): Int => Int = Foo.this.f + } +} + diff --git a/test/files/run/t6555.scala b/test/files/run/t6555.scala new file mode 100644 index 0000000000..b1a6137786 --- /dev/null +++ b/test/files/run/t6555.scala @@ -0,0 +1,15 @@ +import scala.tools.partest._ +import java.io.{Console => _, _} + +object Test extends DirectTest { + + override def extraSettings: String = "-usejavacp -Xprint:specialize -d " + testOutput.path + + override def code = "class Foo { val f = (param: Int) => param } " + + override def show(): Unit = { + Console.withErr(System.out) { + compile() + } + } +} diff --git a/test/files/run/t6614.check b/test/files/run/t6614.check new file mode 100644 index 0000000000..2e80ebda8b --- /dev/null +++ b/test/files/run/t6614.check @@ -0,0 +1,11 @@ +(ArrayStack(),true) +(ArrayStack(0),true) +(ArrayStack(0, 1),true) +(ArrayStack(0, 1, 2),true) +(ArrayStack(0, 1, 2, 3),true) +(ArrayStack(0, 1, 2, 3, 4),true) +(ArrayStack(0, 1, 2, 3, 4, 5),true) +(ArrayStack(0, 1, 2, 3, 4, 5, 6),true) +(ArrayStack(0, 1, 2, 3, 4, 5, 6, 7),true) +(ArrayStack(0, 1, 2, 3, 4, 5, 6, 7, 8),true) +(ArrayStack(0, 1, 2, 3, 4, 5, 6, 7, 8, 9),true) diff --git a/test/files/run/t6614.scala b/test/files/run/t6614.scala new file mode 100644 index 0000000000..3ad9f36fc4 --- /dev/null +++ b/test/files/run/t6614.scala @@ -0,0 +1,8 @@ +object Test extends App { + import scala.collection.mutable.ArrayStack + + println((for (i <- 0 to 10) yield { + val in = ArrayStack.tabulate(i)(_.toString) + (in, (in filter (_ => true)) == in) + }).mkString("\n")) +} diff --git a/test/files/run/t6628.check b/test/files/run/t6628.check new file mode 100644 index 0000000000..bb101b641b --- /dev/null +++ b/test/files/run/t6628.check @@ -0,0 +1,2 @@ +true +true diff --git a/test/files/run/t6628.scala b/test/files/run/t6628.scala new file mode 100644 index 0000000000..84524a7a35 --- /dev/null +++ b/test/files/run/t6628.scala @@ -0,0 +1,11 @@ +object Test { + def coll = new Traversable[String] { + override def foreach[U](f:String=>U) { f("1") } + } + val dropped = coll.view drop 1 + + def main(args: Array[String]): Unit = { + println(dropped.isEmpty) + println(dropped.force.isEmpty) + } +} diff --git a/test/files/run/t6631.scala b/test/files/run/t6631.scala new file mode 100644 index 0000000000..e472b83d50 --- /dev/null +++ b/test/files/run/t6631.scala @@ -0,0 +1,18 @@ +import reflect.ClassTag + +object Test extends App { + def intercept[T <: Throwable : ClassTag](act: => Any) = try { + act + } catch { + case x: Throwable => + val cls = implicitly[ClassTag[T]].runtimeClass + assert(cls.isInstance(x), (x.getClass, x, cls).toString) + } + assert(s"""\f\r\n\t""" == "\f\r\n\t") + + import StringContext.InvalidEscapeException + intercept[InvalidEscapeException](s"""\""") + intercept[InvalidEscapeException](s"""\x""") + intercept[InvalidEscapeException](s"\") + +} diff --git a/test/files/run/t6644.scala b/test/files/run/t6644.scala new file mode 100644 index 0000000000..b8b36f957c --- /dev/null +++ b/test/files/run/t6644.scala @@ -0,0 +1,8 @@ +class Testable(val c: String) extends AnyVal { + def matching(cases: Boolean*) = cases contains true +} + +object Test extends App { + assert(new Testable("").matching(true, false)) +} + diff --git a/test/files/run/t6646.check b/test/files/run/t6646.check new file mode 100644 index 0000000000..b0b7ad32f3 --- /dev/null +++ b/test/files/run/t6646.check @@ -0,0 +1,5 @@ +Found NotNull +Found lower +Found 2 +A single ident is always a pattern +A single ident is always a pattern diff --git a/test/files/run/t6646.scala b/test/files/run/t6646.scala new file mode 100644 index 0000000000..150b0df11e --- /dev/null +++ b/test/files/run/t6646.scala @@ -0,0 +1,19 @@ +sealed trait ColumnOption +case object NotNull extends ColumnOption +case object PrimaryKey extends ColumnOption +case object lower extends ColumnOption + +object Test { + def main(args: Array[String]) { + val l = List(PrimaryKey, NotNull, lower) + + // withFilter must be generated in these + for (option @ NotNull <- l) println("Found " + option) + for (option @ `lower` <- l) println("Found " + option) + for ((`lower`, i) <- l.zipWithIndex) println("Found " + i) + + // no withFilter + for (X <- List("A single ident is always a pattern")) println(X) + for (`x` <- List("A single ident is always a pattern")) println(`x`) + } +} diff --git a/test/files/run/t6673.check b/test/files/run/t6673.check new file mode 100644 index 0000000000..ef2aa551dc --- /dev/null +++ b/test/files/run/t6673.check @@ -0,0 +1 @@ +List(x) diff --git a/test/files/run/t6673.scala b/test/files/run/t6673.scala new file mode 100644 index 0000000000..115bbdf234 --- /dev/null +++ b/test/files/run/t6673.scala @@ -0,0 +1,5 @@ +object Test extends App { + def foo(f: String => Array[String])(s: String) = f(s) + val test = foo(Array(_)) _ + println(test("x").toList) +}
\ No newline at end of file diff --git a/test/files/run/t6677.scala b/test/files/run/t6677.scala new file mode 100644 index 0000000000..e6eaf6a498 --- /dev/null +++ b/test/files/run/t6677.scala @@ -0,0 +1,28 @@ + +class Test { + val cm: reflect.runtime.universe.Mirror = reflect.runtime.currentMirror + def error { + new cm.universe.Traverser // java.lang.VerifyError: (class: Test, method: error signature: ()V) Incompatible object argument for function call + + } + + def okay1 { + val cm: reflect.runtime.universe.Mirror = reflect.runtime.currentMirror + + new cm.universe.Traverser + } + + def okay2 { + val cm: reflect.runtime.universe.Mirror = reflect.runtime.currentMirror + val u: reflect.runtime.universe.type = cm.universe + new u.Traverser + } +} + +object Test { + def main(args: Array[String]) { + new Test().error + new Test().okay1 + new Test().okay2 + } +} diff --git a/test/files/run/t6677b.scala b/test/files/run/t6677b.scala new file mode 100644 index 0000000000..e4fe5e3722 --- /dev/null +++ b/test/files/run/t6677b.scala @@ -0,0 +1,33 @@ +trait U { + trait U1 { + class X + } + type U11 <: U1 + val u : U11 = null.asInstanceOf[U11] +} +trait A extends U + +trait B extends U { + def foo = "" + class U11 extends U1 { class X extends super.X { foo } } // refer to foo to add $outer pointer + override val u = new U11 +} +class C { + val ab: A with B = new A with B // `B with A` works. + + def foo { + // fails + new ab.u.X + + // works: + val u = ab.u + new u.X + } +} +object Test { + def main(args: Array[String]) { + // java.lang.NoSuchMethodError: A.u()LB$U11; + // at C.foo(t6677b.scala:23) + new C().foo + } +} diff --git a/test/files/run/t6687.scala b/test/files/run/t6687.scala new file mode 100644 index 0000000000..ee44e5f0d2 --- /dev/null +++ b/test/files/run/t6687.scala @@ -0,0 +1,10 @@ +import scala.reflect.runtime.universe._ + +class A { lazy val x = 1 } + +object Test { + def main(args: Array[String]): Unit = { + val vars = typeOf[A].members.toList filter (x => x.isTerm && x.asTerm.isVar) + assert(vars.isEmpty, vars) + } +} diff --git a/test/files/run/t6690.scala b/test/files/run/t6690.scala new file mode 100644 index 0000000000..43ede967a0 --- /dev/null +++ b/test/files/run/t6690.scala @@ -0,0 +1,62 @@ +import scala.collection.mutable + +object Test extends App { + def last0(ml: mutable.MutableList[Int]) = + ml.asInstanceOf[{def last0: mutable.LinkedList[Int]}].last0 + + def first0(ml: mutable.MutableList[Int]) = + ml.asInstanceOf[{def first0: mutable.LinkedList[Int]}].first0 + + val f = mutable.Queue[Int]() + def check(desc: String) { + assert(f.length == 0, s"$desc: non empty: $f") + assert(last0(f).isEmpty, s"$desc: last0 leak: ${last0(f)}") + assert(first0(f).isEmpty, s"$desc: first0 leak: ${last0(f)}") + } + + f.enqueue(1) + f.dequeue() + check("dequeue 1") + + f.enqueue(1) + f.enqueue(2) + f.dequeue() + assert(last0(f).toList == List(2), last0(f)) + f.dequeue() + check("dequeue 2") + + f.enqueue(1) + f.dequeueAll(_ => false) + f.dequeueAll(_ => true) + check("dequeueAll") + + f.enqueue(1) + f.dequeueFirst(_ => true) + check("dequeueFirst") + + { + f.enqueue(1) + val tail = f.tail + assert(last0(tail).isEmpty, last0(tail)) + assert(first0(tail).isEmpty, first0(tail)) + } + + { + val ml = mutable.MutableList[Int]() + 1 +=: ml + val tail = ml.tail + assert(last0(tail).isEmpty, last0(tail)) + assert(first0(tail).isEmpty, first0(tail)) + } + + { + val ml = mutable.MutableList[Int]() + 1 +=: ml + ml += 2 + val tail = ml.tail + assert(last0(tail).toList == List(2), last0(tail)) + assert(first0(tail) == last0(tail).toList, first0(tail)) + assert(last0(tail.tail).toList == Nil, last0(tail.tail).toList) + assert(first0(tail.tail) == Nil, first0(tail.tail)) + } +} diff --git a/test/files/run/t6695.scala b/test/files/run/t6695.scala new file mode 100644 index 0000000000..b527238a51 --- /dev/null +++ b/test/files/run/t6695.scala @@ -0,0 +1,18 @@ +object Test extends App { + try { + Array("a", "b", "c") match { + case Array("a", "x", "c") => println("x") + case Array("a", "b", "x") => println("a"); + case Array("a", "d", _*) => println("wrongly positive") + } + assert(false, "match succeeded") + } catch { + case _: MatchError => // okay + } + + Array("a", "b", "c") match { + case Array("a", "x", "c") => println("x") + case Array("a", "b", "x") => println("a"); + case Array("a", "b", _*) => // okay + } +} diff --git a/test/files/run/t6706.scala b/test/files/run/t6706.scala new file mode 100644 index 0000000000..905494ca8d --- /dev/null +++ b/test/files/run/t6706.scala @@ -0,0 +1,14 @@ +object Test { + var name = "foo" + 1 + var s1 = Symbol(name) + s1 = null + System.gc + val s2 = Symbol("foo1") + name = null + System.gc + val s3 = Symbol("foo1") + + def main(args: Array[String]): Unit = { + assert(s2 eq s3, ((s2, System.identityHashCode(s2), s3, System.identityHashCode(s3)))) + } +} diff --git a/test/files/run/t6731.check b/test/files/run/t6731.check new file mode 100644 index 0000000000..a5d59bd378 --- /dev/null +++ b/test/files/run/t6731.check @@ -0,0 +1,40 @@ +Mono$.bar() +Mono$.bar +Mono$.bar() +Mono$.bar +Mono$.bar +Mono$.baz +Mono$.bar(bippy=1, boppy=2) +Mono$.baz +Poly.bar[Nothing] +Poly.bar[Int] +Poly.bar[Nothing]() +Poly.bar[Int]() +Poly.bar[Int](1, 2, 3) +Poly.bar[Nothing] +Poly.bar[Int] +Poly.bar[Nothing]() +Poly.bar[Int]() +Poly.bar[Int](1, 2, 3) +Updating.bar +Updating.bar = b +Nest1$Nest2$Nest3$.bippy(1, 2, 3) +Nest1$Nest2$Nest3$.bippy +Named.bippy(a=1, b=2) +Named.boppy(c=3, d=4) +Named.apply() +Named.apply() +Named.apply(e=5, f=6) +Named2.bippy(1)(q0, c) +Named2.bippy(1)(q0, c) +Named2.bippy(1)(b, q0) +Named2.bippy(1)(q0, c) +Named2.bippy(1)(c, b) +Named2.bippy(1)(b, c) +Named2.bippy(1)(q0, c) +Named2.bippy(2)(b, c) +Named2.bippy(1)(q0, c) +Named2.bippy(5)(b, c) +Named2.dingus(100)(b, dong) +Named2.bippy(1)(q0, q1) +Named2.hello(100)(!!, !!) diff --git a/test/files/run/t6731.scala b/test/files/run/t6731.scala new file mode 100644 index 0000000000..89d212e91e --- /dev/null +++ b/test/files/run/t6731.scala @@ -0,0 +1,143 @@ +import scala.language.dynamics +import scala.reflect.{ ClassTag, classTag } + +object Util { + def show[T](x: T): T = { println(x) ; x } + def mkArgs(xs: Any*) = xs map { case ((k, v)) => k + "=" + v ; case x => "" + x } mkString ("(", ", ", ")") +} +import Util._ + +abstract class MonoDynamic extends Dynamic { + def selectDynamic(name: String): String = show(this + "." + name) + def applyDynamic(name: String)(args: Any*): String = show(this + "." + name + mkArgs(args: _*)) + def applyDynamicNamed(name: String)(args: (String, Any)*): String = show(this + "." + name + mkArgs(args: _*)) + + override def toString = this.getClass.getName split '.' last +} + +object Mono extends MonoDynamic { + def f(s: String): String = s + + def f1 = this.bar() + def f2 = this.bar + def f3 = f(this.bar()) + def f4 = f(this.bar) + def f5 = f(f(f(f(f(f(this.bar)))))) + f(f(f(f(f(f(this.baz)))))) + def f6 = f(f(f(f(f(f(this.bar(bippy = 1, boppy = 2))))))) + f(f(f(f(f(f(this.baz)))))) +} + +object Poly extends Dynamic { + def selectDynamic[T: ClassTag](name: String): String = show(s"$this.$name[${classTag[T]}]") + def applyDynamic[T: ClassTag](name: String)(args: Any*): String = show(args.mkString(s"$this.$name[${classTag[T]}](", ", ", ")")) + + def f(s: String): String = s + + def f1 = this.bar + def f2 = this.bar[Int] + def f3 = this.bar() + def f4 = this.bar[Int]() + def f5 = this.bar[Int](1, 2, 3) + + def f6 = f(f(this.bar)) + def f7 = f(f(this.bar[Int])) + def f8 = f(f(this.bar())) + def f9 = f(f(this.bar[Int]())) + def f10 = f(f(this.bar[Int](1, 2, 3))) + + override def toString = "Poly" +} + +object Updating extends Dynamic { + def selectDynamic(name: String): String = show(s"$this.$name") + def updateDynamic(name: String)(value: Any): String = show(s"$this.$name = $value") + + def f1 = this.bar + def f2 = this.bar = "b" + + override def toString = "Updating" +} + +object Nest1 extends Dynamic { + def applyDynamic(name: String)(args: Any*): Nest2.type = Nest2 + + object Nest2 extends Dynamic { + def applyDynamicNamed(name: String)(args: (String, Any)*): Nest3.type = Nest3 + + object Nest3 extends MonoDynamic { + + } + } + + def f1 = Nest1.bip().bop(foo = "bar").bippy(1, 2, 3) + def f2 = Nest1.bip("abc").bop(foo = 5).bippy +} + +object Named extends Dynamic { + def applyDynamic(name: String)(args: Any*): Named.type = { + show(this + "." + name + mkArgs(args: _*)) + this + } + def applyDynamicNamed(name: String)(args: (String, Any)*): Named.type = { + show(this + "." + name + mkArgs(args: _*)) + this + } + + def f1 = this.bippy(a = 1, b = 2).boppy(c = 3, d = 4)()()(e = 5, f = 6) + override def toString = "Named" +} + +object Named2 extends Dynamic { + def applyDynamic(name: String)(a: Any)(b: Any = "b", c: Any = "c"): Named2.type = { + show(this + "." + name + mkArgs(a) + mkArgs(b, c)) + this + } + def applyDynamicNamed(name: String)(a: (String, Any))(b: (String, Any), c: (String, Any)): Named2.type = { + show(this + "." + name + mkArgs(a) + mkArgs(b, c)) + this + } + + def f1 = this.bippy(1)(b = "q0") + def f2 = this.bippy(1)("q0") + def f3 = this.bippy(1)(c = "q0") + def f4 = this.bippy(1)("q0") + def f5 = this.bippy(1)(c = "b", b = "c") + def f6 = this.bippy(1)("b", "c") + def f7 = this.bippy(1)(b = "q0").bippy(2)() + def f8 = this.bippy(1)("q0").bippy(5)(c = "c").dingus(100)(c = "dong") + def f9 = this.bippy(1)(b = "q0", c = "q1").hello(100)("!!", "!!") + + override def toString = "Named2" +} + + +object Test { + def main(args: Array[String]): Unit = { + { + import Mono._ + f1 ; f2 ; f3 ; f4 ; f5 + f6 + } + { + import Poly._ + f1 ; f2 ; f3 ; f4 ; f5 + f6 ; f7 ; f8 ; f9 ; f10 + } + { + import Updating._ + f1 ; f2 + } + { + import Nest1._ + f1 ; f2 + } + { + import Named._ + f1 + } + { + import Named2._ + f1 ; f2 ; f3 ; f4 ; f5 + f6 ; f7 ; f8 ; f9 + } + } +} diff --git a/test/files/run/toolbox_typecheck_implicitsdisabled.scala b/test/files/run/toolbox_typecheck_implicitsdisabled.scala index f11f0192f3..8a3d433142 100644 --- a/test/files/run/toolbox_typecheck_implicitsdisabled.scala +++ b/test/files/run/toolbox_typecheck_implicitsdisabled.scala @@ -6,16 +6,16 @@ import scala.tools.reflect.ToolBox object Test extends App { val toolbox = cm.mkToolBox() - val tree1 = Block( - Import(Select(Ident(newTermName("scala")), newTermName("Predef")), List(ImportSelector(nme.WILDCARD, -1, null, -1))), + val tree1 = Block(List( + Import(Select(Ident(newTermName("scala")), newTermName("Predef")), List(ImportSelector(nme.WILDCARD, -1, null, -1)))), Apply(Select(Literal(Constant(1)), newTermName("$minus$greater")), List(Literal(Constant(2)))) ) val ttree1 = toolbox.typeCheck(tree1, withImplicitViewsDisabled = false) println(ttree1) try { - val tree2 = Block( - Import(Select(Ident(newTermName("scala")), newTermName("Predef")), List(ImportSelector(nme.WILDCARD, -1, null, -1))), + val tree2 = Block(List( + Import(Select(Ident(newTermName("scala")), newTermName("Predef")), List(ImportSelector(nme.WILDCARD, -1, null, -1)))), Apply(Select(Literal(Constant(1)), newTermName("$minus$greater")), List(Literal(Constant(2)))) ) val ttree2 = toolbox.typeCheck(tree2, withImplicitViewsDisabled = true) diff --git a/test/files/run/typetags_without_scala_reflect_typetag_lookup.check b/test/files/run/typetags_without_scala_reflect_typetag_lookup.check index 53df68cfc2..8c558ced60 100644 --- a/test/files/run/typetags_without_scala_reflect_typetag_lookup.check +++ b/test/files/run/typetags_without_scala_reflect_typetag_lookup.check @@ -1,3 +1,2 @@ -newSource1:9: error: could not find implicit value for evidence parameter of type reflect.runtime.package.universe.TypeTag[Int] - Library.foo[Int] - ^ + +pos: source-newSource1,line-9,offset=466 could not find implicit value for evidence parameter of type reflect.runtime.package.universe.TypeTag[Int] ERROR diff --git a/test/files/run/typetags_without_scala_reflect_typetag_lookup.scala b/test/files/run/typetags_without_scala_reflect_typetag_lookup.scala index e51ecdb180..1fbdc62a1e 100644 --- a/test/files/run/typetags_without_scala_reflect_typetag_lookup.scala +++ b/test/files/run/typetags_without_scala_reflect_typetag_lookup.scala @@ -1,6 +1,6 @@ import scala.tools.partest._ -object Test extends DirectTest { +object Test extends StoreReporterDirectTest { def code = ??? def library = """ @@ -32,14 +32,12 @@ object Test extends DirectTest { } def show(): Unit = { - val prevErr = System.err - val baos = new java.io.ByteArrayOutputStream(); - System.setErr(new java.io.PrintStream(baos)); compileLibrary(); + println(filteredInfos.mkString("\n")) + storeReporter.infos.clear() compileApp(); - // we should get bad symbolic reference errors, because we're trying to call a method that can't be unpickled + // we should get bad symbolic reference errors, because we're trying to use an implicit that can't be unpickled // but we don't know the number of these errors and their order, so I just ignore them all - baos.toString.split("\n") filter (!_.startsWith("error: bad symbolic reference")) foreach println - System.setErr(prevErr) + println(filteredInfos.filterNot(_.msg.contains("bad symbolic reference")).mkString("\n")) } -}
\ No newline at end of file +} diff --git a/test/files/run/typetags_without_scala_reflect_typetag_manifest_interop.check b/test/files/run/typetags_without_scala_reflect_typetag_manifest_interop.check index 729c0715df..acfecce628 100644 --- a/test/files/run/typetags_without_scala_reflect_typetag_manifest_interop.check +++ b/test/files/run/typetags_without_scala_reflect_typetag_manifest_interop.check @@ -1,3 +1,2 @@ -newSource1:9: error: No Manifest available for App.this.T. - manifest[T] - ^ + +pos: source-newSource1,line-9,offset=479 No Manifest available for App.this.T. ERROR diff --git a/test/files/run/typetags_without_scala_reflect_typetag_manifest_interop.scala b/test/files/run/typetags_without_scala_reflect_typetag_manifest_interop.scala index e984127583..6804baa0c3 100644 --- a/test/files/run/typetags_without_scala_reflect_typetag_manifest_interop.scala +++ b/test/files/run/typetags_without_scala_reflect_typetag_manifest_interop.scala @@ -1,6 +1,7 @@ import scala.tools.partest._ +import scala.tools.nsc.Settings -object Test extends DirectTest { +object Test extends StoreReporterDirectTest { def code = ??? def library = """ @@ -29,18 +30,18 @@ object Test extends DirectTest { """ def compileApp() = { val classpath = List(sys.props("partest.lib"), testOutput.path) mkString sys.props("path.separator") + val global = newCompiler("-cp", classpath, "-d", testOutput.path) compileString(newCompiler("-cp", classpath, "-d", testOutput.path))(app) + //global.reporter.ERROR.foreach(println) } def show(): Unit = { - val prevErr = System.err - val baos = new java.io.ByteArrayOutputStream(); - System.setErr(new java.io.PrintStream(baos)); compileLibrary(); + println(filteredInfos.mkString("\n")) + storeReporter.infos.clear() compileApp(); // we should get bad symbolic reference errors, because we're trying to use an implicit that can't be unpickled // but we don't know the number of these errors and their order, so I just ignore them all - baos.toString.split("\n") filter (!_.startsWith("error: bad symbolic reference")) foreach println - System.setErr(prevErr) + println(filteredInfos.filterNot (_.msg.contains("bad symbolic reference")).mkString("\n")) } -}
\ No newline at end of file +} diff --git a/test/pending/run/macro-reify-tagless-b/Test_2.scala b/test/pending/run/macro-reify-tagless-b/Test_2.scala index ebd35ffe47..10487b1515 100644 --- a/test/pending/run/macro-reify-tagless-b/Test_2.scala +++ b/test/pending/run/macro-reify-tagless-b/Test_2.scala @@ -6,7 +6,7 @@ object Test extends App { import scala.reflect.runtime.{currentMirror => cm} import scala.tools.reflect.ToolBox val tpt = AppliedTypeTree(Ident(definitions.ListClass), List(Ident(definitions.StringClass))) - val rhs = Apply(Select(Ident("Macros"), newTermName("foo")), List(Literal(Constant("hello world")))) + val rhs = Apply(Select(Ident(newTermName("Macros")), newTermName("foo")), List(Literal(Constant("hello world")))) val list = ValDef(NoMods, newTermName("list"), tpt, rhs) val tree = Block(list, Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Ident(list.name)))) println(cm.mkToolBox().eval(tree)) diff --git a/test/scaladoc/run/t4922.check b/test/scaladoc/run/t4922.check new file mode 100644 index 0000000000..619c56180b --- /dev/null +++ b/test/scaladoc/run/t4922.check @@ -0,0 +1 @@ +Done. diff --git a/test/scaladoc/run/t4922.scala b/test/scaladoc/run/t4922.scala new file mode 100644 index 0000000000..bce87ac980 --- /dev/null +++ b/test/scaladoc/run/t4922.scala @@ -0,0 +1,32 @@ +import scala.tools.nsc.doc.model._ +import scala.tools.partest.ScaladocModelTest + +object Test extends ScaladocModelTest { + + // Test code + override def code = """ + // This the default values should be displayed + + object Test { + def f (a: Any = "".isEmpty) = () + def g[A](b: A = null) = () + } + """ + + // no need for special settings + def scaladocSettings = "" + + def testModel(rootPackage: Package) = { + // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s)) + import access._ + + val Test = rootPackage._object("Test") + val f = Test._method("f") + val g = Test._method("g") + + def assertEqual(s1: String, s2: String) = assert(s1 == s2, s1 + " == " + s2) + + assertEqual(f.valueParams(0)(0).defaultValue.get.expression, "\"\".isEmpty") + assertEqual(g.valueParams(0)(0).defaultValue.get.expression, "null") + } +}
\ No newline at end of file diff --git a/tools/epfl-publish b/tools/epfl-publish index de5e17b13f..cdf18823a5 100755 --- a/tools/epfl-publish +++ b/tools/epfl-publish @@ -24,7 +24,7 @@ if [[ -z $publish_to ]]; then else echo "Publishing nightly build to $publish_to" # Archive Scala nightly distribution - rsync -az dists/archives/ "$publish_to/distributions" + rsync -az --exclude scala-latest-sources.tgz dists/archives/ "$publish_to/distributions" # only publish scaladoc nightly for trunk [[ $version == "master" ]] && rsync -az build/scaladoc/ "$publish_to/docs" # sbaz |