Skip to content
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

Incorrect unnecessary_cast from analyzer when cast influences type inference #44411

Closed
MohiuddinM opened this issue Dec 7, 2020 · 6 comments
Closed
Labels
analyzer-warning Issues with the analyzer's Warning codes area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. P2 A bug or feature request we're likely to work on

Comments

@MohiuddinM
Copy link

This code doesn't work: The argument type 'SizedBox' can't be assigned to the parameter type 'Text'.

final items = [1, 2, 3].map((e) => Text(e.toString())).toList();
items.add(SizedBox());

Adding a cast as List<Widget> solves the problem, but then it asks to remove unnecessary cast.

@mraleph
Copy link
Member

mraleph commented Dec 7, 2020

items is a List<Text> because of how map is defined: if you give map a function which returns T you get an Iterable<T> as a result.

There are few ways to fix it:

final items = [1, 2, 3].map<Widget>((e) => Text(e.toString())).toList();
items.add(SizedBox());

or alternatively:

final items = [
  for (var e in [1, 2, 3])
    Text(e.toString());
  SizedBox(),
]

Adding a cast as List<Widget> solves the problem, but then it asks to remove unnecessary cast.

That's wrong message from the analyzer though. Self contained repro:

class A {}

class B extends A {}

class C extends A {}

void main() {
  final items = [1, 2, 3].map((e) => B()).toList() as List<A>;
  items.add(C());
}

Produces unnecessary_cast but clearly should not because cast influences inference.

@mraleph mraleph changed the title Type inference fails Incorrect unnecessary_cast from analyzer when cast influences type inference Dec 7, 2020
@mraleph mraleph added the area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. label Dec 7, 2020
@eernstg
Copy link
Member

eernstg commented Dec 7, 2020

The context type actually won't reach the relevant location in this case, so type inference proceeds from a blank slate.

The syntactic context e as T actually does not provide a context type for e, so we will create a List<B> and then perform the upcast to List<A> in the example at the end of this comment. So the inference applied to [1, 2, 3].map((e) => B()).toList() works as it would have worked with final items = [1, 2, 3].map((e) => B()).toList();. But a context type wouldn't even be sufficient (say, List<A> items = [1, 2, 3].map((e) => B()).toList();), because type inference of the receiver [1, 2, 3].map((e) => B()) gets the empty context type even in the case where a method invocation (here: <receiver>.toList()) has a context type.

But I agree that the cast does have an effect: The type of items is List<A> with the cast and List<B> without it. So it is somewhat misleading that the analyzer says 'unnecessary cast'.

@mraleph
Copy link
Member

mraleph commented Dec 7, 2020

Thanks for clarification @eernstg. Yeah, now that I actually run the code I see that it only affects the static type of items but not its runtime type. I am a bit puzzled why it solved an issue for the reporter then:

Adding a cast as List solves the problem, but then it asks to remove unnecessary cast.

Given your explanation it is is clearly "redundant cast", though it might have downstream effects on the inference.

@eernstg
Copy link
Member

eernstg commented Dec 7, 2020

I suspect that it didn't resolve the problem: The compile-time error was gone, because we're no more trying to add a SizedBox to a List<Text> according to the static types, but it will still do exactly that in terms of the types at run time, and then there will be a downcast failure.

@MohiuddinM
Copy link
Author

You are right, cast doesn't solve the problem. It only helps with compilation. This is the error I get at runtime:
type 'SizedBox' is not a subtype of type 'Text' of 'value'

@scheglov scheglov added analyzer-warning Issues with the analyzer's Warning codes P2 A bug or feature request we're likely to work on labels Dec 8, 2020
@scheglov
Copy link
Contributor

scheglov commented Dec 8, 2020

@bwilkerson @pq

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
analyzer-warning Issues with the analyzer's Warning codes area-analyzer Use area-analyzer for Dart analyzer issues, including the analysis server and code completion. P2 A bug or feature request we're likely to work on
Projects
None yet
Development

No branches or pull requests

4 participants