Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix false unreachable due to opaqueness #19368

Merged
merged 1 commit into from
Jan 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -668,17 +668,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 =>
Loading