From 69f5f730c9b887ccaf8436729de2a2f52fed871c Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 10 Oct 2024 12:43:42 +0100 Subject: [PATCH] Fix ctx implicits under case unapplySeq A case class with a varargs has a unapplySeq extractor instead of unapply. When we type an unapply, in typedUnapply, we first look for unapply methods before unapplySeq methods. But when searching for unapply, if a class method isn't found, then an extension method is looked for, which causes context implicits to be cached. The bindings from a pattern (such as from an unapply or unapplySeq extractor) are added to the context in indexPattern. But Context's `implicitCache` doesn't account for the scope changing. I opted for giving the body its own scope context, rather than making indexPattern reset the context implicits cache. --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 4 ++-- tests/pos/i21742.1.scala | 5 +++++ tests/pos/i21742.2.scala | 5 +++++ 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 tests/pos/i21742.1.scala create mode 100644 tests/pos/i21742.2.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index f20c2d313ec7..ed0ff5e0bd2f 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -2198,7 +2198,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer /** Type a case. */ def typedCase(tree: untpd.CaseDef, sel: Tree, wideSelType: Type, pt: Type)(using Context): CaseDef = { val originalCtx = ctx - val gadtCtx: Context = ctx.fresh.setFreshGADTBounds.setNewScope + val gadtCtx: Context = ctx.fresh.setFreshGADTBounds def caseRest(pat: Tree)(using Context) = { val pt1 = instantiateMatchTypeProto(pat, pt) match { @@ -2228,7 +2228,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer val pat1 = typedPattern(tree.pat, wideSelType)(using gadtCtx) caseRest(pat1)( using Nullables.caseContext(sel, pat1)( - using gadtCtx)) + using gadtCtx.fresh.setNewScope)) } def typedLabeled(tree: untpd.Labeled)(using Context): Labeled = { diff --git a/tests/pos/i21742.1.scala b/tests/pos/i21742.1.scala new file mode 100644 index 000000000000..c9c1a94b222c --- /dev/null +++ b/tests/pos/i21742.1.scala @@ -0,0 +1,5 @@ +case class C(n: Int, ds: Double*) +class Test: + def m(using n: Int): Int = n + 1 + def t(): Unit = + C(1, 2, 3, 4) match { case C(given Int, ds*) => m } diff --git a/tests/pos/i21742.2.scala b/tests/pos/i21742.2.scala new file mode 100644 index 000000000000..83dc4b6ad46f --- /dev/null +++ b/tests/pos/i21742.2.scala @@ -0,0 +1,5 @@ +case class C(n: Int, ds: Seq[Double]) +class Test: + def m(using n: Int): Int = n + 1 + def t(): Unit = + C(1, Seq(2, 3, 4)) match { case C(given Int, ds) => m }