-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Avoid spurious custom extractor warnings
The pattern matcher converts code like: Box(Option("hello")) match { case Box(Some(s)) => case Box(None) => } into two invocations of Box.unapply, because it can't trust that Box.unapply is idempotent. For case classes (like Some) it can, and moreso it can just access the underlying values directly ("x1.value"). The exhaustivity/unreachability analysis builds on this (e.g "pointsToBound.exists(sym => t.exists(_.symbol == sym)"). With the previous commits making the exhaustivity/unreachability checker consider custom extractors this would result in multiple symbols for each extraction (instead of all being "x1.value", for example) which results in multiple SAT variables which results, basically, in warnings that the value returned from the first extraction could None and the second value could be Some - which is only true for a non-idempotent Box.unapply. The intent of the previous commits (and the whole PR) is to make the exhaustivity checker provide warnings that were previous missing, but warning for fear of non-idempotent custom extractors would produce more noise than signal. Now, within a minor release like 2.13.4 we can't go and change the code generation and thus the code semantics (Dotty can and apparently does), but we can do the analysis with the assumption of idempotency. That's what this does: in MatchApproximator's TreeMakersToProps use a cache for the binders so when we see two extractions that are equivalent we reuse the same binder, so it translates into the same SAT variable.
- Loading branch information
Showing
2 changed files
with
64 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// scalac: -Xfatal-warnings | ||
|
||
final class Box[A](val unwrap: A) | ||
|
||
object Box { | ||
def apply[A](x: A): Box[A] = new Box[A](x) | ||
def unapply[A](x: Box[A]): Some[A] = Some(x.unwrap) | ||
} | ||
|
||
object Perhaps { | ||
def unapply[A](oa: Option[A]): Some[Option[A]] = Some(oa) | ||
} | ||
|
||
class Test { | ||
def test() = { | ||
List(Option("hello")) match { | ||
case Perhaps(Some(s)) :: _ => | ||
case Perhaps(None ) :: _ => | ||
case Nil => | ||
} | ||
} | ||
|
||
def justOption() = { | ||
Option("hello") match { | ||
case Perhaps(Some(s)) => | ||
case Perhaps(None) => | ||
} | ||
} | ||
|
||
def boxTest() = { | ||
Box(Option("hello")) match { | ||
case Box(Some(s)) => | ||
case Box(None) => | ||
} | ||
} | ||
} |