From a9b2a7efc3d576c65558b58bb45645584ce2214c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Zieli=C5=84ski?= Date: Tue, 14 Apr 2026 01:51:08 +0200 Subject: [PATCH 1/3] handle SubMatch in ensureNoLocalRefs --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 5 +++++ tests/pos/i25746.scala | 9 +++++++++ 2 files changed, 14 insertions(+) create mode 100644 tests/pos/i25746.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index e41550164889..694c0abc09cf 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1589,6 +1589,11 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer case block @ Block(stats, expr) if !expr.isInstanceOf[Closure] => val expr1 = ascribeType(expr, pt) cpy.Block(block)(stats, expr1).withType(expr1.tpe) // no assignType here because avoid is redundant + case m @ Match(selector, cases) if m.isSubMatch => + val newCases = cases.map: cdef => + val newBody = ascribeType(cdef.body, pt) + cpy.CaseDef(cdef)(body = newBody).withType(newBody.tpe) + cpy.Match(m)(selector, newCases).withType(TypeComparer.lub(newCases.map(_.tpe))) case _ => val target = pt.simplified val targetTpt = TypeTree(target, inferred = true) diff --git a/tests/pos/i25746.scala b/tests/pos/i25746.scala new file mode 100644 index 000000000000..2cd11644d50d --- /dev/null +++ b/tests/pos/i25746.scala @@ -0,0 +1,9 @@ +import scala.language.experimental.subCases + +@main def test = + val r1 = "^foo".r.unanchored + val r2 = "bar$".r.unanchored + + val result1 = "foo bar" match + case s @ r1() if s match { case r2() => s } + case _ => "no" From c2096b34287ee623a72debc55ca4f7bc977cee1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Zieli=C5=84ski?= Date: Tue, 14 Apr 2026 10:30:40 +0200 Subject: [PATCH 2/3] add i25746 to excludelist for coverage test --- compiler/test/dotc/scoverage-ignore.excludelist | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/test/dotc/scoverage-ignore.excludelist b/compiler/test/dotc/scoverage-ignore.excludelist index 22cc1a29adb4..637586972b0d 100644 --- a/compiler/test/dotc/scoverage-ignore.excludelist +++ b/compiler/test/dotc/scoverage-ignore.excludelist @@ -84,3 +84,4 @@ tailrec.scala traitParams.scala i25460.scala matrix.scala +i25746.scala From 5527de603e532fde0d2bdf3a6d3c8103a1829b67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Zieli=C5=84ski?= Date: Tue, 14 Apr 2026 11:44:53 +0200 Subject: [PATCH 3/3] use .tpes instead of map --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 694c0abc09cf..9decd3372ee0 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1593,7 +1593,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer val newCases = cases.map: cdef => val newBody = ascribeType(cdef.body, pt) cpy.CaseDef(cdef)(body = newBody).withType(newBody.tpe) - cpy.Match(m)(selector, newCases).withType(TypeComparer.lub(newCases.map(_.tpe))) + cpy.Match(m)(selector, newCases).withType(TypeComparer.lub(newCases.tpes)) case _ => val target = pt.simplified val targetTpt = TypeTree(target, inferred = true)