From ea6bca1d686f964c262699d00ed4b675eb317e40 Mon Sep 17 00:00:00 2001 From: Yoonjae Jeon Date: Sun, 17 Aug 2025 22:19:05 +0900 Subject: [PATCH 1/4] fix(patmat): Use childPrefix to resolve path-dependent sealed children --- .../src/dotty/tools/dotc/core/TypeOps.scala | 17 ++++++++++++++++- tests/warn/i23369.scala | 16 ++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 tests/warn/i23369.scala diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index cf03273b4805..b257fd829abc 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -748,7 +748,22 @@ object TypeOps: // if (child.name == tpnme.LOCAL_CHILD) return child.typeRef - val childTp = if (child.isTerm) child.termRef else child.typeRef + val childTp = { + val parentSym = parent.typeSymbol + val parentPre = parent.normalizedPrefix + val defaultRef = if (child.isTerm) child.termRef else child.typeRef + + if (parentSym.isClass && parentPre.isInstanceOf[TermRef]) { + val newPrefix = childPrefix(parentPre, parentSym, child) + if (newPrefix.exists) + if (child.isTerm) TermRef(newPrefix, child.asTerm) + else TypeRef(newPrefix, child.asType) + else + defaultRef + } + else + defaultRef + } inContext(ctx.fresh.setExploreTyperState().setFreshGADTBounds.addMode(Mode.GadtConstraintInference)) { instantiateToSubType(childTp, parent, mixins).dealias diff --git a/tests/warn/i23369.scala b/tests/warn/i23369.scala new file mode 100644 index 000000000000..2222606110ed --- /dev/null +++ b/tests/warn/i23369.scala @@ -0,0 +1,16 @@ +class Module { + type BarTy + sealed trait Adt[A] + case class Foo() extends Adt[String] + case class Bar[A <: BarTy](x: BarTy) extends Adt[A] +} + +object Basic extends Module { + type BarTy = String +} + +def test(a: Basic.Adt[String]) = { + a match { // warn: match may not be exhaustive + case Basic.Foo() => + } +} \ No newline at end of file From 8b711e8e1110658f3ef7ac74d50023173f05cc8d Mon Sep 17 00:00:00 2001 From: Yoonjae Jeon Date: Wed, 20 Aug 2025 22:27:01 +0900 Subject: [PATCH 2/4] add new line --- tests/warn/i23369.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/warn/i23369.scala b/tests/warn/i23369.scala index 2222606110ed..4229dc61bf5e 100644 --- a/tests/warn/i23369.scala +++ b/tests/warn/i23369.scala @@ -13,4 +13,4 @@ def test(a: Basic.Adt[String]) = { a match { // warn: match may not be exhaustive case Basic.Foo() => } -} \ No newline at end of file +} From 192c959f92662ed8cbc5ef19fd367dd29c45b883 Mon Sep 17 00:00:00 2001 From: Yoonjae Jeon Date: Tue, 2 Sep 2025 18:08:51 +0900 Subject: [PATCH 3/4] second approach --- compiler/src/dotty/tools/dotc/core/TypeOps.scala | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index b257fd829abc..df8fb47c0482 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -820,9 +820,13 @@ object TypeOps: prefixTVar.uncheckedNN case ThisType(tref) if !tref.symbol.isStaticOwner => val symbol = tref.symbol + val compatibleSingleton = singletons.valuesIterator.find(_.underlying.derivesFrom(symbol)) if singletons.contains(symbol) then prefixTVar = singletons(symbol) // e.g. tests/pos/i16785.scala, keep Outer.this prefixTVar.uncheckedNN + else if compatibleSingleton.isDefined then + prefixTVar = compatibleSingleton.get + prefixTVar.uncheckedNN else if symbol.is(Module) then TermRef(this(tref.prefix), symbol.sourceModule) else if (prefixTVar != null) @@ -920,10 +924,11 @@ object TypeOps: } val inferThisMap = new InferPrefixMap - val tvars = tp1.etaExpand match + val prefixInferredTp = inferThisMap(tp1) + val tvars = prefixInferredTp.etaExpand match case eta: TypeLambda => constrained(eta) case _ => Nil - val protoTp1 = inferThisMap.apply(tp1).appliedTo(tvars) + val protoTp1 = prefixInferredTp.appliedTo(tvars) if gadtSyms.nonEmpty then ctx.gadtState.addToConstraint(gadtSyms) From f583b701a105e1d789870149c7dabd585dae37a0 Mon Sep 17 00:00:00 2001 From: Yoonjae Jeon Date: Tue, 2 Sep 2025 19:07:39 +0900 Subject: [PATCH 4/4] revert previous approach --- .../src/dotty/tools/dotc/core/TypeOps.scala | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index df8fb47c0482..f1936ff8cd01 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -748,22 +748,7 @@ object TypeOps: // if (child.name == tpnme.LOCAL_CHILD) return child.typeRef - val childTp = { - val parentSym = parent.typeSymbol - val parentPre = parent.normalizedPrefix - val defaultRef = if (child.isTerm) child.termRef else child.typeRef - - if (parentSym.isClass && parentPre.isInstanceOf[TermRef]) { - val newPrefix = childPrefix(parentPre, parentSym, child) - if (newPrefix.exists) - if (child.isTerm) TermRef(newPrefix, child.asTerm) - else TypeRef(newPrefix, child.asType) - else - defaultRef - } - else - defaultRef - } + val childTp = if (child.isTerm) child.termRef else child.typeRef inContext(ctx.fresh.setExploreTyperState().setFreshGADTBounds.addMode(Mode.GadtConstraintInference)) { instantiateToSubType(childTp, parent, mixins).dealias