Skip to content

Commit 1f34957

Browse files
committed
Fix #7204: Use evidence based type testing for unapplies
* Deprecate `IsXYZ` extrators * Provide `IsInstanceOf[XYZ]` evidences * Refine the types of arguments of `unapply`s * Use `_: XYZ` instead of `IsXYZ(_)` in the dotty library
1 parent 68375c9 commit 1f34957

File tree

26 files changed

+1274
-974
lines changed

26 files changed

+1274
-974
lines changed

compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala

Lines changed: 469 additions & 269 deletions
Large diffs are not rendered by default.

library/src-bootstrapped/scala/tasty/reflect/TreeUtils.scala

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -57,21 +57,21 @@ trait TreeUtils
5757
foldTrees(foldTree(x, elemtpt), elems)
5858
case Inlined(call, bindings, expansion) =>
5959
foldTree(foldTrees(x, bindings), expansion)
60-
case IsDefinition(vdef @ ValDef(_, tpt, rhs)) =>
60+
case vdef @ ValDef(_, tpt, rhs) =>
6161
implicit val ctx = localCtx(vdef)
6262
foldTrees(foldTree(x, tpt), rhs)
63-
case IsDefinition(ddef @ DefDef(_, tparams, vparamss, tpt, rhs)) =>
63+
case ddef @ DefDef(_, tparams, vparamss, tpt, rhs) =>
6464
implicit val ctx = localCtx(ddef)
6565
foldTrees(foldTree(vparamss.foldLeft(foldTrees(x, tparams))(foldTrees), tpt), rhs)
66-
case IsDefinition(tdef @ TypeDef(_, rhs)) =>
66+
case tdef @ TypeDef(_, rhs) =>
6767
implicit val ctx = localCtx(tdef)
6868
foldTree(x, rhs)
69-
case IsDefinition(cdef @ ClassDef(_, constr, parents, derived, self, body)) =>
69+
case cdef @ ClassDef(_, constr, parents, derived, self, body) =>
7070
implicit val ctx = localCtx(cdef)
7171
foldTrees(foldTrees(foldTrees(foldTrees(foldTree(x, constr), parents), derived), self), body)
7272
case Import(expr, _) =>
7373
foldTree(x, expr)
74-
case IsPackageClause(clause @ PackageClause(pid, stats)) =>
74+
case clause @ PackageClause(pid, stats) =>
7575
foldTrees(foldTree(x, pid), stats)(given clause.symbol.localContext)
7676
case Inferred() => x
7777
case TypeIdent(_) => x
@@ -112,47 +112,47 @@ trait TreeUtils
112112

113113
def transformTree(tree: Tree)(given ctx: Context): Tree = {
114114
tree match {
115-
case IsPackageClause(tree) =>
115+
case tree: PackageClause =>
116116
PackageClause.copy(tree)(transformTerm(tree.pid).asInstanceOf[Ref], transformTrees(tree.stats)(given tree.symbol.localContext))
117-
case IsImport(tree) =>
117+
case tree: Import =>
118118
Import.copy(tree)(transformTerm(tree.expr), tree.selectors)
119-
case IsStatement(tree) =>
119+
case tree: Statement =>
120120
transformStatement(tree)
121-
case IsTypeTree(tree) => transformTypeTree(tree)
122-
case IsTypeBoundsTree(tree) => tree // TODO traverse tree
123-
case IsWildcardTypeTree(tree) => tree // TODO traverse tree
124-
case IsCaseDef(tree) =>
121+
case tree: TypeTree => transformTypeTree(tree)
122+
case tree: TypeBoundsTree => tree // TODO traverse tree
123+
case tree: WildcardTypeTree => tree // TODO traverse tree
124+
case tree: CaseDef =>
125125
transformCaseDef(tree)
126-
case IsTypeCaseDef(tree) =>
126+
case tree: TypeCaseDef =>
127127
transformTypeCaseDef(tree)
128-
case IsBind(pattern) =>
128+
case pattern: Bind =>
129129
Bind.copy(pattern)(pattern.name, pattern.pattern)
130-
case IsUnapply(pattern) =>
130+
case pattern: Unapply =>
131131
Unapply.copy(pattern)(transformTerm(pattern.fun), transformSubTrees(pattern.implicits), transformTrees(pattern.patterns))
132-
case IsAlternatives(pattern) =>
132+
case pattern: Alternatives =>
133133
Alternatives.copy(pattern)(transformTrees(pattern.patterns))
134134
}
135135
}
136136

137137
def transformStatement(tree: Statement)(given ctx: Context): Statement = {
138138
def localCtx(definition: Definition): Context = definition.symbol.localContext
139139
tree match {
140-
case IsTerm(tree) =>
140+
case tree: Term =>
141141
transformTerm(tree)
142-
case IsValDef(tree) =>
142+
case tree: ValDef =>
143143
implicit val ctx = localCtx(tree)
144144
val tpt1 = transformTypeTree(tree.tpt)
145145
val rhs1 = tree.rhs.map(x => transformTerm(x))
146146
ValDef.copy(tree)(tree.name, tpt1, rhs1)
147-
case IsDefDef(tree) =>
147+
case tree: DefDef =>
148148
implicit val ctx = localCtx(tree)
149149
DefDef.copy(tree)(tree.name, transformSubTrees(tree.typeParams), tree.paramss mapConserve (transformSubTrees(_)), transformTypeTree(tree.returnTpt), tree.rhs.map(x => transformTerm(x)))
150-
case IsTypeDef(tree) =>
150+
case tree: TypeDef =>
151151
implicit val ctx = localCtx(tree)
152152
TypeDef.copy(tree)(tree.name, transformTree(tree.rhs))
153-
case IsClassDef(tree) =>
153+
case tree: ClassDef =>
154154
ClassDef.copy(tree)(tree.name, tree.constructor, tree.parents, tree.derived, tree.self, tree.body)
155-
case IsImport(tree) =>
155+
case tree: Import =>
156156
Import.copy(tree)(transformTerm(tree.expr), tree.selectors)
157157
}
158158
}
@@ -177,7 +177,7 @@ trait TreeUtils
177177
New.copy(tree)(transformTypeTree(tpt))
178178
case Typed(expr, tpt) =>
179179
Typed.copy(tree)(transformTerm(expr), transformTypeTree(tpt))
180-
case IsNamedArg(tree) =>
180+
case tree: NamedArg =>
181181
NamedArg.copy(tree)(tree.name, transformTerm(tree.value))
182182
case Assign(lhs, rhs) =>
183183
Assign.copy(tree)(transformTerm(lhs), transformTerm(rhs))
@@ -204,28 +204,28 @@ trait TreeUtils
204204

205205
def transformTypeTree(tree: TypeTree)(given ctx: Context): TypeTree = tree match {
206206
case Inferred() => tree
207-
case IsTypeIdent(tree) => tree
208-
case IsTypeSelect(tree) =>
207+
case tree: TypeIdent => tree
208+
case tree: TypeSelect =>
209209
TypeSelect.copy(tree)(tree.qualifier, tree.name)
210-
case IsProjection(tree) =>
210+
case tree: Projection =>
211211
Projection.copy(tree)(tree.qualifier, tree.name)
212-
case IsAnnotated(tree) =>
212+
case tree: Annotated =>
213213
Annotated.copy(tree)(tree.arg, tree.annotation)
214-
case IsSingleton(tree) =>
214+
case tree: Singleton =>
215215
Singleton.copy(tree)(transformTerm(tree.ref))
216-
case IsRefined(tree) =>
216+
case tree: Refined =>
217217
Refined.copy(tree)(transformTypeTree(tree.tpt), transformTrees(tree.refinements).asInstanceOf[List[Definition]])
218-
case IsApplied(tree) =>
218+
case tree: Applied =>
219219
Applied.copy(tree)(transformTypeTree(tree.tpt), transformTrees(tree.args))
220-
case IsMatchTypeTree(tree) =>
220+
case tree: MatchTypeTree =>
221221
MatchTypeTree.copy(tree)(tree.bound.map(b => transformTypeTree(b)), transformTypeTree(tree.selector), transformTypeCaseDefs(tree.cases))
222-
case IsByName(tree) =>
222+
case tree: ByName =>
223223
ByName.copy(tree)(transformTypeTree(tree.result))
224-
case IsLambdaTypeTree(tree) =>
224+
case tree: LambdaTypeTree =>
225225
LambdaTypeTree.copy(tree)(transformSubTrees(tree.tparams), transformTree(tree.body))(given tree.symbol.localContext)
226-
case IsTypeBind(tree) =>
226+
case tree: TypeBind =>
227227
TypeBind.copy(tree)(tree.name, tree.body)
228-
case IsTypeBlock(tree) =>
228+
case tree: TypeBlock =>
229229
TypeBlock.copy(tree)(tree.aliases, tree.tpt)
230230
}
231231

library/src/scala/internal/quoted/Matcher.scala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -131,14 +131,14 @@ private[quoted] object Matcher {
131131
(scrutinee, pattern) match {
132132

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

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

165-
case (IsRef(_), IsRef(_)) if scrutinee.symbol == pattern.symbol =>
165+
case (_: Ref, _: Ref) if scrutinee.symbol == pattern.symbol =>
166166
matched
167167

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

212-
case (IsTypeTree(scrutinee), IsTypeTree(pattern)) if scrutinee.tpe <:< pattern.tpe =>
212+
case (scrutinee: TypeTree, pattern: TypeTree) if scrutinee.tpe <:< pattern.tpe =>
213213
matched
214214

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

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

330-
case (IsTerm(v1), IsTerm(v2)) =>
330+
case (v1: Term, v2: Term) =>
331331
(summon[Env], v1 =?= v2)
332332

333333
case _ =>
@@ -360,7 +360,7 @@ private[quoted] object Matcher {
360360
}
361361

362362
private def isTypeBinding(tree: Tree): Boolean = tree match {
363-
case IsTypeDef(tree) => hasBindAnnotation(tree.symbol)
363+
case tree: TypeDef => hasBindAnnotation(tree.symbol)
364364
case _ => false
365365
}
366366
}

library/src/scala/quoted/matching/Sym.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ object Sym {
2222
def unapply[T](expr: Expr[T])(given qctx: QuoteContext): Option[Sym[T]] = {
2323
import qctx.tasty.{_, given}
2424
expr.unseal match {
25-
case IsIdent(ref) =>
25+
case ref: Ident =>
2626
val sym = ref.symbol
2727
Some(new Sym[T](sym.name, sym))
2828
case _ => None

library/src/scala/quoted/matching/package.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ package object matching {
1313
def searchImplicitExpr[T](given tpe: Type[T], qctx: QuoteContext): Option[Expr[T]] = {
1414
import qctx.tasty.{_, given}
1515
searchImplicit(tpe.unseal.tpe) match {
16-
case IsImplicitSearchSuccess(iss) => Some(iss.tree.seal.asInstanceOf[Expr[T]])
17-
case IsImplicitSearchFailure(isf) => None
16+
case iss: ImplicitSearchSuccess => Some(iss.tree.seal.asInstanceOf[Expr[T]])
17+
case isf: ImplicitSearchFailure => None
1818
}
1919
}
2020

0 commit comments

Comments
 (0)