|  | // Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file | 
|  | // for details. All rights reserved. Use of this source code is governed by a | 
|  | // BSD-style license that can be found in the LICENSE file. | 
|  |  | 
|  | // @dart = 2.9 | 
|  |  | 
|  | // Test how control flow interacts with inference. | 
|  | import 'package:expect/expect.dart'; | 
|  |  | 
|  | import 'utils.dart'; | 
|  |  | 
|  | void main() { | 
|  | testBottomUpInference(); | 
|  | testLoopVariableInference(); | 
|  | testTopDownInference(); | 
|  | } | 
|  |  | 
|  | void testBottomUpInference() { | 
|  | // Lists. | 
|  | Expect.type<List<int>>([for (; false;) 1]); | 
|  | Expect.type<List<int>>([for (; false;) 1, for (; false;) 2]); | 
|  | Expect.type<List<num>>([for (; false;) 1, for (; false;) 0.2]); | 
|  | Expect.type<List<int>>([for (; false;) 1, 2]); | 
|  | Expect.type<List<num>>([for (; false;) 1, 0.2]); | 
|  | Expect.type<List<dynamic>>([for (; false;) ...[]]); | 
|  | Expect.type<List<int>>([for (; false;) ...<int>[]]); | 
|  |  | 
|  | // Maps. | 
|  | Expect.type<Map<int, int>>({for (; false;) 1: 1}); | 
|  | Expect.type<Map<int, int>>({for (; false;) 1: 1, for (; false;) 2: 2}); | 
|  | Expect.type<Map<num, num>>({for (; false;) 1: 0.1, for (; false;) 0.2: 2}); | 
|  | Expect.type<Map<int, int>>({for (; false;) 1: 1, 2: 2}); | 
|  | Expect.type<Map<num, num>>({for (; false;) 1: 0.1, 0.2: 2}); | 
|  | Expect.type<Map<dynamic, dynamic>>({for (; false;) ...{}}); | 
|  | Expect.type<Map<int, int>>({for (; false;) ...<int, int>{}}); | 
|  |  | 
|  | // Sets. | 
|  | Expect.type<Set<int>>({for (; false;) 1}); | 
|  | Expect.type<Set<int>>({for (; false;) 1, for (; false;) 2}); | 
|  | Expect.type<Set<num>>({for (; false;) 1, for (; false;) 0.2}); | 
|  | Expect.type<Set<int>>({for (; false;) 1, 2}); | 
|  | Expect.type<Set<num>>({for (; false;) 1, 0.2}); | 
|  | Expect.type<Set<dynamic>>({for (; false;) ...[]}); | 
|  | Expect.type<Set<int>>({for (; false;) ...<int>[]}); | 
|  |  | 
|  | // If a nested iterable's type is dynamic, the element type is dynamic. | 
|  | Expect.type<List<dynamic>>([for (; false;) ...([] as dynamic)]); | 
|  | Expect.type<Set<dynamic>>({1, for (; false;) ...([] as dynamic)}); | 
|  |  | 
|  | // If a nested maps's type is dynamic, the key and value types are dynamic. | 
|  | Expect.type<Map<dynamic, dynamic>>({1: 1, for (; false;) ...({} as dynamic)}); | 
|  | } | 
|  |  | 
|  | void testLoopVariableInference() { | 
|  | // Infers loop variable from iterable. | 
|  | Expect.type<List<int>>([for (var i in <int>[1]) i]); | 
|  | Expect.type<List<String>>([for (var i in <int>[1]) i.toRadixString(10)]); | 
|  |  | 
|  | // Infers loop variable from initializer. | 
|  | Expect.type<List<int>>([for (var i = 1; i < 2; i++) i]); | 
|  | Expect.type<List<String>>([for (var i = 1; i < 2; i++) i.toRadixString(10)]); | 
|  |  | 
|  | // Loop variable type is pushed into sequence. | 
|  | Expect.listEquals(<int>[1], [for (int i in expectIntIterable([1])) i]); | 
|  |  | 
|  | // Loop variable type is pushed into initializer. | 
|  | Expect.listEquals(<int>[1], [for (int i = expectInt(1); i < 2; i++) i]); | 
|  | } | 
|  |  | 
|  | void testTopDownInference() { | 
|  | // Lists. | 
|  |  | 
|  | // The context element type is pushed into the body. | 
|  | Expect.listEquals(<int>[1], <int>[for (var i = 0; i < 1; i++) expectInt(1)]); | 
|  |  | 
|  | // Bottom up-inference from elements is not pushed back down into the body. | 
|  | Expect.listEquals(<int>[1, 2], | 
|  | [1, for (var i = 0; i < 1; i++) expectDynamic(2)]); | 
|  |  | 
|  | // Maps. | 
|  |  | 
|  | // The context element type is pushed into the body. | 
|  | Expect.mapEquals(<int, String>{1: "s"}, <int, String>{ | 
|  | for (var i = 0; i < 1; i++) expectInt(1): expectString("s") | 
|  | }); | 
|  |  | 
|  | // Bottom up-inference from elements is not pushed back down into the body. | 
|  | Expect.mapEquals(<int, String>{1: "s", 2: "t"}, { | 
|  | 1: "s", | 
|  | for (var i = 0; i < 1; i++) expectDynamic(2): expectDynamic("t") | 
|  | }); | 
|  |  | 
|  | // Sets. | 
|  |  | 
|  | // The context element type is pushed into the body. | 
|  | Expect.setEquals(<int>{1}, <int>{for (var i = 0; i < 1; i++) expectInt(1)}); | 
|  |  | 
|  | // Bottom up-inference from elements is not pushed back down into the body. | 
|  | Expect.setEquals(<int>{1, 2}, | 
|  | {1, for (var i = 0; i < 1; i++) expectDynamic(2)}); | 
|  | } |