Skip to content

Commit

Permalink
Represent tq"" as SyntacticEmptyTypeTree rather than TypeTree()
Browse files Browse the repository at this point in the history
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")
  • Loading branch information
densh committed Feb 7, 2014
1 parent d60b832 commit 1e5654c
Show file tree
Hide file tree
Showing 7 changed files with 30 additions and 4 deletions.
2 changes: 2 additions & 0 deletions src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
Expand Up @@ -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) =>
Expand Down
7 changes: 7 additions & 0 deletions src/reflect/scala/reflect/api/BuildUtils.scala
Expand Up @@ -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

Expand Down
7 changes: 5 additions & 2 deletions src/reflect/scala/reflect/internal/BuildUtils.scala
Expand Up @@ -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
}

Expand Down
1 change: 1 addition & 0 deletions src/reflect/scala/reflect/internal/StdNames.scala
Expand Up @@ -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"
Expand Down
Expand Up @@ -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)
}
Expand Down
Expand Up @@ -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]}"
}
}
9 changes: 8 additions & 1 deletion test/files/scalacheck/quasiquotes/TypecheckedProps.scala
Expand Up @@ -75,4 +75,11 @@ object TypecheckedProps extends QuasiquoteProperties("typechecked") {
assert(f.original ≈ pq"Test.this.Cell")
assert(args ≈ List(pq"v"))
}
}

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
}
}

0 comments on commit 1e5654c

Please sign in to comment.