@@ -12,7 +12,6 @@ import 'package:analyzer/src/dart/ast/ast.dart';
12
12
import 'package:analyzer/src/dart/element/element.dart' ;
13
13
import 'package:analyzer/src/dart/element/type.dart' ;
14
14
import 'package:analyzer/src/dart/element/type_provider.dart' ;
15
- import 'package:analyzer/src/dart/element/type_schema.dart' ;
16
15
import 'package:analyzer/src/dart/element/type_system.dart' ;
17
16
import 'package:analyzer/src/error/codes.dart' ;
18
17
import 'package:analyzer/src/generated/engine.dart' ;
@@ -267,39 +266,42 @@ class TypedLiteralResolver {
267
266
return _LiteralResolution (_LiteralResolutionKind .ambiguous, null );
268
267
}
269
268
270
- /// If [contextType] is defined and is a subtype of `Iterable<Object>` and
271
- /// [contextType] is not a subtype of `Map<Object, Object>` , then *e* is a set
269
+ /// If [contextType] implements `Iterable` , but not `Map` , then *e* is a set
272
270
/// literal.
273
271
///
274
- /// If [contextType] is defined and is a subtype of `Map<Object, Object>` and
275
- /// [contextType] is not a subtype of `Iterable<Object>` then *e* is a map
272
+ /// If [contextType] implements `Map` , but not `Iterable` , then *e* is a map
276
273
/// literal.
277
274
_LiteralResolution _fromContextType (DartType contextType) {
278
275
if (contextType != null ) {
279
- DartType unwrap (DartType type) {
280
- if (type is InterfaceType &&
281
- type.isDartAsyncFutureOr &&
282
- type.typeArguments.length == 1 ) {
283
- return unwrap (type.typeArguments[0 ]);
284
- }
285
- return type;
286
- }
287
-
288
- DartType unwrappedContextType = unwrap (contextType);
276
+ var unwrappedContextType = _typeSystem.futureOrBase (contextType);
289
277
// TODO(brianwilkerson) Find out what the "greatest closure" is and use that
290
278
// where [unwrappedContextType] is used below.
291
- bool isIterable = _typeSystem.isSubtypeOf2 (
292
- unwrappedContextType, _typeProvider.iterableForSetMapDisambiguation);
293
- bool isMap = _typeSystem.isSubtypeOf2 (
294
- unwrappedContextType, _typeProvider.mapForSetMapDisambiguation);
279
+ var iterableType = unwrappedContextType.asInstanceOf (
280
+ _typeProvider.iterableElement,
281
+ );
282
+ var mapType = unwrappedContextType.asInstanceOf (
283
+ _typeProvider.mapElement,
284
+ );
285
+ var isIterable = iterableType != null ;
286
+ var isMap = mapType != null ;
287
+
288
+ // When `S` implements `Iterable` but not `Map`, `e` is a set literal.
295
289
if (isIterable && ! isMap) {
296
290
return _LiteralResolution (
297
- _LiteralResolutionKind .set , unwrappedContextType);
298
- } else if (isMap && ! isIterable) {
291
+ _LiteralResolutionKind .set ,
292
+ unwrappedContextType,
293
+ );
294
+ }
295
+
296
+ // When `S` implements `Map` but not `Iterable`, `e` is a map literal.
297
+ if (isMap && ! isIterable) {
299
298
return _LiteralResolution (
300
- _LiteralResolutionKind .map, unwrappedContextType);
299
+ _LiteralResolutionKind .map,
300
+ unwrappedContextType,
301
+ );
301
302
}
302
303
}
304
+
303
305
return _LiteralResolution (_LiteralResolutionKind .ambiguous, null );
304
306
}
305
307
@@ -513,38 +515,54 @@ class TypedLiteralResolver {
513
515
} else if (canBeAMap && mustBeAMap) {
514
516
return _toMapType (literal, contextType, inferredTypes);
515
517
}
518
+
516
519
// Note: according to the spec, the following computations should be based
517
520
// on the greatest closure of the context type (unless the context type is
518
521
// `_`). In practice, we can just use the context type directly, because
519
522
// the only way the greatest closure of the context type could possibly have
520
523
// a different subtype relationship to `Iterable<Object>` and
521
524
// `Map<Object, Object>` is if the context type is `_`.
522
- bool contextProvidesAmbiguityResolutionClues =
523
- contextType != null && contextType is ! UnknownInferredType ;
524
- bool contextIsIterable = contextProvidesAmbiguityResolutionClues &&
525
- _typeSystem.isSubtypeOf2 (
526
- contextType, _typeProvider.iterableForSetMapDisambiguation);
527
- bool contextIsMap = contextProvidesAmbiguityResolutionClues &&
528
- _typeSystem.isSubtypeOf2 (
529
- contextType, _typeProvider.mapForSetMapDisambiguation);
530
- if (contextIsIterable && ! contextIsMap) {
531
- return _toSetType (literal, contextType, inferredTypes);
532
- } else if ((contextIsMap && ! contextIsIterable) || elements.isEmpty) {
533
- return _toMapType (literal, contextType, inferredTypes);
534
- } else {
535
- // Ambiguous. We're not going to get any more information to resolve the
536
- // ambiguity. We don't want to make an arbitrary decision at this point
537
- // because it will interfere with future type inference (see
538
- // dartbug.com/36210), so we return a type of `dynamic`.
539
- if (mustBeAMap && mustBeASet) {
540
- _errorReporter.reportErrorForNode (
541
- CompileTimeErrorCode .AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH , literal);
542
- } else {
543
- _errorReporter.reportErrorForNode (
544
- CompileTimeErrorCode .AMBIGUOUS_SET_OR_MAP_LITERAL_EITHER , literal);
525
+ if (contextType != null ) {
526
+ var contextIterableType = contextType.asInstanceOf (
527
+ _typeProvider.iterableElement,
528
+ );
529
+ var contextMapType = contextType.asInstanceOf (
530
+ _typeProvider.mapElement,
531
+ );
532
+ var contextIsIterable = contextIterableType != null ;
533
+ var contextIsMap = contextMapType != null ;
534
+
535
+ // When `S` implements `Iterable` but not `Map`, `e` is a set literal.
536
+ if (contextIsIterable && ! contextIsMap) {
537
+ return _toSetType (literal, contextType, inferredTypes);
545
538
}
546
- return _typeProvider.dynamicType;
539
+
540
+ // When `S` implements `Map` but not `Iterable`, `e` is a map literal.
541
+ if (contextIsMap && ! contextIsIterable) {
542
+ return _toMapType (literal, contextType, inferredTypes);
543
+ }
544
+ }
545
+
546
+ // When `e` is of the form `{}` and `S` is undefined, `e` is a map literal.
547
+ if (elements.isEmpty && contextType == null ) {
548
+ return _typeProvider.mapType2 (
549
+ DynamicTypeImpl .instance,
550
+ DynamicTypeImpl .instance,
551
+ );
552
+ }
553
+
554
+ // Ambiguous. We're not going to get any more information to resolve the
555
+ // ambiguity. We don't want to make an arbitrary decision at this point
556
+ // because it will interfere with future type inference (see
557
+ // dartbug.com/36210), so we return a type of `dynamic`.
558
+ if (mustBeAMap && mustBeASet) {
559
+ _errorReporter.reportErrorForNode (
560
+ CompileTimeErrorCode .AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH , literal);
561
+ } else {
562
+ _errorReporter.reportErrorForNode (
563
+ CompileTimeErrorCode .AMBIGUOUS_SET_OR_MAP_LITERAL_EITHER , literal);
547
564
}
565
+ return _typeProvider.dynamicType;
548
566
}
549
567
550
568
DartType _inferSetTypeDownwards (SetOrMapLiteral node, DartType contextType) {
0 commit comments