Open
Description
See dart-lang/sdk#53221 for context.
The gist is that
sealed class S {}
mixin M on S {}
class C extends S {}
class F implements M {}
is not prohibited by the specifications, and they also don't count M
towards exhausting S
, so
int i = switch (F() as S) {C _ => throw "Not this"};
should be allowed, as currently written, and have who-knows-what behavior.
Current behavior is:
- CFE disallows program, counts
M
as needed for exhaustingS
. - Analyzer: Accepts program.
We can either:
- Count
M
towards exhaustingS
, by includingon
-types in the list of dependencies that count. Or because that's generally useless, - allow
M
to be excluded from exhaustiveness, but then enforce that it's not implementable in any way:- We keep the current exhaustiveness rules about which types count twards exhaustiveness, which exclude mixins with only an
on
reference to the sealed class, onlyextends
,implements
andwith
clauses count. - We add the following restrictions on
mixin ... on SealedClass
and its uses:- It's a compile-time error if a
mixin
declaration M has a sealed (necessarilyclass
) declaration S as
a declaredon
type, M does not have S as a declared interface, and M is not markedbase
. - It's a compile-time error if any declaration has a
mixin
declaration M as declared interface, M has a sealed
declaration S as declaredon
type, and M does not have S as a declared interface. (Even inside the same
library. Really, only inside the same library, otherwise the "implementing abase
type" error should take precedence.)
- It's a compile-time error if a
- We keep the current exhaustiveness rules about which types count twards exhaustiveness, which exclude mixins with only an
If we do count M
towards exhauting S
, we should allow M
to be declared sealed
(or implicitly count it as sealed, so that it's possible to exhaust M
using all the classes of the form class F extends S with M {}
.