diff options
Diffstat (limited to 'src')
22 files changed, 359 insertions, 136 deletions
diff --git a/src/build/maven/scala-dist-pom.xml b/src/build/maven/scala-dist-pom.xml index 9a566d231b..22a24dea21 100644 --- a/src/build/maven/scala-dist-pom.xml +++ b/src/build/maven/scala-dist-pom.xml @@ -39,6 +39,12 @@ <artifactId>scala-compiler</artifactId> <version>@VERSION@</version> </dependency> + <dependency> + <groupId>org.scala-lang.plugins</groupId> + <!-- plugins are fully cross-versioned. But, we don't publish with 2.11.0-SNAPSHOT, instead use full version of the last non-snapshot version --> + <artifactId>scala-continuations-plugin_@SCALA_FULL_VERSION@</artifactId> + <version>@CONTINUATIONS_PLUGIN_VERSION@</version> + </dependency> <!-- duplicated from scala-compiler, where it's optional, so that resolving scala-dist's transitive dependencies does not include jline, even though we need to include it in the dist, but macros depending on the compiler diff --git a/src/build/maven/scala-library-all-pom.xml b/src/build/maven/scala-library-all-pom.xml index b649c8c525..3fcf207559 100644 --- a/src/build/maven/scala-library-all-pom.xml +++ b/src/build/maven/scala-library-all-pom.xml @@ -49,11 +49,11 @@ <artifactId>scala-parser-combinators_@SCALA_BINARY_VERSION@</artifactId> <version>@PARSER_COMBINATORS_VERSION@</version> </dependency> - <dependency> - <groupId>org.scala-lang.plugins</groupId> - <artifactId>scala-continuations-plugin_@SCALA_BINARY_VERSION@</artifactId> - <version>@CONTINUATIONS_PLUGIN_VERSION@</version> - </dependency> + <!-- + the continuations plugin is a dependency of scala-dist, as scala-library-all should be + a drop-in replacement for scala-library, and as such should not (indirectly) + depend on plugins/the compiler. + --> <dependency> <groupId>org.scala-lang.plugins</groupId> <artifactId>scala-continuations-library_@SCALA_BINARY_VERSION@</artifactId> diff --git a/src/compiler/scala/reflect/macros/runtime/JavaReflectionRuntimes.scala b/src/compiler/scala/reflect/macros/runtime/JavaReflectionRuntimes.scala index ecdd48db22..be114efbc0 100644 --- a/src/compiler/scala/reflect/macros/runtime/JavaReflectionRuntimes.scala +++ b/src/compiler/scala/reflect/macros/runtime/JavaReflectionRuntimes.scala @@ -14,7 +14,7 @@ trait JavaReflectionRuntimes { def resolveJavaReflectionRuntime(classLoader: ClassLoader): MacroRuntime = { val implClass = Class.forName(className, true, classLoader) - val implMeths = implClass.getDeclaredMethods.find(_.getName == methName) + val implMeths = implClass.getMethods.find(_.getName == methName) // relies on the fact that macro impls cannot be overloaded // so every methName can resolve to at maximum one method val implMeth = implMeths getOrElse { throw new NoSuchMethodException(s"$className.$methName") } diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 1a38fcf3a4..d87090fa46 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -833,19 +833,41 @@ trait Implicits { * so that if there is a best candidate it can still be selected. */ object DivergentImplicitRecovery { - // symbol of the implicit that caused the divergence. - // Initially null, will be saved on first diverging expansion. - private var implicitSym: Symbol = _ - private var countdown: Int = 1 - - def sym: Symbol = implicitSym - def apply(search: SearchResult, i: ImplicitInfo): SearchResult = - if (search.isDivergent && countdown > 0) { - countdown -= 1 - implicitSym = i.sym - log(s"discarding divergent implicit $implicitSym during implicit search") + private var divergentError: Option[DivergentImplicitTypeError] = None + + private def saveDivergent(err: DivergentImplicitTypeError) { + if (divergentError.isEmpty) divergentError = Some(err) + } + + def issueSavedDivergentError() { + divergentError foreach (err => context.issue(err)) + } + + def apply(search: SearchResult, i: ImplicitInfo, errors: Seq[AbsTypeError]): SearchResult = { + // A divergent error from a nested implicit search will be found in `errors`. Stash that + // aside to be re-issued if this implicit search fails. + errors.collectFirst { case err: DivergentImplicitTypeError => err } foreach saveDivergent + + if (search.isDivergent && divergentError.isEmpty) { + // Divergence triggered by `i` at this level of the implicit serach. We haven't + // seen divergence so far, we won't issue this error just yet, and instead temporarily + // treat `i` as a failed candidate. + saveDivergent(DivergentImplicitTypeError(tree, pt, i.sym)) + log(s"discarding divergent implicit ${i.sym} during implicit search") SearchFailure - } else search + } else { + if (search.isFailure) { + // We don't want errors that occur during checking implicit info + // to influence the check of further infos, but we should retain divergent implicit errors + // (except for the one we already squirreled away) + val saved = divergentError.getOrElse(null) + context.reportBuffer.retainErrors { + case err: DivergentImplicitTypeError => err ne saved + } + } + search + } + } } /** Sorted list of eligible implicits. @@ -869,31 +891,33 @@ trait Implicits { * - if it matches, forget about all others it improves upon */ @tailrec private def rankImplicits(pending: Infos, acc: Infos): Infos = pending match { - case Nil => acc - case i :: is => - DivergentImplicitRecovery(typedImplicit(i, ptChecked = true, isLocalToCallsite), i) match { - case sr if sr.isDivergent => - Nil - case sr if sr.isFailure => - // We don't want errors that occur during checking implicit info - // to influence the check of further infos. - context.reportBuffer.retainErrors { - case err: DivergentImplicitTypeError => true + case Nil => acc + case firstPending :: otherPending => + def firstPendingImproves(alt: ImplicitInfo) = + firstPending == alt || ( + try improves(firstPending, alt) + catch { + case e: CyclicReference => + debugwarn(s"Discarding $firstPending during implicit search due to cyclic reference.") + true } - rankImplicits(is, acc) - case newBest => - best = newBest - val newPending = undoLog undo { - is filterNot (alt => alt == i || { - try improves(i, alt) - catch { - case e: CyclicReference => - debugwarn(s"Discarding $i during implicit search due to cyclic reference") - true - } - }) + ) + + val typedFirstPending = typedImplicit(firstPending, ptChecked = true, isLocalToCallsite) + + // Pass the errors to `DivergentImplicitRecovery` so that it can note + // the first `DivergentImplicitTypeError` that is being propagated + // from a nested implicit search; this one will be + // re-issued if this level of the search fails. + DivergentImplicitRecovery(typedFirstPending, firstPending, context.errors) match { + case sr if sr.isDivergent => Nil + case sr if sr.isFailure => rankImplicits(otherPending, acc) + case newBest => + best = newBest // firstPending is our new best, since we already pruned last time around: + val pendingImprovingBest = undoLog undo { + otherPending filterNot firstPendingImproves } - rankImplicits(newPending, i :: acc) + rankImplicits(pendingImprovingBest, firstPending :: acc) } } @@ -921,12 +945,9 @@ trait Implicits { } if (best.isFailure) { - /* If there is no winner, and we witnessed and caught divergence, - * now we can throw it for the error message. - */ - if (DivergentImplicitRecovery.sym != null) { - DivergingImplicitExpansionError(tree, pt, DivergentImplicitRecovery.sym)(context) - } + // If there is no winner, and we witnessed and recorded a divergence error, + // our recovery attempt has failed, so we must now issue it. + DivergentImplicitRecovery.issueSavedDivergentError() if (invalidImplicits.nonEmpty) setAddendum(pos, () => diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index 87da565142..9b9e641cad 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -346,12 +346,14 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT * performance hit for the compiler as a whole. */ override def atOwner[A](tree: Tree, owner: Symbol)(trans: => A): A = { + val savedValid = validCurrentOwner if (owner.isClass) validCurrentOwner = true val savedLocalTyper = localTyper localTyper = localTyper.atOwner(tree, if (owner.isModule) owner.moduleClass else owner) typers = typers updated (owner, localTyper) val result = super.atOwner(tree, owner)(trans) localTyper = savedLocalTyper + validCurrentOwner = savedValid typers -= owner result } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 9f557f4aa5..e3901be546 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1041,11 +1041,11 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper if (tree.tpe <:< AnyTpe) pt.dealias match { case TypeRef(_, UnitClass, _) => // (12) if (settings.warnValueDiscard) - context.unit.warning(tree.pos, "discarded non-Unit value") + context.warning(tree.pos, "discarded non-Unit value") return typedPos(tree.pos, mode, pt)(Block(List(tree), Literal(Constant(())))) case TypeRef(_, sym, _) if isNumericValueClass(sym) && isNumericSubType(tree.tpe, pt) => if (settings.warnNumericWiden) - context.unit.warning(tree.pos, "implicit numeric widening") + context.warning(tree.pos, "implicit numeric widening") return typedPos(tree.pos, mode, pt)(Select(tree, "to" + sym.name)) case _ => } @@ -5109,7 +5109,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper def isPlausible(m: Symbol) = m.alternatives exists (m => requiresNoArgs(m.info)) def maybeWarn(s: String): Unit = { - def warn(message: String) = context.unit.warning(lit.pos, s"$message Did you forget the interpolator?") + def warn(message: String) = context.warning(lit.pos, s"$message Did you forget the interpolator?") def suspiciousSym(name: TermName) = context.lookupSymbol(name, _ => true).symbol def suspiciousExpr = InterpolatorCodeRegex findFirstIn s def suspiciousIdents = InterpolatorIdentRegex findAllIn s map (s => suspiciousSym(s drop 1)) diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala b/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala index 8376fca4ad..68cc728eb3 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala @@ -43,13 +43,13 @@ trait Holes { self: Quasiquotes => tpe <:< NothingClass.tpe || tpe <:< NullClass.tpe private def extractIterableTParam(tpe: Type) = IterableTParam.asSeenFrom(tpe, IterableClass) - private def stripIterable(tpe: Type, limit: Option[Rank] = None): (Rank, Type) = - if (limit.map { _ == NoDot }.getOrElse { false }) (NoDot, tpe) + private def stripIterable(tpe: Type, limit: Rank = DotDotDot): (Rank, Type) = + if (limit == NoDot) (NoDot, tpe) else if (tpe != null && !isIterableType(tpe)) (NoDot, tpe) else if (isBottomType(tpe)) (NoDot, tpe) else { val targ = extractIterableTParam(tpe) - val (rank, innerTpe) = stripIterable(targ, limit.map { _.pred }) + val (rank, innerTpe) = stripIterable(targ, limit.pred) (rank.succ, innerTpe) } private def iterableTypeFromRank(n: Rank, tpe: Type): Type = { @@ -76,10 +76,12 @@ trait Holes { self: Quasiquotes => class ApplyHole(annotatedRank: Rank, unquotee: Tree) extends Hole { val (strippedTpe, tpe): (Type, Type) = { - val (strippedRank, strippedTpe) = stripIterable(unquotee.tpe, limit = Some(annotatedRank)) + val (strippedRank, strippedTpe) = stripIterable(unquotee.tpe, limit = annotatedRank) if (isBottomType(strippedTpe)) cantSplice() - else if (isNativeType(strippedTpe)) (strippedTpe, iterableTypeFromRank(annotatedRank, strippedTpe)) - else if (isLiftableType(strippedTpe)) (strippedTpe, iterableTypeFromRank(annotatedRank, treeType)) + else if (isNativeType(strippedTpe)) { + if (strippedRank != NoDot && !(strippedTpe <:< treeType) && !isLiftableType(strippedTpe)) cantSplice() + else (strippedTpe, iterableTypeFromRank(annotatedRank, strippedTpe)) + } else if (isLiftableType(strippedTpe)) (strippedTpe, iterableTypeFromRank(annotatedRank, treeType)) else cantSplice() } @@ -191,7 +193,7 @@ trait Holes { self: Quasiquotes => val (iterableRank, _) = stripIterable(tpe) if (iterableRank.value < rank.value) c.abort(pat.pos, s"Can't extract $tpe with $rank, consider using $iterableRank") - val (_, strippedTpe) = stripIterable(tpe, limit = Some(rank)) + val (_, strippedTpe) = stripIterable(tpe, limit = rank) if (strippedTpe <:< treeType) treeNoUnlift else unlifters.spawn(strippedTpe, rank).map { diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala index 1b8b0686e8..95113d5b00 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala @@ -193,8 +193,6 @@ trait Reifiers { self: Quasiquotes => reifyBuildCall(nme.SyntacticAppliedType, tpt, targs) case SyntacticFunction(args, body) => reifyBuildCall(nme.SyntacticFunction, args, body) - case SyntacticIdent(name, isBackquoted) => - reifyBuildCall(nme.SyntacticIdent, name, isBackquoted) case SyntacticEmptyTypeTree() => reifyBuildCall(nme.SyntacticEmptyTypeTree) case SyntacticImport(expr, selectors) => @@ -203,6 +201,20 @@ trait Reifiers { self: Quasiquotes => reifyBuildCall(nme.SyntacticPartialFunction, cases) case SyntacticMatch(scrutinee, cases) => reifyBuildCall(nme.SyntacticMatch, scrutinee, cases) + case SyntacticTermIdent(name, isBackquoted) => + reifyBuildCall(nme.SyntacticTermIdent, name, isBackquoted) + case SyntacticTypeIdent(name) => + reifyBuildCall(nme.SyntacticTypeIdent, name) + case SyntacticCompoundType(parents, defns) => + reifyBuildCall(nme.SyntacticCompoundType, parents, defns) + case SyntacticSingletonType(ref) => + reifyBuildCall(nme.SyntacticSingletonType, ref) + case SyntacticTypeProjection(qual, name) => + reifyBuildCall(nme.SyntacticTypeProjection, qual, name) + case SyntacticAnnotatedType(tpt, annot) => + reifyBuildCall(nme.SyntacticAnnotatedType, tpt, annot) + case SyntacticExistentialType(tpt, where) => + reifyBuildCall(nme.SyntacticExistentialType, tpt, where) case Q(tree) if fillListHole.isDefinedAt(tree) => mirrorBuildCall(nme.SyntacticBlock, fillListHole(tree)) case Q(other) => diff --git a/src/library/scala/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala index 01a0aa3b51..1b496383a3 100644 --- a/src/library/scala/collection/Iterator.scala +++ b/src/library/scala/collection/Iterator.scala @@ -165,11 +165,11 @@ object Iterator { /** Avoid stack overflows when applying ++ to lots of iterators by * flattening the unevaluated iterators out into a vector of closures. */ - private[scala] final class ConcatIterator[+A](initial: Vector[() => Iterator[A]]) extends Iterator[A] { - // current set to null when all iterators are exhausted - private[this] var current: Iterator[A] = Iterator.empty + private[scala] final class ConcatIterator[+A](private[this] var current: Iterator[A], initial: Vector[() => Iterator[A]]) extends Iterator[A] { + @deprecated def this(initial: Vector[() => Iterator[A]]) = this(Iterator.empty, initial) // for binary compatibility private[this] var queue: Vector[() => Iterator[A]] = initial // Advance current to the next non-empty iterator + // current is set to null when all iterators are exhausted private[this] def advance(): Boolean = { if (queue.isEmpty) { current = null @@ -185,7 +185,7 @@ object Iterator { def next() = if (hasNext) current.next else Iterator.empty.next override def ++[B >: A](that: => GenTraversableOnce[B]): Iterator[B] = - new ConcatIterator(queue :+ (() => that.toIterator)) + new ConcatIterator(current, queue :+ (() => that.toIterator)) } private[scala] final class JoinIterator[+A](lhs: Iterator[A], that: => GenTraversableOnce[A]) extends Iterator[A] { @@ -194,7 +194,7 @@ object Iterator { def next = if (lhs.hasNext) lhs.next else rhs.next override def ++[B >: A](that: => GenTraversableOnce[B]) = - new ConcatIterator(Vector(() => this, () => that.toIterator)) + new ConcatIterator(this, Vector(() => that.toIterator)) } } diff --git a/src/library/scala/collection/generic/Sorted.scala b/src/library/scala/collection/generic/Sorted.scala index ab0d443a03..a0b0e1318b 100644 --- a/src/library/scala/collection/generic/Sorted.scala +++ b/src/library/scala/collection/generic/Sorted.scala @@ -62,7 +62,8 @@ trait Sorted[K, +This <: Sorted[K, This]] { /** Creates a ranged projection of this collection with both a lower-bound * and an upper-bound. * - * @param from The upper-bound (exclusive) of the ranged projection. + * @param from The lower-bound (inclusive) of the ranged projection. + * @param until The upper-bound (exclusive) of the ranged projection. */ def range(from: K, until: K): This = rangeImpl(Some(from), Some(until)) diff --git a/src/reflect/scala/reflect/api/Internals.scala b/src/reflect/scala/reflect/api/Internals.scala index 9faba7efd7..577cd09295 100644 --- a/src/reflect/scala/reflect/api/Internals.scala +++ b/src/reflect/scala/reflect/api/Internals.scala @@ -765,7 +765,7 @@ trait Internals { self: Universe => val SyntacticPartialFunction: SyntacticPartialFunctionExtractor trait SyntacticPartialFunctionExtractor { def apply(cases: List[Tree]): Match - def unapply(tree: Match): Option[List[CaseDef]] + def unapply(tree: Tree): Option[List[CaseDef]] } val SyntacticMatch: SyntacticMatchExtractor @@ -780,10 +780,16 @@ trait Internals { self: Universe => def unapply(tree: Try): Option[(Tree, List[CaseDef], Tree)] } - val SyntacticIdent: SyntacticIdentExtractor - trait SyntacticIdentExtractor { - def apply(name: Name, isBackquoted: Boolean = false): Ident - def unapply(tree: Ident): Option[(Name, Boolean)] + val SyntacticTermIdent: SyntacticTermIdentExtractor + trait SyntacticTermIdentExtractor { + def apply(name: TermName, isBackquoted: Boolean = false): Ident + def unapply(id: Ident): Option[(TermName, Boolean)] + } + + val SyntacticTypeIdent: SyntacticTypeIdentExtractor + trait SyntacticTypeIdentExtractor { + def apply(name: TypeName): Ident + def unapply(tree: Tree): Option[TypeName] } val SyntacticImport: SyntacticImportExtractor @@ -803,6 +809,36 @@ trait Internals { self: Universe => def apply(qual: Tree, name: TermName): Select def unapply(tree: Tree): Option[(Tree, TermName)] } + + val SyntacticCompoundType: SyntacticCompoundTypeExtractor + trait SyntacticCompoundTypeExtractor { + def apply(parents: List[Tree], defns: List[Tree]): CompoundTypeTree + def unapply(tree: Tree): Option[(List[Tree], List[Tree])] + } + + val SyntacticSingletonType: SyntacitcSingletonTypeExtractor + trait SyntacitcSingletonTypeExtractor { + def apply(tree: Tree): SingletonTypeTree + def unapply(tree: Tree): Option[Tree] + } + + val SyntacticTypeProjection: SyntacticTypeProjectionExtractor + trait SyntacticTypeProjectionExtractor { + def apply(qual: Tree, name: TypeName): SelectFromTypeTree + def unapply(tree: Tree): Option[(Tree, TypeName)] + } + + val SyntacticAnnotatedType: SyntacticAnnotatedTypeExtractor + trait SyntacticAnnotatedTypeExtractor { + def apply(tpt: Tree, annot: Tree): Annotated + def unapply(tree: Tree): Option[(Tree, Tree)] + } + + val SyntacticExistentialType: SyntacticExistentialTypeExtractor + trait SyntacticExistentialTypeExtractor { + def apply(tpt: Tree, where: List[Tree]): ExistentialTypeTree + def unapply(tree: Tree): Option[(Tree, List[MemberDef])] + } } @deprecated("Use `internal.reificationSupport` instead", "2.11.0") diff --git a/src/reflect/scala/reflect/api/Liftables.scala b/src/reflect/scala/reflect/api/Liftables.scala index ec9d85b69e..673dbce6f5 100644 --- a/src/reflect/scala/reflect/api/Liftables.scala +++ b/src/reflect/scala/reflect/api/Liftables.scala @@ -6,7 +6,7 @@ trait Liftables { self: Universe => /** A type class that defines a representation of `T` as a `Tree`. * - * @see [[http://docs.scala-lang.org/overviews/macros/quasiquotes.html#lifting]] + * @see [[http://docs.scala-lang.org/overviews/quasiquotes/lifting.html]] */ trait Liftable[T] { def apply(value: T): Tree @@ -32,7 +32,7 @@ trait Liftables { self: Universe => * lifted: universe.Tree = O * }}} * - * @see [[http://docs.scala-lang.org/overviews/macros/quasiquotes.html#lifting]] + * @see [[http://docs.scala-lang.org/overviews/quasiquotes/lifting.html]] */ def apply[T](f: T => Tree): Liftable[T] = new Liftable[T] { def apply(value: T): Tree = f(value) } @@ -40,7 +40,7 @@ trait Liftables { self: Universe => /** A type class that defines a way to extract instance of `T` from a `Tree`. * - * @see [[http://docs.scala-lang.org/overviews/macros/quasiquotes.html#unlifting]] + * @see [[http://docs.scala-lang.org/overviews/quasiquotes/unlifting.html]] */ trait Unliftable[T] { def unapply(tree: Tree): Option[T] @@ -66,7 +66,7 @@ trait Liftables { self: Universe => * scala> val q"${_: O.type}" = q"$Oref" * }}} * - * @see [[http://docs.scala-lang.org/overviews/macros/quasiquotes.html#unlifting]] + * @see [[http://docs.scala-lang.org/overviews/quasiquotes/unlifting.html]] */ def apply[T](pf: PartialFunction[Tree, T]): Unliftable[T] = new Unliftable[T] { def unapply(value: Tree): Option[T] = pf.lift(value) diff --git a/src/reflect/scala/reflect/api/Mirror.scala b/src/reflect/scala/reflect/api/Mirror.scala index da3afd89ff..318fdb369a 100644 --- a/src/reflect/scala/reflect/api/Mirror.scala +++ b/src/reflect/scala/reflect/api/Mirror.scala @@ -118,4 +118,22 @@ abstract class Mirror[U <: Universe with Singleton] { * @group Mirror */ def staticPackage(fullName: String): U#ModuleSymbol + + /** + * Shortcut for `implicitly[WeakTypeTag[T]].tpe` + * @group TypeTags + */ + def weakTypeOf[T: universe.WeakTypeTag]: U#Type = universe.weakTypeTag[T].in(this).tpe + + /** + * Shortcut for `implicitly[TypeTag[T]].tpe` + * @group TypeTags + */ + def typeOf[T: universe.TypeTag]: U#Type = universe.typeTag[T].in(this).tpe + + /** + * Type symbol of `x` as derived from a type tag. + * @group TypeTags + */ + def symbolOf[T: universe.WeakTypeTag]: U#TypeSymbol } diff --git a/src/reflect/scala/reflect/api/Quasiquotes.scala b/src/reflect/scala/reflect/api/Quasiquotes.scala index 0065926e3b..e905aa4153 100644 --- a/src/reflect/scala/reflect/api/Quasiquotes.scala +++ b/src/reflect/scala/reflect/api/Quasiquotes.scala @@ -7,7 +7,7 @@ trait Quasiquotes { self: Universe => * that are also known as quasiquotes. With their help you can easily manipulate * Scala reflection ASTs. * - * @see [[http://docs.scala-lang.org/overviews/macros/quasiquotes.html]] + * @see [[http://docs.scala-lang.org/overviews/quasiquotes/intro.html]] */ implicit class Quasiquote(ctx: StringContext) { protected trait api { diff --git a/src/reflect/scala/reflect/api/StandardLiftables.scala b/src/reflect/scala/reflect/api/StandardLiftables.scala index af11de46ce..66ac62cc9e 100644 --- a/src/reflect/scala/reflect/api/StandardLiftables.scala +++ b/src/reflect/scala/reflect/api/StandardLiftables.scala @@ -27,6 +27,7 @@ trait StandardLiftables { self: Universe => callScala(stdnme.Symbol)(Literal(Constant(v.name)) :: Nil) } + implicit def liftTree[T <: Tree]: Liftable[T] = Liftable { identity } implicit def liftName[T <: Name]: Liftable[T] = Liftable { name => Ident(name) } implicit def liftExpr[T <: Expr[_]]: Liftable[T] = Liftable { expr => expr.tree } implicit def liftType[T <: Type]: Liftable[T] = Liftable { tpe => TypeTree(tpe) } diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 25d78f4e6f..bf560a21e5 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -490,8 +490,10 @@ trait Definitions extends api.StandardDefinitions { lazy val TypeCreatorClass = getClassIfDefined("scala.reflect.api.TypeCreator") // defined in scala-reflect.jar, so we need to be careful lazy val TreeCreatorClass = getClassIfDefined("scala.reflect.api.TreeCreator") // defined in scala-reflect.jar, so we need to be careful - lazy val BlackboxContextClass = getClassIfDefined("scala.reflect.macros.blackbox.Context") // defined in scala-reflect.jar, so we need to be careful - lazy val WhiteboxContextClass = getClassIfDefined("scala.reflect.macros.whitebox.Context") // defined in scala-reflect.jar, so we need to be careful + private def Context_210 = if (settings.isScala211) NoSymbol else getClassIfDefined("scala.reflect.macros.Context") // needed under -Xsource:2.10 + lazy val BlackboxContextClass = getClassIfDefined("scala.reflect.macros.blackbox.Context").orElse(Context_210) // defined in scala-reflect.jar, so we need to be careful + + lazy val WhiteboxContextClass = getClassIfDefined("scala.reflect.macros.whitebox.Context").orElse(Context_210) // defined in scala-reflect.jar, so we need to be careful def MacroContextPrefix = BlackboxContextClass.map(sym => getMemberMethod(sym, nme.prefix)) def MacroContextPrefixType = BlackboxContextClass.map(sym => getTypeMember(sym, tpnme.PrefixType)) def MacroContextUniverse = BlackboxContextClass.map(sym => getMemberMethod(sym, nme.universe)) diff --git a/src/reflect/scala/reflect/internal/Mirrors.scala b/src/reflect/scala/reflect/internal/Mirrors.scala index 7065a8cd6d..4a35e024de 100644 --- a/src/reflect/scala/reflect/internal/Mirrors.scala +++ b/src/reflect/scala/reflect/internal/Mirrors.scala @@ -30,6 +30,8 @@ trait Mirrors extends api.Mirrors { val EmptyPackageClass: ClassSymbol val EmptyPackage: ModuleSymbol + def symbolOf[T: universe.WeakTypeTag]: universe.TypeSymbol = universe.weakTypeTag[T].in(this).tpe.typeSymbolDirect.asType + def findMemberFromRoot(fullName: Name): Symbol = { val segs = nme.segments(fullName.toString, fullName.isTermName) if (segs.isEmpty) NoSymbol diff --git a/src/reflect/scala/reflect/internal/ReificationSupport.scala b/src/reflect/scala/reflect/internal/ReificationSupport.scala index 9a130337b4..ad8a2594dd 100644 --- a/src/reflect/scala/reflect/internal/ReificationSupport.scala +++ b/src/reflect/scala/reflect/internal/ReificationSupport.scala @@ -6,7 +6,7 @@ import Flags._ import util._ trait ReificationSupport { self: SymbolTable => - import definitions.{TupleClass, FunctionClass, ScalaPackage, UnitClass} + import definitions._ import internal._ class ReificationSupportImpl extends ReificationSupportApi { @@ -227,9 +227,9 @@ trait ReificationSupport { self: SymbolTable => else throw new IllegalArgumentException(s"can't create applied type from non-type $tree") def unapply(tree: Tree): Option[(Tree, List[Tree])] = tree match { - case AppliedTypeTree(tpe, targs) => Some((tpe, targs)) - case _ if tree.isType => Some((tree, Nil)) - case _ => None + case MaybeTypeTreeOriginal(AppliedTypeTree(tpe, targs)) => Some((tpe, targs)) + case _ if tree.isType => Some((tree, Nil)) + case _ => None } } @@ -241,10 +241,15 @@ trait ReificationSupport { self: SymbolTable => case UnApply(treeInfo.Unapplied(Select(fun, nme.unapply)), pats) => Some((fun, pats :: Nil)) case treeInfo.Applied(fun, targs, argss) => - val callee = - if (fun.isTerm) SyntacticTypeApplied(fun, targs) - else SyntacticAppliedType(fun, targs) - Some((callee, argss)) + fun match { + case Select(_: New, nme.CONSTRUCTOR) => + Some((tree, Nil)) + case _ => + val callee = + if (fun.isTerm) SyntacticTypeApplied(fun, targs) + else SyntacticAppliedType(fun, targs) + Some((callee, argss)) + } } } @@ -510,7 +515,9 @@ trait ReificationSupport { self: SymbolTable => gen.mkNew(parents, mkSelfType(selfType), earlyDefs ::: body, NoPosition, NoPosition) def unapply(tree: Tree): Option[(List[Tree], List[Tree], ValDef, List[Tree])] = tree match { - case SyntacticApplied(Select(New(SyntacticAppliedType(ident, targs)), nme.CONSTRUCTOR), argss) => + case treeInfo.Applied(Select(New(SyntacticAppliedType(ident, targs)), nme.CONSTRUCTOR), Nil, List(Nil)) => + Some((Nil, SyntacticAppliedType(ident, targs) :: Nil, noSelfType, Nil)) + case treeInfo.Applied(Select(New(SyntacticAppliedType(ident, targs)), nme.CONSTRUCTOR), Nil, argss) => Some((Nil, SyntacticApplied(SyntacticAppliedType(ident, targs), argss) :: Nil, noSelfType, Nil)) case SyntacticBlock(SyntacticClassDef(_, tpnme.ANON_CLASS_NAME, Nil, _, ListOfNil, earlyDefs, parents, selfType, body) :: Apply(Select(New(Ident(tpnme.ANON_CLASS_NAME)), nme.CONSTRUCTOR), Nil) :: Nil) => @@ -523,11 +530,21 @@ trait ReificationSupport { self: SymbolTable => object SyntacticDefDef extends SyntacticDefDefExtractor { def apply(mods: Modifiers, name: TermName, tparams: List[Tree], vparamss: List[List[Tree]], tpt: Tree, rhs: Tree): DefDef = { + val tparams0 = mkTparams(tparams) val vparamss0 = mkParam(vparamss, PARAM) - DefDef(mods, name, mkTparams(tparams), vparamss0, tpt, rhs) + val rhs0 = { + if (name != nme.CONSTRUCTOR) rhs + else rhs match { + case Block(_, _) => rhs + case _ => Block(List(rhs), gen.mkSyntheticUnit) + } + } + DefDef(mods, name, tparams0, vparamss0, tpt, rhs0) } def unapply(tree: Tree): Option[(Modifiers, TermName, List[TypeDef], List[List[ValDef]], Tree, Tree)] = tree match { + case DefDef(mods, nme.CONSTRUCTOR, tparams, vparamss, tpt, Block(List(expr), Literal(Constant(())))) => + Some((mods, nme.CONSTRUCTOR, tparams, vparamss, tpt, expr)) case DefDef(mods, name, tparams, vparamss, tpt, rhs) => Some((mods, name, tparams, vparamss, tpt, rhs)) case _ => None @@ -829,10 +846,10 @@ trait ReificationSupport { self: SymbolTable => // drop potential @scala.unchecked annotation protected object MaybeUnchecked { def unapply(tree: Tree): Some[Tree] = tree match { - case Annotated(SyntacticNew(Nil, Apply(ScalaDot(tpnme.unchecked), Nil) :: Nil, noSelfType, Nil), annottee) => + case Annotated(SyntacticNew(Nil, ScalaDot(tpnme.unchecked) :: Nil, noSelfType, Nil), annottee) => Some(annottee) case Typed(annottee, MaybeTypeTreeOriginal( - Annotated(SyntacticNew(Nil, Apply(ScalaDot(tpnme.unchecked), Nil) :: Nil, noSelfType, Nil), _))) => + Annotated(SyntacticNew(Nil, ScalaDot(tpnme.unchecked) :: Nil, noSelfType, Nil), _))) => Some(annottee) case annottee => Some(annottee) } @@ -852,9 +869,25 @@ trait ReificationSupport { self: SymbolTable => object SyntacticPartialFunction extends SyntacticPartialFunctionExtractor { def apply(cases: List[Tree]): Match = Match(EmptyTree, mkCases(cases)) - def unapply(tree: Match): Option[List[CaseDef]] = tree match { + def unapply(tree: Tree): Option[List[CaseDef]] = tree match { case Match(EmptyTree, cases) => Some(cases) - case _ => None + case Typed( + Block( + List(ClassDef(clsMods, tpnme.ANON_FUN_NAME, Nil, Template( + List(abspf: TypeTree, ser: TypeTree), noSelfType, List( + DefDef(_, nme.CONSTRUCTOR, _, _, _, _), + DefDef(_, nme.applyOrElse, _, _, _, + Match(_, cases :+ + CaseDef(Bind(nme.DEFAULT_CASE, Ident(nme.WILDCARD)), _, _))), + DefDef(_, nme.isDefinedAt, _, _, _, _))))), + Apply(Select(New(Ident(tpnme.ANON_FUN_NAME)), termNames.CONSTRUCTOR), List())), + pf: TypeTree) + if pf.tpe != null && pf.tpe.typeSymbol.eq(PartialFunctionClass) && + abspf.tpe != null && abspf.tpe.typeSymbol.eq(AbstractPartialFunctionClass) && + ser.tpe != null && ser.tpe.typeSymbol.eq(SerializableClass) && + clsMods.hasFlag(FINAL) && clsMods.hasFlag(SYNTHETIC) => + Some(cases) + case _ => None } } @@ -875,13 +908,24 @@ trait ReificationSupport { self: SymbolTable => def unapply(tree: Try): Option[(Tree, List[CaseDef], Tree)] = Try.unapply(tree) } - object SyntacticIdent extends SyntacticIdentExtractor { - def apply(name: Name, isBackquoted: Boolean) = { + object SyntacticTermIdent extends SyntacticTermIdentExtractor { + def apply(name: TermName, isBackquoted: Boolean): Ident = { val id = self.Ident(name) if (isBackquoted) id updateAttachment BackquotedIdentifierAttachment id } - def unapply(tree: Ident): Some[(Name, Boolean)] = Some((tree.name, tree.hasAttachment[BackquotedIdentifierAttachment.type])) + def unapply(id: Ident): Option[(TermName, Boolean)] = id.name match { + case name: TermName => Some((name, id.hasAttachment[BackquotedIdentifierAttachment.type])) + case _ => None + } + } + + object SyntacticTypeIdent extends SyntacticTypeIdentExtractor { + def apply(name: TypeName): Ident = self.Ident(name) + def unapply(tree: Tree): Option[TypeName] = tree match { + case MaybeTypeTreeOriginal(Ident(name: TypeName)) => Some(name) + case _ => None + } } /** Facade over Imports and ImportSelectors that lets to structurally @@ -1027,8 +1071,8 @@ trait ReificationSupport { self: SymbolTable => object SyntacticSelectType extends SyntacticSelectTypeExtractor { def apply(qual: Tree, name: TypeName): Select = Select(qual, name) def unapply(tree: Tree): Option[(Tree, TypeName)] = tree match { - case Select(qual, name: TypeName) => Some((qual, name)) - case _ => None + case MaybeTypeTreeOriginal(Select(qual, name: TypeName)) => Some((qual, name)) + case _ => None } } @@ -1039,6 +1083,63 @@ trait ReificationSupport { self: SymbolTable => case _ => None } } + + object SyntacticCompoundType extends SyntacticCompoundTypeExtractor { + def apply(parents: List[Tree], defns: List[Tree]) = + CompoundTypeTree(Template(gen.mkParents(NoMods, parents), noSelfType, defns)) + def unapply(tree: Tree): Option[(List[Tree], List[Tree])] = tree match { + case MaybeTypeTreeOriginal(CompoundTypeTree(Template(parents, _, defns))) => + Some((parents, defns)) + case _ => + None + } + } + + object SyntacticSingletonType extends SyntacitcSingletonTypeExtractor { + def apply(ref: Tree): SingletonTypeTree = SingletonTypeTree(ref) + def unapply(tree: Tree): Option[Tree] = tree match { + case MaybeTypeTreeOriginal(SingletonTypeTree(ref)) => + Some(ref) + case _ => + None + } + } + + object SyntacticTypeProjection extends SyntacticTypeProjectionExtractor { + def apply(qual: Tree, name: TypeName): SelectFromTypeTree = + SelectFromTypeTree(qual, name) + def unapply(tree: Tree): Option[(Tree, TypeName)] = tree match { + case MaybeTypeTreeOriginal(SelectFromTypeTree(qual, name)) => + Some((qual, name)) + case _ => + None + } + } + + object SyntacticAnnotatedType extends SyntacticAnnotatedTypeExtractor { + def apply(tpt: Tree, annot: Tree): Annotated = + Annotated(annot, tpt) + def unapply(tree: Tree): Option[(Tree, Tree)] = tree match { + case MaybeTypeTreeOriginal(Annotated(annot, tpt)) => + Some((tpt, annot)) + case _ => + None + } + } + + object SyntacticExistentialType extends SyntacticExistentialTypeExtractor { + def apply(tpt: Tree, where: List[Tree]): ExistentialTypeTree = + ExistentialTypeTree(tpt, where.map { + case md: MemberDef => md + case tree => throw new IllegalArgumentException("$tree is not legal forSome definition") + }) + def unapply(tree: Tree): Option[(Tree, List[MemberDef])] = tree match { + case MaybeTypeTreeOriginal(ExistentialTypeTree(tpt, where)) => + Some((tpt, where)) + case _ => + None + } + } } val build = new ReificationSupportImpl diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index 10959ff41f..6848c357c5 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -612,37 +612,6 @@ trait StdNames { val SelectFromTypeTree: NameType = "SelectFromTypeTree" val SingleType: NameType = "SingleType" val SuperType: NameType = "SuperType" - val SyntacticApplied: NameType = "SyntacticApplied" - val SyntacticAppliedType: NameType = "SyntacticAppliedType" - val SyntacticAssign: NameType = "SyntacticAssign" - val SyntacticBlock: NameType = "SyntacticBlock" - val SyntacticClassDef: NameType = "SyntacticClassDef" - val SyntacticDefDef: NameType = "SyntacticDefDef" - val SyntacticEmptyTypeTree: NameType = "SyntacticEmptyTypeTree" - val SyntacticFilter: NameType = "SyntacticFilter" - val SyntacticFor: NameType = "SyntacticFor" - val SyntacticForYield: NameType = "SyntacticForYield" - val SyntacticFunction: NameType = "SyntacticFunction" - val SyntacticFunctionType: NameType = "SyntacticFunctionType" - val SyntacticIdent: NameType = "SyntacticIdent" - val SyntacticImport: NameType = "SyntacticImport" - val SyntacticMatch: NameType = "SyntacticMatch" - val SyntacticNew: NameType = "SyntacticNew" - val SyntacticObjectDef: NameType = "SyntacticObjectDef" - val SyntacticPackageObjectDef: NameType = "SyntacticPackageObjectDef" - val SyntacticPartialFunction: NameType = "SyntacticPartialFunction" - val SyntacticPatDef: NameType = "SyntacticPatDef" - val SyntacticSelectType: NameType = "SyntacticSelectType" - val SyntacticSelectTerm: NameType = "SyntacticSelectTerm" - val SyntacticTraitDef: NameType = "SyntacticTraitDef" - val SyntacticTry: NameType = "SyntacticTry" - val SyntacticTuple: NameType = "SyntacticTuple" - val SyntacticTupleType: NameType = "SyntacticTupleType" - val SyntacticTypeApplied: NameType = "SyntacticTypeApplied" - val SyntacticValDef: NameType = "SyntacticValDef" - val SyntacticValEq: NameType = "SyntacticValEq" - val SyntacticValFrom: NameType = "SyntacticValFrom" - val SyntacticVarDef: NameType = "SyntacticVarDef" val This: NameType = "This" val ThisType: NameType = "ThisType" val Tuple2: NameType = "Tuple2" @@ -810,11 +779,50 @@ trait StdNames { val zero: NameType = "zero" // quasiquote interpolators: - val q: NameType = "q" - val tq: NameType = "tq" - val cq: NameType = "cq" - val pq: NameType = "pq" - val fq: NameType = "fq" + val q: NameType = "q" + val tq: NameType = "tq" + val cq: NameType = "cq" + val pq: NameType = "pq" + val fq: NameType = "fq" + + // quasiquote's syntactic combinators + val SyntacticAnnotatedType: NameType = "SyntacticAnnotatedType" + val SyntacticApplied: NameType = "SyntacticApplied" + val SyntacticAppliedType: NameType = "SyntacticAppliedType" + val SyntacticAssign: NameType = "SyntacticAssign" + val SyntacticBlock: NameType = "SyntacticBlock" + val SyntacticClassDef: NameType = "SyntacticClassDef" + val SyntacticCompoundType: NameType = "SyntacticCompoundType" + val SyntacticDefDef: NameType = "SyntacticDefDef" + val SyntacticEmptyTypeTree: NameType = "SyntacticEmptyTypeTree" + val SyntacticExistentialType: NameType = "SyntacticExistentialType" + val SyntacticFilter: NameType = "SyntacticFilter" + val SyntacticFor: NameType = "SyntacticFor" + val SyntacticForYield: NameType = "SyntacticForYield" + val SyntacticFunction: NameType = "SyntacticFunction" + val SyntacticFunctionType: NameType = "SyntacticFunctionType" + val SyntacticImport: NameType = "SyntacticImport" + val SyntacticMatch: NameType = "SyntacticMatch" + val SyntacticNew: NameType = "SyntacticNew" + val SyntacticObjectDef: NameType = "SyntacticObjectDef" + val SyntacticPackageObjectDef: NameType = "SyntacticPackageObjectDef" + val SyntacticPartialFunction: NameType = "SyntacticPartialFunction" + val SyntacticPatDef: NameType = "SyntacticPatDef" + val SyntacticSelectTerm: NameType = "SyntacticSelectTerm" + val SyntacticSelectType: NameType = "SyntacticSelectType" + val SyntacticSingletonType: NameType = "SyntacticSingletonType" + val SyntacticTermIdent: NameType = "SyntacticTermIdent" + val SyntacticTraitDef: NameType = "SyntacticTraitDef" + val SyntacticTry: NameType = "SyntacticTry" + val SyntacticTuple: NameType = "SyntacticTuple" + val SyntacticTupleType: NameType = "SyntacticTupleType" + val SyntacticTypeApplied: NameType = "SyntacticTypeApplied" + val SyntacticTypeIdent: NameType = "SyntacticTypeIdent" + val SyntacticTypeProjection: NameType = "SyntacticTypeProjection" + val SyntacticValDef: NameType = "SyntacticValDef" + val SyntacticValEq: NameType = "SyntacticValEq" + val SyntacticValFrom: NameType = "SyntacticValFrom" + val SyntacticVarDef: NameType = "SyntacticVarDef" // unencoded operators object raw { diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala index a96bed4696..ce0eadc04f 100644 --- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala @@ -402,7 +402,13 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) private val crashRecovery: PartialFunction[Throwable, Boolean] = { case ex: Throwable => - echo(intp.global.throwableAsString(ex)) + val (err, explain) = ( + if (intp.isInitializeComplete) + (intp.global.throwableAsString(ex), "") + else + (ex.getMessage, "The compiler did not initialize.\n") + ) + echo(err) ex match { case _: NoSuchMethodError | _: NoClassDefFoundError => @@ -410,7 +416,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) throw ex case _ => def fn(): Boolean = - try in.readYesOrNo(replayQuestionMessage, { echo("\nYou must enter y or n.") ; fn() }) + try in.readYesOrNo(explain + replayQuestionMessage, { echo("\nYou must enter y or n.") ; fn() }) catch { case _: RuntimeException => false } if (fn()) replay() diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala index 9c853fb514..47d97dd4dd 100644 --- a/src/repl/scala/tools/nsc/interpreter/IMain.scala +++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala @@ -117,8 +117,10 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set private def _initSources = List(new BatchSourceFile("<init>", "class $repl_$init { }")) private def _initialize() = { try { - // todo. if this crashes, REPL will hang - new _compiler.Run() compileSources _initSources + // if this crashes, REPL will hang its head in shame + val run = new _compiler.Run() + assert(run.typerPhase != NoPhase, "REPL requires a typer phase.") + run compileSources _initSources _initializeComplete = true true } @@ -384,6 +386,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set def compileSourcesKeepingRun(sources: SourceFile*) = { val run = new Run() + assert(run.typerPhase != NoPhase, "REPL requires a typer phase.") reporter.reset() run compileSources sources.toList (!reporter.hasErrors, run) diff --git a/src/repl/scala/tools/nsc/interpreter/ReplGlobal.scala b/src/repl/scala/tools/nsc/interpreter/ReplGlobal.scala index 51fab3082e..07d619bca5 100644 --- a/src/repl/scala/tools/nsc/interpreter/ReplGlobal.scala +++ b/src/repl/scala/tools/nsc/interpreter/ReplGlobal.scala @@ -55,6 +55,8 @@ trait ReplGlobal extends Global { // newNamer(rootContext(unit)).enterSym(unit.body) } } + // add to initial or terminal phase to sanity check Run at construction + override val requires = List("typer") // ensure they didn't -Ystop-after:parser } override protected def computePhaseDescriptors: List[SubComponent] = { |