Skip to content

Fix #7204: Use evidence based type testing for unapplies #7528

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

70 changes: 35 additions & 35 deletions library/src-bootstrapped/scala/tasty/reflect/TreeUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -57,21 +57,21 @@ trait TreeUtils
foldTrees(foldTree(x, elemtpt), elems)
case Inlined(call, bindings, expansion) =>
foldTree(foldTrees(x, bindings), expansion)
case IsDefinition(vdef @ ValDef(_, tpt, rhs)) =>
case vdef @ ValDef(_, tpt, rhs) =>
implicit val ctx = localCtx(vdef)
foldTrees(foldTree(x, tpt), rhs)
case IsDefinition(ddef @ DefDef(_, tparams, vparamss, tpt, rhs)) =>
case ddef @ DefDef(_, tparams, vparamss, tpt, rhs) =>
implicit val ctx = localCtx(ddef)
foldTrees(foldTree(vparamss.foldLeft(foldTrees(x, tparams))(foldTrees), tpt), rhs)
case IsDefinition(tdef @ TypeDef(_, rhs)) =>
case tdef @ TypeDef(_, rhs) =>
implicit val ctx = localCtx(tdef)
foldTree(x, rhs)
case IsDefinition(cdef @ ClassDef(_, constr, parents, derived, self, body)) =>
case cdef @ ClassDef(_, constr, parents, derived, self, body) =>
implicit val ctx = localCtx(cdef)
foldTrees(foldTrees(foldTrees(foldTrees(foldTree(x, constr), parents), derived), self), body)
case Import(expr, _) =>
foldTree(x, expr)
case IsPackageClause(clause @ PackageClause(pid, stats)) =>
case clause @ PackageClause(pid, stats) =>
foldTrees(foldTree(x, pid), stats)(given clause.symbol.localContext)
case Inferred() => x
case TypeIdent(_) => x
Expand Down Expand Up @@ -112,47 +112,47 @@ trait TreeUtils

def transformTree(tree: Tree)(given ctx: Context): Tree = {
tree match {
case IsPackageClause(tree) =>
case tree: PackageClause =>
PackageClause.copy(tree)(transformTerm(tree.pid).asInstanceOf[Ref], transformTrees(tree.stats)(given tree.symbol.localContext))
case IsImport(tree) =>
case tree: Import =>
Import.copy(tree)(transformTerm(tree.expr), tree.selectors)
case IsStatement(tree) =>
case tree: Statement =>
transformStatement(tree)
case IsTypeTree(tree) => transformTypeTree(tree)
case IsTypeBoundsTree(tree) => tree // TODO traverse tree
case IsWildcardTypeTree(tree) => tree // TODO traverse tree
case IsCaseDef(tree) =>
case tree: TypeTree => transformTypeTree(tree)
case tree: TypeBoundsTree => tree // TODO traverse tree
case tree: WildcardTypeTree => tree // TODO traverse tree
case tree: CaseDef =>
transformCaseDef(tree)
case IsTypeCaseDef(tree) =>
case tree: TypeCaseDef =>
transformTypeCaseDef(tree)
case IsBind(pattern) =>
case pattern: Bind =>
Bind.copy(pattern)(pattern.name, pattern.pattern)
case IsUnapply(pattern) =>
case pattern: Unapply =>
Unapply.copy(pattern)(transformTerm(pattern.fun), transformSubTrees(pattern.implicits), transformTrees(pattern.patterns))
case IsAlternatives(pattern) =>
case pattern: Alternatives =>
Alternatives.copy(pattern)(transformTrees(pattern.patterns))
}
}

def transformStatement(tree: Statement)(given ctx: Context): Statement = {
def localCtx(definition: Definition): Context = definition.symbol.localContext
tree match {
case IsTerm(tree) =>
case tree: Term =>
transformTerm(tree)
case IsValDef(tree) =>
case tree: ValDef =>
implicit val ctx = localCtx(tree)
val tpt1 = transformTypeTree(tree.tpt)
val rhs1 = tree.rhs.map(x => transformTerm(x))
ValDef.copy(tree)(tree.name, tpt1, rhs1)
case IsDefDef(tree) =>
case tree: DefDef =>
implicit val ctx = localCtx(tree)
DefDef.copy(tree)(tree.name, transformSubTrees(tree.typeParams), tree.paramss mapConserve (transformSubTrees(_)), transformTypeTree(tree.returnTpt), tree.rhs.map(x => transformTerm(x)))
case IsTypeDef(tree) =>
case tree: TypeDef =>
implicit val ctx = localCtx(tree)
TypeDef.copy(tree)(tree.name, transformTree(tree.rhs))
case IsClassDef(tree) =>
case tree: ClassDef =>
ClassDef.copy(tree)(tree.name, tree.constructor, tree.parents, tree.derived, tree.self, tree.body)
case IsImport(tree) =>
case tree: Import =>
Import.copy(tree)(transformTerm(tree.expr), tree.selectors)
}
}
Expand All @@ -177,7 +177,7 @@ trait TreeUtils
New.copy(tree)(transformTypeTree(tpt))
case Typed(expr, tpt) =>
Typed.copy(tree)(transformTerm(expr), transformTypeTree(tpt))
case IsNamedArg(tree) =>
case tree: NamedArg =>
NamedArg.copy(tree)(tree.name, transformTerm(tree.value))
case Assign(lhs, rhs) =>
Assign.copy(tree)(transformTerm(lhs), transformTerm(rhs))
Expand All @@ -204,28 +204,28 @@ trait TreeUtils

def transformTypeTree(tree: TypeTree)(given ctx: Context): TypeTree = tree match {
case Inferred() => tree
case IsTypeIdent(tree) => tree
case IsTypeSelect(tree) =>
case tree: TypeIdent => tree
case tree: TypeSelect =>
TypeSelect.copy(tree)(tree.qualifier, tree.name)
case IsProjection(tree) =>
case tree: Projection =>
Projection.copy(tree)(tree.qualifier, tree.name)
case IsAnnotated(tree) =>
case tree: Annotated =>
Annotated.copy(tree)(tree.arg, tree.annotation)
case IsSingleton(tree) =>
case tree: Singleton =>
Singleton.copy(tree)(transformTerm(tree.ref))
case IsRefined(tree) =>
case tree: Refined =>
Refined.copy(tree)(transformTypeTree(tree.tpt), transformTrees(tree.refinements).asInstanceOf[List[Definition]])
case IsApplied(tree) =>
case tree: Applied =>
Applied.copy(tree)(transformTypeTree(tree.tpt), transformTrees(tree.args))
case IsMatchTypeTree(tree) =>
case tree: MatchTypeTree =>
MatchTypeTree.copy(tree)(tree.bound.map(b => transformTypeTree(b)), transformTypeTree(tree.selector), transformTypeCaseDefs(tree.cases))
case IsByName(tree) =>
case tree: ByName =>
ByName.copy(tree)(transformTypeTree(tree.result))
case IsLambdaTypeTree(tree) =>
case tree: LambdaTypeTree =>
LambdaTypeTree.copy(tree)(transformSubTrees(tree.tparams), transformTree(tree.body))(given tree.symbol.localContext)
case IsTypeBind(tree) =>
case tree: TypeBind =>
TypeBind.copy(tree)(tree.name, tree.body)
case IsTypeBlock(tree) =>
case tree: TypeBlock =>
TypeBlock.copy(tree)(tree.aliases, tree.tpt)
}

Expand Down
14 changes: 7 additions & 7 deletions library/src/scala/internal/quoted/Matcher.scala
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,14 @@ private[quoted] object Matcher {
(scrutinee, pattern) match {

// Match a scala.internal.Quoted.patternHole typed as a repeated argument and return the scrutinee tree
case (IsTerm(scrutinee @ Typed(s, tpt1)), Typed(TypeApply(patternHole, tpt :: Nil), tpt2))
case (scrutinee @ Typed(s, tpt1), Typed(TypeApply(patternHole, tpt :: Nil), tpt2))
if patternHole.symbol == internal.Definitions_InternalQuoted_patternHole &&
s.tpe <:< tpt.tpe &&
tpt2.tpe.derivesFrom(defn.RepeatedParamClass) =>
matched(scrutinee.seal)

// Match a scala.internal.Quoted.patternHole and return the scrutinee tree
case (IsTerm(scrutinee), TypeApply(patternHole, tpt :: Nil))
case (scrutinee: Term, TypeApply(patternHole, tpt :: Nil))
if patternHole.symbol == internal.Definitions_InternalQuoted_patternHole &&
scrutinee.tpe <:< tpt.tpe =>
matched(scrutinee.seal)
Expand All @@ -162,7 +162,7 @@ private[quoted] object Matcher {
case (Select(qual1, _), Select(qual2, _)) if scrutinee.symbol == pattern.symbol =>
qual1 =?= qual2

case (IsRef(_), IsRef(_)) if scrutinee.symbol == pattern.symbol =>
case (_: Ref, _: Ref) if scrutinee.symbol == pattern.symbol =>
matched

case (Apply(fn1, args1), Apply(fn2, args2)) if fn1.symbol == fn2.symbol =>
Expand Down Expand Up @@ -209,7 +209,7 @@ private[quoted] object Matcher {
case (Repeated(elems1, _), Repeated(elems2, _)) if elems1.size == elems2.size =>
elems1 =?= elems2

case (IsTypeTree(scrutinee), IsTypeTree(pattern)) if scrutinee.tpe <:< pattern.tpe =>
case (scrutinee: TypeTree, pattern: TypeTree) if scrutinee.tpe <:< pattern.tpe =>
matched

case (Applied(tycon1, args1), Applied(tycon2, args2)) =>
Expand Down Expand Up @@ -306,7 +306,7 @@ private[quoted] object Matcher {
* `None` if it did not match or `Some(tup: Tuple)` if it matched where `tup` contains the contents of the holes.
*/
private def patternsMatches(scrutinee: Tree, pattern: Tree)(given Context, Env): (Env, Matching) = (scrutinee, pattern) match {
case (IsTerm(v1), Unapply(TypeApply(Select(patternHole @ Ident("patternHole"), "unapply"), List(tpt)), Nil, Nil))
case (v1: Term, Unapply(TypeApply(Select(patternHole @ Ident("patternHole"), "unapply"), List(tpt)), Nil, Nil))
if patternHole.symbol.owner.fullName == "scala.runtime.quoted.Matcher$" =>
(summon[Env], matched(v1.seal))

Expand All @@ -327,7 +327,7 @@ private[quoted] object Matcher {
case (Typed(Ident("_"), tpt1), Typed(Ident("_"), tpt2)) =>
(summon[Env], tpt1 =?= tpt2)

case (IsTerm(v1), IsTerm(v2)) =>
case (v1: Term, v2: Term) =>
(summon[Env], v1 =?= v2)

case _ =>
Expand Down Expand Up @@ -360,7 +360,7 @@ private[quoted] object Matcher {
}

private def isTypeBinding(tree: Tree): Boolean = tree match {
case IsTypeDef(tree) => hasBindAnnotation(tree.symbol)
case tree: TypeDef => hasBindAnnotation(tree.symbol)
case _ => false
}
}
Expand Down
2 changes: 1 addition & 1 deletion library/src/scala/quoted/matching/Sym.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ object Sym {
def unapply[T](expr: Expr[T])(given qctx: QuoteContext): Option[Sym[T]] = {
import qctx.tasty.{_, given}
expr.unseal match {
case IsIdent(ref) =>
case ref: Ident =>
val sym = ref.symbol
Some(new Sym[T](sym.name, sym))
case _ => None
Expand Down
4 changes: 2 additions & 2 deletions library/src/scala/quoted/matching/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ package object matching {
def searchImplicitExpr[T](given tpe: Type[T], qctx: QuoteContext): Option[Expr[T]] = {
import qctx.tasty.{_, given}
searchImplicit(tpe.unseal.tpe) match {
case IsImplicitSearchSuccess(iss) => Some(iss.tree.seal.asInstanceOf[Expr[T]])
case IsImplicitSearchFailure(isf) => None
case iss: ImplicitSearchSuccess => Some(iss.tree.seal.asInstanceOf[Expr[T]])
case isf: ImplicitSearchFailure => None
}
}

Expand Down
Loading