Skip to content

Type inference is confusing on pattern context for List<String>.map(jsonDecode) #54676

Open
@whesse

Description

@whesse

Applying type inference on
List<String> a;
[ for (final {'event': String event} in a.map(jsonDecode)) switch(event) .... ];

gives an error where the type dynamic can't be inferred for the .map call.

Changing the call to .map<dynamic> makes the error go away.

The error is rather confusing, saying that it tries the candidate dynamic but it doesn't work.
The error (from tip-of-tree 'dart analyze', also is the same on stable 3.2.3) is

error • benchmarks.dart:3575:20 • Couldn't infer type parameter
          'T'.
          
          Tried to infer 'dynamic' for 'T' which doesn't work:
            Return
          type declared as 'Iterable<T>'
                        used where 
          'Iterable<Map<_, String>>' is required.
          The type 'dynamic' was
          inferred from:
            Parameter 'toElement' declared as     'T
          Function(String)'
                                  but argument is 'dynamic
          Function(String, {Object? Function(Object?, Object?)?
          reviver})'.
          
          Consider passing explicit type argument(s) to the
          generic.
          
           • could_not_infer

1 issue found.

Sample code showing the error is below:
The code runs without error, does not fail due to type inference failure.

 

import "dart:convert";

List<String> lines = [];

class BenchmarkParseResult {
  double counter;
  
  BenchmarkParseResult(this.counter);
}

List foo(int iterations) =>
   [
      for (final {'event': String event, 'counter-value': String counterString}
          in lines.map(jsonDecode))
        ...switch (event) {
          'cycles:u' => [
              BenchmarkParseResult(
                  double.parse(counterString) / iterations)
            ],
          'instructions:u' => [
              BenchmarkParseResult(
                  double.parse(counterString) / iterations)
            ],
          _ => [],
        }
    ];

void main() {
  print(foo(1));
}

Simpler cases do not give an error:

for (Map foo in lines.map<dynamic>(jsonDecode))
for (final foo in lines.map(jsonDecode))

The simple case without the pattern (or the control-flow expression) does give an error, but it is more comprehensible.
With the pattern instead, it gives the error shown above:

for (Map foo in <String>[].map(jsonDecode)) {}
for (final {'foo': int foo}  in <String>[].map(jsonDecode)) {}

The comprehensible error tries to propagate the Map type in to the jsonDecode argument:

The argument type 'dynamic Function(String, {Object? Function(Object?, Object?)? reviver})' can't be assigned
to the parameter type 'Map<dynamic, dynamic> Function(String)'.dart[argument_type_not_assignable]
(https://dart.dev/diagnostics/argument_type_not_assignable)

@johnniwinther @athomas

Metadata

Metadata

Labels

P3A lower priority bug or feature requestarea-dart-modelFor issues related to conformance to the language spec in the parser, compilers or the CLI analyzer.dart-model-language-patternsIssues with analyzer's support for the patterns language feature

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions