-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Use upper bound of abstract types in exhaustivity checking #23909
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
Conversation
|
@zielinsky Could you review this PR? |
zielinsky
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this change impacts abstract type members as well, could you add tests for them too?
Sure, I made a test code like below. trait Foo
trait Bar
trait AbstractType:
type Type <: (Foo | Bar)
object FooOrBar extends AbstractType:
type Type = Foo | Bar
trait Buz
@main def main =
val p: FooOrBar.Type | Buz = new Buz {}
p match
case _: Foo => println("foo")
case _: Buz => println("buz")
case _: Bar => println("bar")
It passes well, but this abstract type member setup doesn't hide the implementation type, it doesn't reach the logic that I added. tpw.isInstanceOf[OrType] || // It is caught by this condition
(tpw.isInstanceOf[AndType] && {
val and = tpw.asInstanceOf[AndType]
isCheckable(and.tp1) || isCheckable(and.tp2)
}) ||
tpw.isRef(defn.BooleanClass) ||
classSym.isAllOf(JavaEnum) ||
classSym.is(Case) ||
(tpw.isInstanceOf[TypeRef] && {
val tref = tpw.asInstanceOf[TypeRef]
if (tref.symbol.isAbstractOrAliasType && !tref.info.hiBound.isNothingType) {
println(s" hibound: ${tref.info.hiBound}")
isCheckable(tref.info.hiBound)
} else
false
})Is this expected, right? |
|
@nox213, The test you sent does not test the change you made, so there is no point in adding it :/ sealed trait S
trait Z
case object A extends S, Z
case object B extends S, Z
trait HasT:
type T <: S & Z
def nonExhaustive(h: HasT, x: h.T) =
x match
case A => ()
|
zielinsky
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
closes scala#23620, scala#24246 If the upper bound of an abstract type is not `sealed` but is effectively sealed, it is not handled correctly, since classSym could return a type that is not `sealed` (Object in the issue above). If the type were not abstract, it would pass the logic that checks whether it is an Or, And, etc., and would be handled properly. This PR makes exhaustivity checking use the upper bound of abstract types that are effectively sealed. --------- Co-authored-by: Zieliński Patryk <75637004+zielinsky@users.noreply.github.com>
closes scala#23620, scala#24246 If the upper bound of an abstract type is not `sealed` but is effectively sealed, it is not handled correctly, since classSym could return a type that is not `sealed` (Object in the issue above). If the type were not abstract, it would pass the logic that checks whether it is an Or, And, etc., and would be handled properly. This PR makes exhaustivity checking use the upper bound of abstract types that are effectively sealed. --------- Co-authored-by: Zieliński Patryk <75637004+zielinsky@users.noreply.github.com> [Cherry-picked 520668f][modified]
closes #23620, #24246
If the upper bound of an abstract type is not
sealedbut is effectively sealed, it is not handled correctly, since classSym could return a type that is notsealed(Object in the issue above).If the type were not abstract, it would pass the logic that checks whether it is an Or, And, etc., and would be handled properly.
This PR makes exhaustivity checking use the upper bound of abstract types that are effectively sealed.