diff options
14 files changed, 30 insertions, 21 deletions
diff --git a/src/compiler/scala/reflect/macros/contexts/Enclosures.scala b/src/compiler/scala/reflect/macros/contexts/Enclosures.scala index 0b4aad85a3..5e931817b5 100644 --- a/src/compiler/scala/reflect/macros/contexts/Enclosures.scala +++ b/src/compiler/scala/reflect/macros/contexts/Enclosures.scala @@ -18,7 +18,6 @@ trait Enclosures { // vals are eager to simplify debugging // after all we wouldn't save that much time by making them lazy val macroApplication: Tree = expandee - val enclosingOwner = site.owner def enclosingPackage: PackageDef = strictEnclosure[PackageDef] val enclosingClass: Tree = lenientEnclosure[ImplDef] def enclosingImpl: ImplDef = strictEnclosure[ImplDef] diff --git a/src/compiler/scala/reflect/macros/contexts/Internals.scala b/src/compiler/scala/reflect/macros/contexts/Internals.scala index e35a8ae034..cca6d957da 100644 --- a/src/compiler/scala/reflect/macros/contexts/Internals.scala +++ b/src/compiler/scala/reflect/macros/contexts/Internals.scala @@ -7,6 +7,8 @@ trait Internals extends scala.tools.nsc.transform.TypingTransformers { import global._ lazy val internal: ContextInternalApi = new global.SymbolTableInternal with ContextInternalApi { + val enclosingOwner = callsiteTyper.context.owner + class HofTransformer(hof: (Tree, TransformApi) => Tree) extends Transformer { val api = new TransformApi { def recur(tree: Tree): Tree = hof(tree, this) diff --git a/src/compiler/scala/reflect/macros/contexts/Typers.scala b/src/compiler/scala/reflect/macros/contexts/Typers.scala index 0c3881fdcf..f1620b764b 100644 --- a/src/compiler/scala/reflect/macros/contexts/Typers.scala +++ b/src/compiler/scala/reflect/macros/contexts/Typers.scala @@ -12,6 +12,7 @@ trait Typers { val TypecheckMode = scala.reflect.internal.Mode val TERMmode = TypecheckMode.EXPRmode val TYPEmode = TypecheckMode.TYPEmode | TypecheckMode.FUNmode + val PATTERNmode = TypecheckMode.PATTERNmode /** * @see [[scala.tools.reflect.ToolBox.typeCheck]] diff --git a/src/compiler/scala/tools/reflect/ToolBox.scala b/src/compiler/scala/tools/reflect/ToolBox.scala index f47db49718..dfe53be6c9 100644 --- a/src/compiler/scala/tools/reflect/ToolBox.scala +++ b/src/compiler/scala/tools/reflect/ToolBox.scala @@ -23,7 +23,7 @@ trait ToolBox[U <: scala.reflect.api.Universe] { /** Represents mode of operations of the typechecker underlying `c.typecheck` calls. * Is necessary since the shape of the typechecked tree alone is not enough to guess how it should be typechecked. - * Can be EXPRmode (typecheck as a term) or TYPEmode (typecheck as a type). + * Can be EXPRmode (typecheck as a term), TYPEmode (typecheck as a type) or PATTERNmode (typecheck as a pattern). */ type TypecheckMode @@ -36,6 +36,10 @@ trait ToolBox[U <: scala.reflect.api.Universe] { */ val TYPEmode: TypecheckMode + /** Indicates that an argument to `c.typecheck` should be typechecked as a pattern. + */ + val PATTERNmode: TypecheckMode + /** @see `Typers.typecheck` */ @deprecated("Use `tb.typecheck` instead", "2.11.0") diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala index 3cae6fa8a8..3a40b44c74 100644 --- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala +++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala @@ -365,6 +365,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => val TypecheckMode = scala.reflect.internal.Mode val TERMmode = TypecheckMode.EXPRmode val TYPEmode = TypecheckMode.TYPEmode | TypecheckMode.FUNmode + val PATTERNmode = TypecheckMode.PATTERNmode def typecheck(tree: u.Tree, mode: TypecheckMode = TERMmode, expectedType: u.Type, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): u.Tree = withCompilerApi { compilerApi => import compilerApi._ diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala b/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala index f50d699e22..29df0ae670 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Placeholders.scala @@ -42,7 +42,7 @@ trait Placeholders { self: Quasiquotes => case nme.apply => args case nme.unapply => val (dummy @ Ident(nme.SELECTOR_DUMMY)) :: Nil = args - internal.subpatterns(dummy) + internal.subpatterns(dummy).get case _ => global.abort("unreachable") } diff --git a/src/reflect/scala/reflect/api/FlagSets.scala b/src/reflect/scala/reflect/api/FlagSets.scala index f36056cc3b..3d438e5b2f 100644 --- a/src/reflect/scala/reflect/api/FlagSets.scala +++ b/src/reflect/scala/reflect/api/FlagSets.scala @@ -176,9 +176,8 @@ trait FlagSets { self: Universe => val ENUM: FlagSet /** Flag indicating that tree represents a parameter of the primary constructor of some class - * or a synthetic member underlying thereof: + * or a synthetic member underlying thereof. E.g. here's how 'class C(val x: Int)' is represented: * - * 13:57 ~$ parse 'class C(val x: Int)' * [[syntax trees at end of parser]]// Scala source: tmposDU52 * class C extends scala.AnyRef { * <paramaccessor> val x: Int = _; @@ -202,9 +201,8 @@ trait FlagSets { self: Universe => val PARAMACCESSOR: FlagSet /** Flag indicating that tree represents a parameter of the primary constructor of some case class - * or a synthetic member underlying thereof: + * or a synthetic member underlying thereof. E.g. here's how 'case class C(val x: Int)' is represented: * - * 13:58 ~$ parse 'case class C(val x: Int)' * [[syntax trees at end of parser]]// Scala source: tmpnHkJ3y * case class C extends scala.Product with scala.Serializable { * <caseaccessor> <paramaccessor> val x: Int = _; diff --git a/src/reflect/scala/reflect/internal/Internals.scala b/src/reflect/scala/reflect/internal/Internals.scala index a152787ae1..ad0bcef48d 100644 --- a/src/reflect/scala/reflect/internal/Internals.scala +++ b/src/reflect/scala/reflect/internal/Internals.scala @@ -122,7 +122,7 @@ trait Internals extends api.Internals { def typeBounds(lo: Type, hi: Type): TypeBounds = self.TypeBounds(lo, hi) def boundedWildcardType(bounds: TypeBounds): BoundedWildcardType = self.BoundedWildcardType(bounds) - def subpatterns(tree: Tree): List[Tree] = tree.attachments.get[SubpatternsAttachment].get.patterns + def subpatterns(tree: Tree): Option[List[Tree]] = tree.attachments.get[SubpatternsAttachment].map(_.patterns.map(_.duplicate)) } lazy val treeBuild = new self.TreeGen { diff --git a/src/reflect/scala/reflect/macros/Enclosures.scala b/src/reflect/scala/reflect/macros/Enclosures.scala index 7c186139cf..69ede42cc7 100644 --- a/src/reflect/scala/reflect/macros/Enclosures.scala +++ b/src/reflect/scala/reflect/macros/Enclosures.scala @@ -20,7 +20,7 @@ import scala.language.existentials // SI-6541 * This is somewhat aligned with the overall evolution of macros during the 2.11 development cycle, where we played with * `c.introduceTopLevel` and `c.introduceMember`, but at the end of the day decided to reject them. * - * If you're relying on the now deprecated APIs, consider using the new [[c.enclosingOwner]] method that can be used to obtain + * If you're relying on the now deprecated APIs, consider using the new [[c.internal.enclosingOwner]] method that can be used to obtain * the names of enclosing definitions. Alternatively try reformulating your macros in terms of completely local expansion * and/or joining a discussion of a somewhat related potential language feature at [[https://groups.google.com/forum/#!topic/scala-debate/f4CLmYShX6Q]]. * We also welcome questions and suggestions on our mailing lists, where we would be happy to further discuss this matter. @@ -52,11 +52,6 @@ trait Enclosures { */ def enclosingPosition: Position - /** Symbol associated with the innermost enclosing lexical context. - * Walking the owner chain of this symbol will reveal information about more and more enclosing contexts. - */ - def enclosingOwner: Symbol - /** Tree that corresponds to the enclosing method, or EmptyTree if not applicable. * @see [[scala.reflect.macros.Enclosures]] */ diff --git a/src/reflect/scala/reflect/macros/Internals.scala b/src/reflect/scala/reflect/macros/Internals.scala index 415e70c36e..843644b7e3 100644 --- a/src/reflect/scala/reflect/macros/Internals.scala +++ b/src/reflect/scala/reflect/macros/Internals.scala @@ -14,6 +14,11 @@ trait Internals { /** @see [[scala.reflect.api.Internals]] */ trait ContextInternalApi extends universe.MacroInternalApi { + /** Symbol associated with the innermost enclosing lexical context. + * Walking the owner chain of this symbol will reveal information about more and more enclosing contexts. + */ + def enclosingOwner: Symbol + /** Functions that are available during [[transform]]. * @see [[transform]] */ diff --git a/src/reflect/scala/reflect/macros/Typers.scala b/src/reflect/scala/reflect/macros/Typers.scala index f1d8575774..d0dccb469d 100644 --- a/src/reflect/scala/reflect/macros/Typers.scala +++ b/src/reflect/scala/reflect/macros/Typers.scala @@ -27,7 +27,7 @@ trait Typers { /** Represents mode of operations of the typechecker underlying `c.typecheck` calls. * Is necessary since the shape of the typechecked tree alone is not enough to guess how it should be typechecked. - * Can be EXPRmode (typecheck as a term) or TYPEmode (typecheck as a type). + * Can be EXPRmode (typecheck as a term), TYPEmode (typecheck as a type) or PATTERNmode (typecheck as a pattern). */ // I'd very much like to make use of https://github.com/dsl-paradise/dsl-paradise here! type TypecheckMode @@ -41,6 +41,10 @@ trait Typers { */ val TYPEmode: TypecheckMode + /** Indicates that an argument to `c.typecheck` should be typechecked as a pattern. + */ + val PATTERNmode: TypecheckMode + /** @see `scala.reflect.macros.TypecheckException` */ type TypecheckException = scala.reflect.macros.TypecheckException diff --git a/src/reflect/scala/reflect/macros/Universe.scala b/src/reflect/scala/reflect/macros/Universe.scala index 23cd23cdb0..2dfb4ee0e2 100644 --- a/src/reflect/scala/reflect/macros/Universe.scala +++ b/src/reflect/scala/reflect/macros/Universe.scala @@ -138,7 +138,7 @@ abstract class Universe extends scala.reflect.api.Universe { /** Retrieves the untyped list of subpatterns attached to selector dummy of an UnApply node. * Useful in writing quasiquoting macros that do pattern matching. */ - def subpatterns(tree: Tree): List[Tree] + def subpatterns(tree: Tree): Option[List[Tree]] } /** @group Internal */ diff --git a/test/files/run/macro-enclosures/Impls_Macros_1.scala b/test/files/run/macro-enclosures/Impls_Macros_1.scala index a0f66a6b98..564cdfa68f 100644 --- a/test/files/run/macro-enclosures/Impls_Macros_1.scala +++ b/test/files/run/macro-enclosures/Impls_Macros_1.scala @@ -14,8 +14,8 @@ object Macros { println("enclosingTemplate = " + ${c.enclosingTemplate.toString}) println("enclosingMethod = " + ${c.enclosingMethod.toString}) println("enclosingDef = " + ${c.enclosingDef.toString}) - println("enclosingOwner = " + ${c.enclosingOwner.toString}) - println("enclosingOwnerChain = " + ${chain(c.enclosingOwner).toString}) + println("enclosingOwner = " + ${c.internal.enclosingOwner.toString}) + println("enclosingOwnerChain = " + ${chain(c.internal.enclosingOwner).toString}) """ } diff --git a/test/files/run/macro-subpatterns.check b/test/files/run/macro-subpatterns.check index b34d4bf4a1..4997146cf2 100644 --- a/test/files/run/macro-subpatterns.check +++ b/test/files/run/macro-subpatterns.check @@ -1,3 +1,3 @@ -List((a @ Extractor((b @ Extractor((c @ _)))))) -List((b @ Extractor((c @ _)))) -List((c @ _)) +Some(List((a @ Extractor((b @ Extractor((c @ _))))))) +Some(List((b @ Extractor((c @ _))))) +Some(List((c @ _))) |