summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@typesafe.com>2014-03-10 11:03:04 -0700
committerAdriaan Moors <adriaan.moors@typesafe.com>2014-03-10 11:03:04 -0700
commit51a413e3327d9050f07377933eb1ca243d52c4ab (patch)
tree433351fea6467957114c8dd9143c6796c2f8b6a8
parent1c7daf40bfe529969aa423ae0d2fd454adb20acb (diff)
parent1b5a34b402cb283db6029a1d54778390ba14ef6f (diff)
downloadscala-51a413e3327d9050f07377933eb1ca243d52c4ab.tar.gz
scala-51a413e3327d9050f07377933eb1ca243d52c4ab.tar.bz2
scala-51a413e3327d9050f07377933eb1ca243d52c4ab.zip
Merge pull request #3594 from densh/si/8331
SI-8331 make sure type select & applied type doesn't match terms
-rw-r--r--bincompat-backward.whitelist.conf25
-rw-r--r--bincompat-forward.whitelist.conf31
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala5
-rw-r--r--src/reflect/scala/reflect/api/Internals.scala15
-rw-r--r--src/reflect/scala/reflect/internal/ReificationSupport.scala53
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala3
-rw-r--r--test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala12
-rw-r--r--test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala12
8 files changed, 144 insertions, 12 deletions
diff --git a/bincompat-backward.whitelist.conf b/bincompat-backward.whitelist.conf
index 10c1da59b8..e82c0fd16d 100644
--- a/bincompat-backward.whitelist.conf
+++ b/bincompat-backward.whitelist.conf
@@ -4,8 +4,8 @@ filter {
# "scala.concurrent.impl"
# "scala.reflect.runtime"
]
- // see SI-8372
problems=[
+ // see SI-8372
{
matchName="scala.collection.mutable.ArrayOps#ofChar.unzip"
problemName=IncompatibleMethTypeProblem
@@ -101,6 +101,27 @@ filter {
{
matchName="scala.collection.mutable.ArrayOps#ofDouble.unzip3"
problemName=IncompatibleMethTypeProblem
+ },
+ // see SI-8331
+ {
+ matchName="scala.reflect.api.Internals#ReificationSupportApi#SyntacticTypeAppliedExtractor.unapply"
+ problemName=IncompatibleResultTypeProblem
+ },
+ {
+ matchName="scala.reflect.api.Internals#ReificationSupportApi#SyntacticTypeAppliedExtractor.unapply"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticSelectType"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticAppliedType"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticSelectTerm"
+ problemName=MissingMethodProblem
}
]
-} \ No newline at end of file
+}
diff --git a/bincompat-forward.whitelist.conf b/bincompat-forward.whitelist.conf
index 96994f8969..f9bd0441a2 100644
--- a/bincompat-forward.whitelist.conf
+++ b/bincompat-forward.whitelist.conf
@@ -4,8 +4,8 @@ filter {
# "scala.concurrent.impl"
# "scala.reflect.runtime"
]
- // see SI-8372
problems=[
+ // see SI-8372
{
matchName="scala.collection.mutable.ArrayOps#ofChar.unzip"
problemName=IncompatibleMethTypeProblem
@@ -101,6 +101,35 @@ filter {
{
matchName="scala.collection.mutable.ArrayOps#ofDouble.unzip3"
problemName=IncompatibleMethTypeProblem
+ },
+ // see SI-8331
+ {
+ matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticSelectType"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticAppliedType"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticSelectTerm"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Internals$ReificationSupportApi$SyntacticSelectTermExtractor"
+ problemName=MissingClassProblem
+ },
+ {
+ matchName="scala.reflect.api.Internals#ReificationSupportApi#SyntacticTypeAppliedExtractor.unapply"
+ problemName=IncompatibleResultTypeProblem
+ },
+ {
+ matchName="scala.reflect.api.Internals#ReificationSupportApi#SyntacticTypeAppliedExtractor.unapply"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Internals$ReificationSupportApi$SyntacticSelectTypeExtractor"
+ problemName=MissingClassProblem
}
]
}
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
index 5eae3b6e6f..c37d5a3273 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
@@ -185,6 +185,8 @@ trait Reifiers { self: Quasiquotes =>
reifyBuildCall(nme.SyntacticApplied, fun, argss)
case SyntacticTypeApplied(fun, targs) if targs.nonEmpty =>
reifyBuildCall(nme.SyntacticTypeApplied, fun, targs)
+ case SyntacticAppliedType(tpt, targs) if targs.nonEmpty =>
+ reifyBuildCall(nme.SyntacticAppliedType, tpt, targs)
case SyntacticFunction(args, body) =>
reifyBuildCall(nme.SyntacticFunction, args, body)
case SyntacticIdent(name, isBackquoted) =>
@@ -215,6 +217,9 @@ trait Reifiers { self: Quasiquotes =>
// correctness of the trees produced by quasiquotes
case Select(id @ Ident(nme.scala_), name) if id.symbol == ScalaPackage =>
reifyBuildCall(nme.ScalaDot, name)
+ case Select(qual, name) =>
+ val ctor = if (name.isTypeName) nme.SyntacticSelectType else nme.SyntacticSelectTerm
+ reifyBuildCall(ctor, qual, name)
case _ =>
super.reifyTreeSyntactically(tree)
}
diff --git a/src/reflect/scala/reflect/api/Internals.scala b/src/reflect/scala/reflect/api/Internals.scala
index 01f928ed61..d2e742726d 100644
--- a/src/reflect/scala/reflect/api/Internals.scala
+++ b/src/reflect/scala/reflect/api/Internals.scala
@@ -600,10 +600,11 @@ trait Internals { self: Universe =>
}
val SyntacticTypeApplied: SyntacticTypeAppliedExtractor
+ val SyntacticAppliedType: SyntacticTypeAppliedExtractor
trait SyntacticTypeAppliedExtractor {
def apply(tree: Tree, targs: List[Tree]): Tree
- def unapply(tree: Tree): Some[(Tree, List[Tree])]
+ def unapply(tree: Tree): Option[(Tree, List[Tree])]
}
val SyntacticApplied: SyntacticAppliedExtractor
@@ -784,6 +785,18 @@ trait Internals { self: Universe =>
def apply(expr: Tree, selectors: List[Tree]): Import
def unapply(imp: Import): Some[(Tree, List[Tree])]
}
+
+ val SyntacticSelectType: SyntacticSelectTypeExtractor
+ trait SyntacticSelectTypeExtractor {
+ def apply(qual: Tree, name: TypeName): Select
+ def unapply(tree: Tree): Option[(Tree, TypeName)]
+ }
+
+ val SyntacticSelectTerm: SyntacticSelectTermExtractor
+ trait SyntacticSelectTermExtractor {
+ def apply(qual: Tree, name: TermName): Select
+ def unapply(tree: Tree): Option[(Tree, TermName)]
+ }
}
@deprecated("Use `internal.reificationSupport` instead", "2.11.0")
diff --git a/src/reflect/scala/reflect/internal/ReificationSupport.scala b/src/reflect/scala/reflect/internal/ReificationSupport.scala
index 66ac4bc751..dfe1811ff0 100644
--- a/src/reflect/scala/reflect/internal/ReificationSupport.scala
+++ b/src/reflect/scala/reflect/internal/ReificationSupport.scala
@@ -101,7 +101,7 @@ trait ReificationSupport { self: SymbolTable =>
}
def mkAnnotation(tree: Tree): Tree = tree match {
- case SyntacticNew(Nil, SyntacticApplied(SyntacticTypeApplied(_, _), _) :: Nil, noSelfType, Nil) =>
+ case SyntacticNew(Nil, SyntacticApplied(SyntacticAppliedType(_, _), _) :: Nil, noSelfType, Nil) =>
tree
case _ =>
throw new IllegalArgumentException(s"Tree ${showRaw(tree)} isn't a correct representation of annotation." +
@@ -201,17 +201,35 @@ trait ReificationSupport { self: SymbolTable =>
def unapply(flags: Long): Some[Long] = Some(flags)
}
+ /** Construct/deconstruct type application term trees.
+ * Treats other term trees as zero-argument type applications.
+ */
object SyntacticTypeApplied extends SyntacticTypeAppliedExtractor {
def apply(tree: Tree, targs: List[Tree]): Tree =
if (targs.isEmpty) tree
else if (tree.isTerm) TypeApply(tree, targs)
- else if (tree.isType) AppliedTypeTree(tree, targs)
- else throw new IllegalArgumentException(s"can't apply types to $tree")
+ else throw new IllegalArgumentException(s"can't apply type arguments to $tree")
- def unapply(tree: Tree): Some[(Tree, List[Tree])] = tree match {
+ def unapply(tree: Tree): Option[(Tree, List[Tree])] = tree match {
case TypeApply(fun, targs) => Some((fun, targs))
+ case _ if tree.isTerm => Some((tree, Nil))
+ case _ => None
+ }
+ }
+
+ /** Construct/deconstruct applied type trees.
+ * Treats other types as zero-arity applied types.
+ */
+ object SyntacticAppliedType extends SyntacticTypeAppliedExtractor {
+ def apply(tree: Tree, targs: List[Tree]): Tree =
+ if (targs.isEmpty) tree
+ else if (tree.isType) AppliedTypeTree(tree, targs)
+ 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 _ => Some((tree, Nil))
+ case _ if tree.isType => Some((tree, Nil))
+ case _ => None
}
}
@@ -223,7 +241,10 @@ trait ReificationSupport { self: SymbolTable =>
case UnApply(treeInfo.Unapplied(Select(fun, nme.unapply)), pats) =>
Some((fun, pats :: Nil))
case treeInfo.Applied(fun, targs, argss) =>
- Some((SyntacticTypeApplied(fun, targs), argss))
+ val callee =
+ if (fun.isTerm) SyntacticTypeApplied(fun, targs)
+ else SyntacticAppliedType(fun, targs)
+ Some((callee, argss))
}
}
@@ -489,8 +510,8 @@ 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(SyntacticTypeApplied(ident, targs)), nme.CONSTRUCTOR), argss) =>
- Some((Nil, SyntacticApplied(SyntacticTypeApplied(ident, targs), argss) :: Nil, noSelfType, Nil))
+ case SyntacticApplied(Select(New(SyntacticAppliedType(ident, targs)), nme.CONSTRUCTOR), 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) =>
Some((earlyDefs, parents, selfType, body))
@@ -987,6 +1008,22 @@ trait ReificationSupport { self: SymbolTable =>
Some((imp.expr, selectors))
}
}
+
+ 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
+ }
+ }
+
+ object SyntacticSelectTerm extends SyntacticSelectTermExtractor {
+ def apply(qual: Tree, name: TermName): Select = Select(qual, name)
+ def unapply(tree: Tree): Option[(Tree, TermName)] = tree match {
+ case Select(qual, name: TermName) => Some((qual, name))
+ 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 339923a061..640e0606c7 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -613,6 +613,7 @@ trait StdNames {
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"
@@ -630,6 +631,8 @@ trait StdNames {
val SyntacticObjectDef: NameType = "SyntacticObjectDef"
val SyntacticPackageObjectDef: NameType = "SyntacticPackageObjectDef"
val SyntacticPatDef: NameType = "SyntacticPatDef"
+ val SyntacticSelectType: NameType = "SyntacticSelectType"
+ val SyntacticSelectTerm: NameType = "SyntacticSelectTerm"
val SyntacticTraitDef: NameType = "SyntacticTraitDef"
val SyntacticTry: NameType = "SyntacticTry"
val SyntacticTuple: NameType = "SyntacticTuple"
diff --git a/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala b/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala
index e96d1186f7..f558a2f078 100644
--- a/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala
+++ b/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala
@@ -199,4 +199,16 @@ object TermDeconstructionProps extends QuasiquoteProperties("term deconstruction
q"..$tpt; ()"
}
}
+
+ property("term select doesn't match type select") = test {
+ assertThrows[MatchError] {
+ val q"$qual.$name" = tq"foo.bar"
+ }
+ }
+
+ property("type application doesn't match applied type") = test {
+ assertThrows[MatchError] {
+ val q"$f[..$targs]" = tq"foo[bar]"
+ }
+ }
}
diff --git a/test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala b/test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala
index 8ec1779353..7572b27b52 100644
--- a/test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala
+++ b/test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala
@@ -63,4 +63,16 @@ object TypeDeconstructionProps extends QuasiquoteProperties("type deconstruction
// matches because type tree isn't syntactic without original
val tq"" = tq"${typeOf[Int]}"
}
+
+ property("type select doesn't match term select") = test {
+ assertThrows[MatchError] {
+ val tq"$qual.$name" = q"foo.bar"
+ }
+ }
+
+ property("applied type doesn't match type appliction") = test {
+ assertThrows[MatchError] {
+ val tq"$tpt[..$tpts]" = q"foo[bar]"
+ }
+ }
}