Skip to content

Commit 6579f38

Browse files
authored
Add a rule to determine which extension types are always-exhaustive (#3568)
Add a rule to determine which extension types are always-exhaustive, namely: The ones whose representation type is always-exhaustive. Also add some commentary, about this new rule, and also about the situation where an extension type implements a sealed type in a different library (which is a no-go for other kinds of types).
1 parent c71b621 commit 6579f38

File tree

1 file changed

+30
-3
lines changed

1 file changed

+30
-3
lines changed

accepted/future-releases/extension-types/feature-specification.md

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ information about the process, including in their change logs.
1818
2024.01.17
1919
- Specify that a type is 'incompatible with await', and use that to specify
2020
a compile-time error at `await e;`.
21+
- Specify which extension types are always-exhaustive.
2122

2223
2023.11.14
2324
- Specify that a method declaration will shadow an otherwise "inherited"
@@ -828,6 +829,17 @@ type)*. Exhaustiveness analysis will treat such patterns as if they had
828829
been an object pattern matching the extension type erasure of `V` (defined
829830
below).
830831

832+
An extension type `V` is always-exhaustive if and only if its instantiated
833+
representation type is always-exhaustive.
834+
835+
*For example, a type `TriBool` defined as
836+
`extension type TriBool(bool? _) {}`,
837+
is always-exhaustive because the representation type, `bool?`, is.
838+
For a declaration like `extension type Pair<S, T>((S, T) _) {}`, the type
839+
`Pair<SomeEnum, TriBool>` is always-exhaustive because `(SomeEnum, TriBool)`
840+
is, and `Pair<String, bool>` is not always-exhaustive because `(String, bool)`
841+
isn't.*
842+
831843
*In other words, we make no attempt to hide the representation type during
832844
the exhaustiveness analysis. The usage of such patterns is very similar to
833845
a cast into the extension type in the sense that it provides a reference of
@@ -868,7 +880,7 @@ _is the extension type_
868880
<code>V\<T<sub>1</sub>, .. T<sub>s</sub>&gt;</code>,
869881
and that its static type _is an extension type_.
870882

871-
We say that a type `T` is _incompatible with await_ if at least
883+
We say that a type `T` is _incompatible with await_ if at least
872884
one of the following criteria holds:
873885

874886
- `T` is an extension type that does not implement `Future`.
@@ -877,10 +889,10 @@ one of the following criteria holds:
877889
- `B` is incompatible with await, or
878890
- `B` does not derive a future type, and `X` is
879891
incompatible with await.
880-
- `T` is a type variable with bound `S`, and `S` is incompatible
892+
- `T` is a type variable with bound `S`, and `S` is incompatible
881893
with await.
882894

883-
Consider an expression of the form `await e`. A compile-time error
895+
Consider an expression of the form `await e`. A compile-time error
884896
occurs if the static type of `e` is incompatible with await.
885897

886898
A compile-time error occurs if an extension type declares a member whose
@@ -911,6 +923,21 @@ types, and it is not an error to have `implements T` where `T` is a type
911923
that denotes a `sealed`, `final`, or `base` class in a different library,
912924
or `T` is an enumerated type.*
913925

926+
*Consider `extension type E(SomeType _) implements SealedType {}`
927+
where `SealedType` is a sealed type. In this situation, `E` does not
928+
need to be taken into account like other immediate subtypes of `SealedType`
929+
(which is also the reason why we can declare it in a different library
930+
than the library that declares `SealedType`).
931+
The representation `SomeType` type could be `SealedType` itself, in which
932+
case `E` will be always-exhaustive. According to the exhaustiveness
933+
analysis, `E` is just another way to spell `SealedType`.
934+
`SomeType` could also be an immediate subtype of `SealedType`, in which case
935+
`E` would be counted as that subtype during exhaustiveness analysis.
936+
Finally, `SomeType` could be some non-immediate subtype of `SealedType`,
937+
in which case it is treated just like any other non-immediate subtype of
938+
`SealedType` (they don't matter anywhere, with respect to exhaustiveness
939+
of `SealedType`).*
940+
914941
A compile-time error occurs if an extension type is used as a
915942
superinterface of a class, mixin, or enum declaration, or if an extension
916943
type is used in a mixin application as a superclass or as a mixin.

0 commit comments

Comments
 (0)