From d60b8323dda884653f31410806c269d15140e5e6 Mon Sep 17 00:00:00 2001 From: Denys Shabalin Date: Thu, 6 Feb 2014 16:13:36 +0100 Subject: Rename EmptyTypTree into SyntacticEmptyTypeTree 1. Change the name as Eugene believes previous name was misleading 2. Remove EmptyTree case as it's not needed any longer --- src/reflect/scala/reflect/internal/BuildUtils.scala | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala index 6106339324..b586297fcb 100644 --- a/src/reflect/scala/reflect/internal/BuildUtils.scala +++ b/src/reflect/scala/reflect/internal/BuildUtils.scala @@ -537,13 +537,9 @@ trait BuildUtils { self: SymbolTable => def unapply(tree: Tree): Option[Tree] = gen.Filter.unapply(tree) } - // abstract over possible alternative representations of no type in valdef - protected object EmptyTypTree { - def unapply(tree: Tree): Boolean = tree match { - case EmptyTree => true - case tt: TypeTree if (tt.original == null || tt.original.isEmpty) => true - case _ => false - } + // a type tree which wasn't specified by the user but might have been inferred by compiler + object SyntacticEmptyTypeTree { + def unapply(tt: TypeTree): Boolean = tt.original == null || tt.original.isEmpty } // match a sequence of desugared `val $pat = $value` @@ -561,8 +557,8 @@ trait BuildUtils { self: SymbolTable => case ValDef(_, name1, _, Match(MaybeUnchecked(value), CaseDef(pat, EmptyTree, Ident(name2)) :: Nil)) :: UnPatSeq(rest) if name1 == name2 => Some((pat, value) :: rest) - // case q"${_} val $name: ${EmptyTypTree()} = $value" :: UnPatSeq(rest) => - case ValDef(_, name, EmptyTypTree(), value) :: UnPatSeq(rest) => + // case q"${_} val $name: ${SyntacticEmptyTypeTree()} = $value" :: UnPatSeq(rest) => + case ValDef(_, name, SyntacticEmptyTypeTree(), value) :: UnPatSeq(rest) => Some((Bind(name, self.Ident(nme.WILDCARD)), value) :: rest) // case q"${_} val $name: $tpt = $value" :: UnPatSeq(rest) => case ValDef(_, name, tpt, value) :: UnPatSeq(rest) => @@ -604,8 +600,8 @@ trait BuildUtils { self: SymbolTable => def unapply(tree: Tree): Option[(Tree, Tree)] = tree match { case Function(ValDef(Modifiers(PARAM, _, _), name, tpt, EmptyTree) :: Nil, body) => tpt match { - case EmptyTypTree() => Some((Bind(name, self.Ident(nme.WILDCARD)), body)) - case _ => Some((Bind(name, Typed(self.Ident(nme.WILDCARD), tpt)), body)) + case SyntacticEmptyTypeTree() => Some((Bind(name, self.Ident(nme.WILDCARD)), body)) + case _ => Some((Bind(name, Typed(self.Ident(nme.WILDCARD), tpt)), body)) } case UnVisitor(_, CaseDef(pat, EmptyTree, body) :: Nil) => Some((pat, body)) -- cgit v1.2.3 From 1e5654c8bd10a3649ccc97c42a7949b179480073 Mon Sep 17 00:00:00 2001 From: Denys Shabalin Date: Thu, 6 Feb 2014 19:51:43 +0100 Subject: Represent tq"" as SyntacticEmptyTypeTree rather than TypeTree() Such representation codifies the fact that type tree that doesn't have embedded syntactic equivalent must have been inferred or otherwise provided by the compiler rather than specified by the end user. Additionally it also ensures that we can still match trees without explicit types (e.g. vals without type) after typechecking. Otherwise the same quote couldn't be used in situations like: val q"val x = 42" = typecheck(q"val x = 42") --- src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala | 2 ++ src/reflect/scala/reflect/api/BuildUtils.scala | 7 +++++++ src/reflect/scala/reflect/internal/BuildUtils.scala | 7 +++++-- src/reflect/scala/reflect/internal/StdNames.scala | 1 + test/files/scalacheck/quasiquotes/TypeConstructionProps.scala | 2 +- test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala | 6 ++++++ test/files/scalacheck/quasiquotes/TypecheckedProps.scala | 9 ++++++++- 7 files changed, 30 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala index 0c73214745..2eb50d5993 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala @@ -190,6 +190,8 @@ trait Reifiers { self: Quasiquotes => reifyBuildCall(nme.SyntacticFunction, args, body) case SyntacticIdent(name, isBackquoted) => reifyBuildCall(nme.SyntacticIdent, name, isBackquoted) + case SyntacticEmptyTypeTree() => + reifyBuildCall(nme.SyntacticEmptyTypeTree) case Q(Placeholder(Hole(tree, DotDot))) => mirrorBuildCall(nme.SyntacticBlock, tree) case Q(other) => diff --git a/src/reflect/scala/reflect/api/BuildUtils.scala b/src/reflect/scala/reflect/api/BuildUtils.scala index 3bcf751ace..7aaa3973b3 100644 --- a/src/reflect/scala/reflect/api/BuildUtils.scala +++ b/src/reflect/scala/reflect/api/BuildUtils.scala @@ -248,6 +248,13 @@ private[reflect] trait BuildUtils { self: Universe => def unapply(tree: Tree): Option[(Tree)] } + val SyntacticEmptyTypeTree: SyntacticEmptyTypeTreeExtractor + + trait SyntacticEmptyTypeTreeExtractor { + def apply(): TypeTree + def unapply(tt: TypeTree): Boolean + } + val SyntacticFor: SyntacticForExtractor val SyntacticForYield: SyntacticForExtractor diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala index b586297fcb..4f4d7df793 100644 --- a/src/reflect/scala/reflect/internal/BuildUtils.scala +++ b/src/reflect/scala/reflect/internal/BuildUtils.scala @@ -537,8 +537,11 @@ trait BuildUtils { self: SymbolTable => def unapply(tree: Tree): Option[Tree] = gen.Filter.unapply(tree) } - // a type tree which wasn't specified by the user but might have been inferred by compiler - object SyntacticEmptyTypeTree { + // TypeTree without original is used to signal that no type was provided + // by the user and compiler should infer it instead. (Note: EmptyTree is + // not appropriate in such role, it's only used for terms, not types.) + object SyntacticEmptyTypeTree extends SyntacticEmptyTypeTreeExtractor { + def apply(): TypeTree = self.TypeTree() def unapply(tt: TypeTree): Boolean = tt.original == null || tt.original.isEmpty } diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index 53475be479..7c979e7bdc 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -602,6 +602,7 @@ trait StdNames { 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" diff --git a/test/files/scalacheck/quasiquotes/TypeConstructionProps.scala b/test/files/scalacheck/quasiquotes/TypeConstructionProps.scala index 0984032084..78b54a4e49 100644 --- a/test/files/scalacheck/quasiquotes/TypeConstructionProps.scala +++ b/test/files/scalacheck/quasiquotes/TypeConstructionProps.scala @@ -30,7 +30,7 @@ object TypeConstructionProps extends QuasiquoteProperties("type construction") } property("empty tq") = test { - val tt: TypeTree = tq" " + val tt: TypeTree = tq"" assert(tt.tpe == null) assert(tt.original == null) } diff --git a/test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala b/test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala index 44f110a3d5..0fdcc19052 100644 --- a/test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala +++ b/test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala @@ -52,4 +52,10 @@ object TypeDeconstructionProps extends QuasiquoteProperties("type deconstruction assert(arglast ≈ tq"C") assert(restpe ≈ tq"D") } + + property("match empty type tree") = test { + val tq"" = TypeTree() + // matches because type tree isn't syntactic without original + val tq"" = tq"${typeOf[Int]}" + } } diff --git a/test/files/scalacheck/quasiquotes/TypecheckedProps.scala b/test/files/scalacheck/quasiquotes/TypecheckedProps.scala index 2f501435e3..3afb47952c 100644 --- a/test/files/scalacheck/quasiquotes/TypecheckedProps.scala +++ b/test/files/scalacheck/quasiquotes/TypecheckedProps.scala @@ -75,4 +75,11 @@ object TypecheckedProps extends QuasiquoteProperties("typechecked") { assert(f.original ≈ pq"Test.this.Cell") assert(args ≈ List(pq"v")) } -} \ No newline at end of file + + property("extract inferred val type") = test { + val typechecked = typecheck(q"val x = 42") + val q"val x = 42" = typechecked + val q"val x: ${tq""} = 42" = typechecked + val q"val x: ${t: Type} = 42" = typechecked + } +} -- cgit v1.2.3 From a98eee51760c4961a5419747d2828d9765a9754b Mon Sep 17 00:00:00 2001 From: Denys Shabalin Date: Fri, 7 Feb 2014 14:43:01 +0100 Subject: Better comment for SyntacticEmptyTypeTree --- src/reflect/scala/reflect/internal/BuildUtils.scala | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala index 4f4d7df793..458c10e69b 100644 --- a/src/reflect/scala/reflect/internal/BuildUtils.scala +++ b/src/reflect/scala/reflect/internal/BuildUtils.scala @@ -537,9 +537,12 @@ trait BuildUtils { self: SymbolTable => def unapply(tree: Tree): Option[Tree] = gen.Filter.unapply(tree) } - // TypeTree without original is used to signal that no type was provided - // by the user and compiler should infer it instead. (Note: EmptyTree is - // not appropriate in such role, it's only used for terms, not types.) + // If a tree in type position isn't provided by the user (e.g. `tpt` fields of + // `ValDef` and `DefDef`, function params etc), then it's going to be parsed as + // TypeTree with empty original and empty tpe. This extractor matches such trees + // so that one can write q"val x = 2" to match typecheck(q"val x = 2"). Note that + // TypeTree() is the only possible representation for empty trees in type positions. + // We used to sometimes receive EmptyTree in such cases, but not anymore. object SyntacticEmptyTypeTree extends SyntacticEmptyTypeTreeExtractor { def apply(): TypeTree = self.TypeTree() def unapply(tt: TypeTree): Boolean = tt.original == null || tt.original.isEmpty -- cgit v1.2.3