Skip to content

Commit 0a0b110

Browse files
Merge pull request #10531 from dotty-staging/fix-#10464
Fix #10464: Match overridden definitions
2 parents 85e48f7 + 4fe5c6e commit 0a0b110

File tree

7 files changed

+56
-8
lines changed

7 files changed

+56
-8
lines changed

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

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ object Matcher {
101101
// TODO improve performance
102102

103103
// TODO use flag from qctx.reflect. Maybe -debug or add -debug-macros
104-
private final val debug = false
104+
private inline val debug = false
105105

106106
import qctx.reflect._
107107
import Matching._
@@ -231,7 +231,7 @@ object Matcher {
231231
scrutinee =?= expr2
232232

233233
/* Match selection */
234-
case (ref: Ref, Select(qual2, _)) if scrutinee.symbol == pattern.symbol || summon[Env].get(scrutinee.symbol).contains(pattern.symbol) =>
234+
case (ref: Ref, Select(qual2, _)) if symbolMatch(scrutinee.symbol, pattern.symbol) =>
235235
ref match
236236
case Select(qual1, _) => qual1 =?= qual2
237237
case ref: Ident =>
@@ -240,7 +240,7 @@ object Matcher {
240240
case _ => matched
241241

242242
/* Match reference */
243-
case (_: Ref, _: Ident) if scrutinee.symbol == pattern.symbol || summon[Env].get(scrutinee.symbol).contains(pattern.symbol) =>
243+
case (_: Ref, _: Ident) if symbolMatch(scrutinee.symbol, pattern.symbol) =>
244244
matched
245245

246246
/* Match application */
@@ -329,23 +329,30 @@ object Matcher {
329329
s""">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
330330
|Scrutinee
331331
| ${scrutinee.show}
332-
|
333-
|${scrutinee.showExtractors}
334-
|
335332
|did not match pattern
336333
| ${pattern.show}
337334
|
338-
|${pattern.showExtractors}
339-
|
340335
|with environment: ${summon[Env]}
341336
|
337+
|Scrutinee: ${scrutinee.showExtractors}
338+
|Pattern: ${pattern.showExtractors}
342339
|
343340
|""".stripMargin)
344341
notMatched
345342
}
346343
}
347344
end extension
348345

346+
/** Does the scrutenne symbol match the pattern symbol? It matches if:
347+
* - They are the same symbol
348+
* - The scrutinee has is in the environment and they are equivalent
349+
* - The scrutinee overrides the symbol of the pattern
350+
*/
351+
private def symbolMatch(scrutinee: Symbol, pattern: Symbol)(using Env): Boolean =
352+
scrutinee == pattern
353+
|| summon[Env].get(scrutinee).contains(pattern)
354+
|| scrutinee.allOverriddenSymbols.contains(pattern)
355+
349356
private object ClosedPatternTerm {
350357
/** Matches a term that does not contain free variables defined in the pattern (i.e. not defined in `Env`) */
351358
def unapply(term: Term)(using Env): Option[term.type] =

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2348,6 +2348,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
23482348

23492349
def paramSymss: List[List[Symbol]] = self.denot.paramSymss
23502350
def primaryConstructor: Symbol = self.denot.primaryConstructor
2351+
def allOverriddenSymbols: Iterator[Symbol] = self.denot.allOverriddenSymbols
23512352

23522353
def caseFields: List[Symbol] =
23532354
if !self.isClass then Nil

library/src/scala/quoted/Quotes.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3625,6 +3625,9 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
36253625
*/
36263626
def paramSymss: List[List[Symbol]]
36273627

3628+
/** Returns all symbols overridden by this symbol. */
3629+
def allOverriddenSymbols: Iterator[Symbol]
3630+
36283631
/** The primary constructor of a class or trait, `noSymbol` if not applicable. */
36293632
def primaryConstructor: Symbol
36303633

tests/run-macros/i10464.check

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
matched!
2+
matched!
3+
matched!
4+
not matched
5+
not matched

tests/run-macros/i10464/Macro_1.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import scala.quoted._
2+
3+
object MatchMac {
4+
5+
inline def apply(inline any: Any): Unit = ${ printMacImpl('any) }
6+
7+
def printMacImpl(any: Expr[Any])(using Quotes): Expr[Unit] = {
8+
import quotes.reflect._
9+
val res = any match {
10+
case '{ ($f: Person).name } => "matched!"
11+
case _ => "not matched"
12+
}
13+
'{ println(${Expr(res)}) }
14+
}
15+
16+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
trait Person:
2+
def name: String
3+
4+
case class PersonA(name: String) extends Person
5+
case class PersonB(name: String) extends Person

tests/run-macros/i10464/Test_2.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
@main def Test = {
3+
val personA: PersonA = PersonA("JoeA")
4+
val personB: PersonB = PersonB("JoeB")
5+
val person: Person = personA
6+
MatchMac(personA.name)
7+
MatchMac(personB.name)
8+
MatchMac(person.name)
9+
MatchMac(PersonA("JoeA").name) // optimized to MatchMac("JoeA")
10+
MatchMac(PersonB("JoeB").name) // optimized to MatchMac("JoeB")
11+
}

0 commit comments

Comments
 (0)