Skip to content

Commit

Permalink
SI-8388 consistently match type trees by originals
Browse files Browse the repository at this point in the history
Due to the fact that all TypTrees are transformed into TypeTrees
during typechecking one couldn't treat typed type trees in the same
way as they treat untyped type trees.

This change implements support for pattern matching of TypeTrees as their
corresponding TypTree equivalent using tree preserved in the original.

The implementation itself is a trivial wrapping of regular TypTree
extractors into MaybeTypeTreeOriginal.
  • Loading branch information
densh authored and xeno-by committed Mar 25, 2014
1 parent c765537 commit 0bac64d
Show file tree
Hide file tree
Showing 7 changed files with 349 additions and 70 deletions.
37 changes: 37 additions & 0 deletions bincompat-backward.whitelist.conf
Expand Up @@ -144,6 +144,43 @@ filter {
{
matchName="scala.reflect.api.Mirror.weakTypeOf"
problemName=MissingMethodProblem
},
// see SI-8388
{
matchName="scala.reflect.api.Internals$ReificationSupportApi$SyntacticIdentExtractor"
problemName=MissingClassProblem
},
{
matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticIdent"
problemName=MissingMethodProblem
},
{
matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticSingletonType"
problemName=MissingMethodProblem
},
{
matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticTermIdent"
problemName=MissingMethodProblem
},
{
matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticTypeIdent"
problemName=MissingMethodProblem
},
{
matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticCompoundType"
problemName=MissingMethodProblem
},
{
matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticAnnotatedType"
problemName=MissingMethodProblem
},
{
matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticTypeProjection"
problemName=MissingMethodProblem
},
{
matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticExistentialType"
problemName=MissingMethodProblem
}
]
}
62 changes: 62 additions & 0 deletions bincompat-forward.whitelist.conf
Expand Up @@ -149,6 +149,7 @@ filter {
matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticPartialFunction"
problemName=MissingMethodProblem
},
// see SI-8428
{
matchName="scala.collection.Iterator#ConcatIterator.this"
problemName=MissingMethodProblem
Expand All @@ -164,6 +165,67 @@ filter {
{
matchName="scala.reflect.api.Mirror.weakTypeOf"
problemName=MissingMethodProblem
},
// see SI-8388
{
matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticSingletonType"
problemName=MissingMethodProblem
},
{
matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticTermIdent"
problemName=MissingMethodProblem
},
{
matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticTypeIdent"
problemName=MissingMethodProblem
},
{
matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticCompoundType"
problemName=MissingMethodProblem
},
{
matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticAnnotatedType"
problemName=MissingMethodProblem
},
{
matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticTypeProjection"
problemName=MissingMethodProblem
},
{
matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticExistentialType"
problemName=MissingMethodProblem
},
{
matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticIdent"
problemName=MissingMethodProblem
},
{
matchName="scala.reflect.api.Internals$ReificationSupportApi$SyntacticAnnotatedTypeExtractor"
problemName=MissingClassProblem
},
{
matchName="scala.reflect.api.Internals$ReificationSupportApi$SyntacticTermIdentExtractor"
problemName=MissingClassProblem
},
{
matchName="scala.reflect.api.Internals$ReificationSupportApi$SyntacitcSingletonTypeExtractor"
problemName=MissingClassProblem
},
{
matchName="scala.reflect.api.Internals$ReificationSupportApi$SyntacticTypeIdentExtractor"
problemName=MissingClassProblem
},
{
matchName="scala.reflect.api.Internals$ReificationSupportApi$SyntacticCompoundTypeExtractor"
problemName=MissingClassProblem
},
{
matchName="scala.reflect.api.Internals$ReificationSupportApi$SyntacticExistentialTypeExtractor"
problemName=MissingClassProblem
},
{
matchName="scala.reflect.api.Internals$ReificationSupportApi$SyntacticTypeProjectionExtractor"
problemName=MissingClassProblem
}
]
}
16 changes: 14 additions & 2 deletions src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
Expand Up @@ -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) =>
Expand All @@ -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) =>
Expand Down
44 changes: 40 additions & 4 deletions src/reflect/scala/reflect/api/Internals.scala
Expand Up @@ -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
Expand All @@ -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")
Expand Down
84 changes: 76 additions & 8 deletions src/reflect/scala/reflect/internal/ReificationSupport.scala
Expand Up @@ -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
}
}

Expand Down Expand Up @@ -891,13 +891,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
Expand Down Expand Up @@ -1043,8 +1054,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
}
}

Expand All @@ -1055,6 +1066,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
Expand Down

0 comments on commit 0bac64d

Please sign in to comment.