Matching on Option[Option[T]] where T is abstract and obtained from inline def in super trait emits exhaustivity warning
See original GitHub issueCompiler version
Scala 3.2.1
Minimized code
trait Base:
type Value
inline def oov: Option[Option[Value]] = None
def get: Option[Value]
trait X extends Base:
override def get: Option[Value] =
oov match
case Some(ov) => ov
case None => None
Output
The compiler emits the following warning:
[warn] -- [E029] Pattern Match Exhaustivity Warning: /path/to/Test.scala:8:8
[warn] 8 | oov match
[warn] | ^^^
[warn] | match may not be exhaustive.
[warn] |
[warn] | It would fail on pattern case: Some(_)
[warn] |
[warn] | longer explanation available when compiling with `-explain`
[warn] one warning found
Expectation
The code should compile.
Workarounds
We have found three ways to make the code compile without this warning and one that gives a new unexpected error:
Extract oov
to local value
trait Base:
type Value
inline def oov: Option[Option[Value]] = None
def get: Option[Value]
trait X extends Base:
override def get: Option[Value] =
val local_oov = oov
local_oov match
case Some(ov) => ov
case None => None
Remove inline
Without the inline
modifier, the code compiles:
trait Base:
type Value
def oov: Option[Option[Value]] = None
def get: Option[Value]
trait X extends Base:
override def get: Option[Value] =
oov match
case Some(ov) => ov
case None => None
Make type Value
concrete
trait Base:
type Value
inline def oov: Option[Option[Value]] = None
def get: Option[Value]
trait X extends Base:
override type Value = Int
override def get: Option[Value] =
oov match
case Some(ov) => ov
case None => None
Adding transparent
to inline
results in new error
This code
trait Base:
type Value
transparent inline def oov: Option[Option[Value]] = None
def get: Option[Value]
trait X extends Base:
override def get: Option[Value] =
oov match
case Some(ov) => ov
case None => None
causes the compiler to emit this error:
[error] -- [E007] Type Mismatch Error: /path/to/Test.scala:9:29
[error] 9 | case Some(ov) => ov
[error] | ^^
[error] | Found: (ov : Any)
[error] | Required: Option[X.this.Value]
Issue Analytics
- State:
- Created 10 months ago
- Comments:8 (7 by maintainers)
Top Results From Across the Web
scala - Type parameter circumvents match exhaustivity warning
If the selector of a pattern match is an instance of a sealed class, the compilation of pattern matching can emit warnings which...
Read more >Match may not be exhaustive warning, is this a big deal?
I have a function like so def foo(bar: Bar): Future[Unit] = { (bar.food, bar.isEnabled) match { case (Food.bread, true) => bazz() case ...
Read more >The Rust Programming Language
Documentation for how to use and how to build the platform is available. Target, std, rustc, cargo, notes. i686-apple-darwin, ✓ ...
Read more >The Practical Difference Between Abstract Classes and Traits ...
This short article will compare abstract classes and traits as means of inheritance.
Read more >Exam 2 Flashcards - Quizlet
A. If a class is declared to be abstract then every method in the class is abstract ... when a concrete class is...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
That
transparent inline
one is also wrong: the type variable?A
inSome.unapply
should infer to be upper-bounded by Nothing, and then instantiate to Nothing, not to Any.Looks like this is caused by the use of tryWiden in https://github.com/lampepfl/dotty/blob/ef653b6a31180416ff6b7fdc432e9ef0343b7075/compiler/src/dotty/tools/dotc/core/TypeOps.scala#L495-L507 In our situation,
tp
islocal.X
andpre
isthis.type
. Since the new prefix is a singleton it makes sense to go with that instead of the current logic which ends up wideninglocal.X
toNothing .. Any
(and thenAny
because we’re in a covariant position)