Comments (4)
@rubenferreira97 when using a variable pattern the variable type becomes ChildB<dynamic, dynamic>
, which is why it works. The type should be kept as ChildB<A, dynamic>
from language.
Using a variable pattern works:
sealed class BaseType<A> {}
class ChildA<A> extends BaseType<A> {}
class ChildB<A, B> extends BaseType<A> {}
test<A>(BaseType<A> a) => switch (a) {
ChildA _ => "ChildA",
ChildB _ => "ChildB",
};
void main() {
for (int i = 0; i < 10; i++) {
print('hello ${i + 1}');
}
}
I try to always follow @lrhn's advice 'Always use the object pattern' #2963 (comment). However, this advice does not work here. It seems you have encountered a different analysis between an object pattern and a variable pattern. I don't know if it's a bug.
Maybe it's impossible due the differences between them, but I really wish that the object and variable patterns could be consistent with each other.
from language.
True, I tried the following explicit version and it still errors:
test<A>(BaseType<A> a) => switch (a) {
ChildA<A>() => "ChildA",
ChildB<A, dynamic>() => "ChildB",
};
I can't find a valid reason for this not to work, but maybe the Dart team can answer 🙂.
from language.
This is likely working as specified, and it is a known short-coming of the exhaustiveness algorithm.
The algorithm sees ChildB<A, Object?>
and doesn't know how B
of Child<A, B>
affects exhausting the supertype BaseType<A>
, since there is no B
in the supertype.
So it gives up, and says you have to exhaust all of ChildB
, meaning ChildB<Object?, Object?>
, otherwise it can't be sure that you've exhausted all values of ChildB
that can be a BaseType<A>
. (That's called "overapproximation" in the specification. It's a guaranteed sound approximation to what you need to exhaust, but not minimal.)
A larger example showing the same thing:
sealed class BaseType<A> {}
class ChildA<A> extends BaseType<A> {}
class ChildB<A, B> extends BaseType<A> {}
test<A>(BaseType<A> a) => switch (a) {
// Not exahustive. Infers type arguments and promotes.
ChildA() => "ChildA: "
"${a..st<E<ChildA<A>>>()}",
ChildB() => "ChildB: "
"${a..st<E<ChildB<A, Object?>>>()}",
};
test2<A>(BaseType<A> a) => switch (a) {
// Exhaustive. Instantiates to bounds, does not promote.
ChildA v => "ChildA: "
"${a..st<E<BaseType<A>>>()}, "
"${v..st<E<ChildA<Object?>>>()}",
ChildB v => "ChildB: "
"${a..st<E<BaseType<A>>>()}, "
"${v..st<E<ChildB<Object?, Object?>>>()}",
};
test3<A>(BaseType<A> a) => switch (a) {
// Not exahustive. Explicit type arguments, promotes.
ChildA<A> v => "ChildA: "
"${a..st<E<ChildA<A>>>()}, "
"${v..st<E<ChildA<A>>>()}",
ChildB<A, Object?> v => "ChildB: "
"${a..st<E<ChildB<A, Object?>>>()}, "
"${v..st<E<ChildB<A, Object?>>>()}",
};
test4<A>(BaseType<A> a) => switch (a) {
// Exhaustive. Explicit super-typed arguments.
ChildA<A> v => "ChildA: "
"${a..st<E<ChildA<A>>>()}, "
"${v..st<E<ChildA<A>>>()}",
ChildB<Object?, Object?> v => "ChildB: "
"${a..st<E<BaseType<A>>>()}, "
"${v..st<E<ChildB<Object?, Object?>>>()}",
};
extension<T> on T {
void st<X extends E<T>>() {}
}
typedef E<T> = T Function(T);
The two switches where the second case pattern doesn't cover all of ChildB<Object?, Object?>
are not exhaustive. The two cases where they do, are.
See also dart-lang/sdk#53486
from language.
Related Issues (20)
- Allow augmenting member declarations immediately in the same body? HOT 7
- [parts-with-imports] Consider dropping the library name from the library directive HOT 1
- Infer the type of an optional parameter from the default value HOT 1
- Should digit separators be supported in int.fromEnvironment? HOT 1
- Support for Rust like #[cfg()] attributes HOT 10
- [parts-with-imports] Conditional part directives and the analyzer HOT 20
- Allow all variable augmentations to omit the initializing expression HOT 4
- `Error: Method not found` when running Flutter app with macro class HOT 2
- Allow a variable initializer to be unresolved, following the treatment of abstract members HOT 3
- Allow Iterators To Use The for-in Syntax HOT 5
- Macros: Emit diagnostics inside macro arguments HOT 2
- URI shorthands without internal whitespace. HOT 2
- URI shorthands, allow reserved words. HOT 8
- URI shorthands, more permissive HOT 2
- Inheriting a type parameter bound?
- Ordering of augmenting initializers and getters on late variables
- Generalize mixin inference to other superinterfaces? HOT 1
- [analyzer] Switch cases for destructured records do not promote types HOT 5
- False negative `unreachable_switch_case` diagnostic when using `switch` statements HOT 1
- Request or suggestion for a!++ or a!+=x; syntax. HOT 6
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from language.