Skip to content

Incorrect unnecessary_cast from analyzer when cast influences type inference #44411

Closed
@MohiuddinM

Description

@MohiuddinM

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.

Activity

mraleph

mraleph commented on Dec 7, 2020

@mraleph
Member

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.

changed the title [-]Type inference fails[/-] [+]Incorrect unnecessary_cast from analyzer when cast influences type inference[/+] on Dec 7, 2020
eernstg

eernstg commented on Dec 7, 2020

@eernstg
Member

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

mraleph commented on Dec 7, 2020

@mraleph
Member

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

eernstg commented on Dec 7, 2020

@eernstg
Member

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

MohiuddinM commented on Dec 7, 2020

@MohiuddinM
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'

added
devexp-warningIssues with the analyzer's Warning codes
P2A bug or feature request we're likely to work on
on Dec 8, 2020
scheglov

scheglov commented on Dec 8, 2020

@scheglov
Contributor
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2A bug or feature request we're likely to work ondevexp-warningIssues with the analyzer's Warning codeslegacy-area-analyzerUse area-devexp instead.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @mraleph@scheglov@MohiuddinM@eernstg

        Issue actions

          Incorrect unnecessary_cast from analyzer when cast influences type inference · Issue #44411 · dart-lang/sdk