Skip to content

Commit

Permalink
Fix false unreachable due to opaqueness (#19368)
Browse files Browse the repository at this point in the history
Fix #19275
  • Loading branch information
sjrd authored Jan 23, 2024
2 parents 1b78736 + a2b0091 commit 2638eb4
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 11 deletions.
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ object Types extends TypeUtils {
*/
def isRef(sym: Symbol, skipRefined: Boolean = true)(using Context): Boolean = this match {
case this1: TypeRef =>
this1.info match { // see comment in Namer#typeDefSig
this1.info match { // see comment in Namer#TypeDefCompleter#typeSig
case TypeAlias(tp) => tp.isRef(sym, skipRefined)
case _ => this1.symbol eq sym
}
Expand Down
18 changes: 8 additions & 10 deletions compiler/src/dotty/tools/dotc/transform/patmat/Space.scala
Original file line number Diff line number Diff line change
Expand Up @@ -657,17 +657,15 @@ object SpaceEngine {
}

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

val ListOfNoType = List(NoType)
val ListOfTypNoType = ListOfNoType.map(Typ(_, decomposed = true))
Expand Down
6 changes: 6 additions & 0 deletions tests/warn/i19275.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
opaque type Foo[A] <: A = A

class Test:
def t1(x: Option[Foo[List[Int]]]): Unit = x match
case Some(foo) =>
case None =>

0 comments on commit 2638eb4

Please sign in to comment.