-
Notifications
You must be signed in to change notification settings - Fork 1.7k
pattern matching type inference issue #51395
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
Comments
Also, I'm not sure if patterns are intended to work this way or not, but the outer pattern, |
Also this program void main() {
print(perms([1, 2, 3]));
}
Iterable<Iterable<A>> perms<A>(Iterable<A> iterable) => switch(iterable) {
Iterable<A>(isEmpty: true) || Iterable<A>(rest: Iterable<A>(isEmpty: true)) => [iterable],
Iterable<A>(length: var len, first: var x, rest: Iterable<A> xs) => () sync* {
for (var i = 0; i < len; i++) {
for (var perm in perms(xs)) {
yield [...perm.take(i), x, ...perm.skip(i)];
}
}
}(),
};
extension<A> on Iterable<A> {
Iterable<A> get rest => skip(1);
} Has the following compiler error
But works if you add an explicit type cast Iterable<Iterable<A>> perms<A>(Iterable<A> iterable) => switch(iterable) {
Iterable<A>(isEmpty: true) || Iterable<A>(rest: Iterable<A>(isEmpty: true)) => [iterable],
Iterable<A>(length: var len, first: var x, rest: Iterable<A> xs) => () sync* {
for (var i = 0; i < len; i++) {
for (var perm in perms(xs)) {
yield [...perm.take(i), x, ...perm.skip(i)];
}
}
}() as Iterable<Iterable<A>>, // type cast here
}; |
@chloestefantsova Chloe can you triage? Tentatively marking as a CFE issue, but it might intended semantics. |
It seems like an error in the inference in the CFE. |
I don't see any particular issues with the type inference on these programs: An immediately invoked function literal ( See dart-lang/language#2820 for a discussion about this topic. One way to improve on the inference of function literals which are invoked immediately is to use a very simple generic function The following program is the initial example from this issue, except that it uses X iife<X>(X Function() f) => f();
void main() {
print(split([1, 2, 3]));
}
class A {}
Iterable<(Iterable<A>, Iterable<A>)> split<A>(Iterable<A> iterable) => switch (iterable) {
Iterable<A>(isEmpty: true) => [(Iterable<A>.empty(), Iterable<A>.empty())],
Iterable<A>(first: var x, rest: var xs) => iife(() sync* {
yield (Iterable<A>.empty(), iterable);
for (var (ls, rs) in split(xs)) {
yield ([x, ...ls], rs);
}
}),
};
extension<A> on Iterable<A> {
Iterable<A> get rest => skip(1);
} The implementation of patterns in for elements isn't complete, so unfortunately we can't execute that program (yet, or it might even work on the bleeding edge, otherwise it's coming soon). But the analyzer reports that there are no issues, which shows that type inference is now able to convey the required information. A later example doesn't use X iife<X>(X Function() f) => f();
void main() {
print(perms([1, 2, 3]));
}
class A {}
extension<A> on Iterable<A> {
Iterable<A> get rest => skip(1);
}
Iterable<Iterable<A>> perms<A>(Iterable<A> iterable) => switch (iterable) {
Iterable<A>(isEmpty: true) || Iterable<A>(rest: Iterable<A>(isEmpty: true)) =>
[iterable],
Iterable<A>(length: var len, first: var x, rest: Iterable<A> xs) =>
iife(() sync* {
for (var i = 0; i < len; i++) {
for (var perm in perms(xs)) {
yield [...perm.take(i), x, ...perm.skip(i)];
}
}
}),
}; Again, the only change I made was replacing |
@eernstg the See updated code below. void main() {
print(perms([1, 2, 3]));
print(split([1, 2, 3]));
}
Iterable<(Iterable<A>, Iterable<A>)> split<A>(Iterable<A> iterable) => switch (iterable) {
Iterable(isEmpty: true) =>
[(Iterable<A>.empty(), Iterable<A>.empty())],
Iterable(first: var x, rest: var xs) =>
iife(() sync* {
yield (Iterable<A>.empty(), iterable);
for (var (ls, rs) in split(xs)) {
yield ([x, ...ls], rs);
}
}),
};
Iterable<Iterable<A>> perms<A>(Iterable<A> iterable) => switch (iterable) {
Iterable(isEmpty: true) || Iterable(rest: Iterable(isEmpty: true)) =>
[iterable],
Iterable(length: var len, first: var x, rest: var xs) =>
iife(() sync* {
for (var i = 0; i < len; i++) {
for (var perm in perms(xs)) {
yield [...perm.take(i), x, ...perm.skip(i)];
}
}
}),
};
extension<A> on Iterable<A> {
Iterable<A> get rest => skip(1);
}
X iife<X>(X Function() f) => f(); Which produces the following error:
The issue is only with the The for patterns do work on the bleeding edge versions, but it isn't related to the issue here. You can use One thing to also note is that the patterns no longer seem to require an explicit type argument after switching to using the |
Apparently, the confusing inference results are caused by a glitch in the typing of pattern declared variables and extension members: #51437. |
Yes, thanks for raising this issue! |
Ran into another issue relating to patterns, this time there is a type inference issue when using a getter defined in an extension.
produces the error
If you change
rest: var xs
torest: Iterable<A> xs
, the program compiles and runs successfully.The text was updated successfully, but these errors were encountered: