Skip to content

Commit 2638eb4

Browse files
authored
Fix false unreachable due to opaqueness (#19368)
Fix #19275
2 parents 1b78736 + a2b0091 commit 2638eb4

File tree

3 files changed

+15
-11
lines changed

3 files changed

+15
-11
lines changed

Diff for: compiler/src/dotty/tools/dotc/core/Types.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ object Types extends TypeUtils {
197197
*/
198198
def isRef(sym: Symbol, skipRefined: Boolean = true)(using Context): Boolean = this match {
199199
case this1: TypeRef =>
200-
this1.info match { // see comment in Namer#typeDefSig
200+
this1.info match { // see comment in Namer#TypeDefCompleter#typeSig
201201
case TypeAlias(tp) => tp.isRef(sym, skipRefined)
202202
case _ => this1.symbol eq sym
203203
}

Diff for: compiler/src/dotty/tools/dotc/transform/patmat/Space.scala

+8-10
Original file line numberDiff line numberDiff line change
@@ -657,17 +657,15 @@ object SpaceEngine {
657657
}
658658

659659
extension (tp: Type)
660-
/** A type is decomposable to children if it has a simple kind, it's sealed,
661-
* abstract (or a trait) - so its not a sealed concrete class that can be instantiated on its own,
662-
* has no anonymous children, which we wouldn't be able to name as counter-examples,
663-
* but does have children.
664-
*
665-
* A sealed trait with no subclasses is considered not decomposable and thus is treated as an opaque type.
666-
* A sealed trait with subclasses that then get removed after `refineUsingParent`, decomposes to the empty list.
667-
* So that's why we consider whether a type has children. */
668660
def isDecomposableToChildren(using Context): Boolean =
669-
val cls = tp.classSymbol
670-
tp.hasSimpleKind && cls.is(Sealed) && cls.isOneOf(AbstractOrTrait) && !cls.hasAnonymousChild && cls.children.nonEmpty
661+
val sym = tp.typeSymbol // e.g. Foo[List[Int]] = type Foo (i19275)
662+
val cls = tp.classSymbol // e.g. Foo[List[Int]] = class List
663+
tp.hasSimpleKind // can't decompose higher-kinded types
664+
&& cls.is(Sealed)
665+
&& cls.isOneOf(AbstractOrTrait) // ignore sealed non-abstract classes
666+
&& !cls.hasAnonymousChild // can't name anonymous classes as counter-examples
667+
&& cls.children.nonEmpty // can't decompose without children
668+
&& !sym.isOpaqueAlias // can't instantiate subclasses to conform to an opaque type (i19275)
671669

672670
val ListOfNoType = List(NoType)
673671
val ListOfTypNoType = ListOfNoType.map(Typ(_, decomposed = true))

Diff for: tests/warn/i19275.scala

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
opaque type Foo[A] <: A = A
2+
3+
class Test:
4+
def t1(x: Option[Foo[List[Int]]]): Unit = x match
5+
case Some(foo) =>
6+
case None =>

0 commit comments

Comments
 (0)