Skip to content

Commit 7700c61

Browse files
committed
Simplify isClosed logic
1 parent ad08a67 commit 7700c61

File tree

1 file changed

+19
-24
lines changed

1 file changed

+19
-24
lines changed

compiler/src/scala/quoted/runtime/impl/QuoteMatcher.scala

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import dotty.tools.dotc.core.Symbols.*
2424
*
2525
* Operations:
2626
* - `s =?= p` checks if a scrutinee `s` matches the pattern `p` while accumulating extracted parts of the code.
27-
* - `isClosedUnder(x1, .., xn)('{e})` returns true if and only if all the references in `e` to names defined in the pattern are contained in the set `{x1, ... xn}`.
27+
* - `isClosedUnderEnv(x1, .., xn)('{e})` returns true if and only if all the references in `e` to names defined in the pattern are contained in the set `{x1, ... xn}`.
2828
* - `lift(x1, .., xn)('{e})` returns `(y1, ..., yn) => [xi = $yi]'{e}` where `yi` is an `Expr` of the type of `xi`.
2929
* - `withEnv(x1 -> y1, ..., xn -> yn)(matching)` evaluates matching recording that `xi` is equivalent to `yi`.
3030
* - `matched` denotes that the the match succeeded and `matched('{e})` denotes that a match succeeded and extracts `'{e}`
@@ -34,10 +34,10 @@ import dotty.tools.dotc.core.Symbols.*
3434
*
3535
* ```scala
3636
* /* Term hole */
37-
* '{ e } =?= '{ hole[T] } && typeOf('{e}) <:< T && isClosedUnder()('{e}) ===> matched('{e})
37+
* '{ e } =?= '{ hole[T] } && typeOf('{e}) <:< T && isClosedUnderEnv()('{e}) ===> matched('{e})
3838
*
3939
* /* Higher order term hole */
40-
* '{ e } =?= '{ hole[(T1, ..., Tn) => T](x1, ..., xn) } && isClosedUnder(x1, ... xn)('{e}) ===> matched(lift(x1, ..., xn)('{e}))
40+
* '{ e } =?= '{ hole[(T1, ..., Tn) => T](x1, ..., xn) } && isClosedUnderEnv(x1, ... xn)('{e}) ===> matched(lift(x1, ..., xn)('{e}))
4141
*
4242
* /* Match literal */
4343
* '{ lit } =?= '{ lit } ===> matched
@@ -199,12 +199,9 @@ object QuoteMatcher {
199199
/* Term hole */
200200
// Match a scala.internal.Quoted.patternHole and return the scrutinee tree
201201
case TypeApply(patternHole, tpt :: Nil)
202-
if patternHole.symbol.eq(defn.QuotedRuntimePatterns_patternHole) &&
203-
scrutinee.tpe <:< tpt.tpe =>
204-
scrutinee match
205-
case ClosedPatternTerm(scrutinee) => matched(scrutinee)
206-
case _ => notMatched
207-
202+
if patternHole.symbol.eq(defn.QuotedRuntimePatterns_patternHole) =>
203+
if scrutinee.tpe <:< tpt.tpe && isClosedUnderEnvEnv(scrutinee) then matched(scrutinee)
204+
else notMatched
208205

209206
/* Higher order term hole */
210207
// Matches an open term and wraps it into a lambda that provides the free variables
@@ -431,21 +428,19 @@ object QuoteMatcher {
431428
|| summon[Env].get(devirtualizedScrutinee).contains(pattern)
432429
|| devirtualizedScrutinee.allOverriddenSymbols.contains(pattern)
433430

434-
private object ClosedPatternTerm {
435-
/** Matches a term that does not contain free variables defined in the pattern (i.e. not defined in `Env`) */
436-
def unapply(term: Tree)(using Env, Context): Option[term.type] =
437-
if freePatternVars(term).isEmpty then Some(term) else None
438-
439-
/** Return all free variables of the term defined in the pattern (i.e. defined in `Env`) */
440-
def freePatternVars(term: Tree)(using Env, Context): Set[Symbol] =
441-
val accumulator = new TreeAccumulator[Set[Symbol]] {
442-
def apply(x: Set[Symbol], tree: Tree)(using Context): Set[Symbol] =
443-
tree match
444-
case tree: Ident if summon[Env].contains(tree.symbol) => foldOver(x + tree.symbol, tree)
445-
case _ => foldOver(x, tree)
446-
}
447-
accumulator.apply(Set.empty, term)
448-
}
431+
/** Matches a term that does not contain free variables defined in the pattern (i.e. not defined in `Env`) */
432+
private def isClosedUnderEnvEnv(term: Tree)(using Env, Context): Boolean =
433+
freePatternVars(term).isEmpty
434+
435+
/** Return all free variables of the term defined in the pattern (i.e. defined in `Env`) */
436+
private def freePatternVars(term: Tree)(using Env, Context): Set[Symbol] =
437+
val accumulator = new TreeAccumulator[Set[Symbol]] {
438+
def apply(x: Set[Symbol], tree: Tree)(using Context): Set[Symbol] =
439+
tree match
440+
case tree: Ident if summon[Env].contains(tree.symbol) => foldOver(x + tree.symbol, tree)
441+
case _ => foldOver(x, tree)
442+
}
443+
accumulator.apply(Set.empty, term)
449444

450445
/** Result of matching a part of an expression */
451446
private opaque type Matching = Option[Tuple]

0 commit comments

Comments
 (0)