|  | // 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. | 
|  |  | 
|  | // Test how control flow interacts with inference. | 
|  | import 'package:expect/expect.dart'; | 
|  |  | 
|  | import 'utils.dart'; | 
|  |  | 
|  | void main() { | 
|  | testBottomUpInference(); | 
|  | testTopDownInference(); | 
|  | } | 
|  |  | 
|  | void testBottomUpInference() { | 
|  | // Lists. | 
|  | expectListOf<int>([if (true) 1]); | 
|  | expectListOf<int>([if (true) 1 else 2]); | 
|  | expectListOf<num>([if (true) 1 else 0.2]); | 
|  | expectListOf<int>([if (true) 1, 2]); | 
|  | expectListOf<num>([if (true) 1, 0.2]); | 
|  | expectListOf<dynamic>([if (true) ...[]]); | 
|  | expectListOf<int>([if (true) ...<int>[]]); | 
|  |  | 
|  | // Maps. | 
|  | expectMapOf<int, int>({if (true) 1: 1}); | 
|  | expectMapOf<int, int>({if (true) 1: 1 else 2: 2}); | 
|  | expectMapOf<num, num>({if (true) 1: 0.1 else 0.2: 2}); | 
|  | expectMapOf<int, int>({if (true) 1: 1, 2: 2}); | 
|  | expectMapOf<num, num>({if (true) 1: 0.1, 0.2: 2}); | 
|  | expectMapOf<dynamic, dynamic>({if (true) ...{}}); | 
|  | expectMapOf<int, int>({if (true) ...<int, int>{}}); | 
|  |  | 
|  | // Sets. | 
|  | expectSetOf<int>({if (true) 1}); | 
|  | expectSetOf<int>({if (true) 1 else 2}); | 
|  | expectSetOf<num>({if (true) 1 else 0.2}); | 
|  | expectSetOf<int>({if (true) 1, 2}); | 
|  | expectSetOf<num>({if (true) 1, 0.2}); | 
|  | expectSetOf<dynamic>({if (true) ...[]}); | 
|  | expectSetOf<int>({if (true) ...<int>[]}); | 
|  |  | 
|  | // If a nested iterable's type is dynamic, the element type is dynamic. | 
|  | expectListOf<dynamic>([if (true) ...([] as dynamic)]); | 
|  | expectSetOf<dynamic>({1, if (true) ...([] as dynamic)}); | 
|  |  | 
|  | // If a nested maps's type is dynamic, the key and value types are dynamic. | 
|  | expectMapOf<dynamic, dynamic>({1: 1, if (true) ...({} as dynamic)}); | 
|  | } | 
|  |  | 
|  | void testTopDownInference() { | 
|  | // Lists. | 
|  |  | 
|  | // The context element type is pushed into the branches. | 
|  | Expect.listEquals(<int>[1], <int>[if (true) expectInt(1)]); | 
|  | Expect.listEquals(<int>[1], <int>[if (false) 9 else expectInt(1)]); | 
|  |  | 
|  | // Bottom up-inference from elements is not pushed back down into branches. | 
|  | Expect.listEquals(<int>[1, 2], [1, if (true) expectDynamic(2)]); | 
|  | Expect.listEquals(<int>[1, 2], [1, if (false) 9 else expectDynamic(2)]); | 
|  |  | 
|  | // Maps. | 
|  |  | 
|  | // The context element type is pushed into the branches. | 
|  | Expect.mapEquals(<int, String>{1: "s"}, | 
|  | <int, String>{if (true) expectInt(1): expectString("s")}); | 
|  |  | 
|  | // Bottom up-inference from elements is not pushed back down into branches. | 
|  | Expect.mapEquals(<int, String>{1: "s", 2: "t"}, | 
|  | {1: "s", if (true) expectDynamic(2): expectDynamic("t")}); | 
|  |  | 
|  | // Sets. | 
|  |  | 
|  | // The context element type is pushed into the branches. | 
|  | Expect.setEquals(<int>{1}, <int>{if (true) expectInt(1)}); | 
|  | Expect.setEquals(<int>{1}, <int>{if (false) 9 else expectInt(1)}); | 
|  |  | 
|  | // Bottom up-inference from elements is not pushed back down into branches. | 
|  | Expect.setEquals(<int>{1, 2}, {1, if (true) expectDynamic(2)}); | 
|  | Expect.setEquals(<int>{1, 2}, {1, if (false) 9 else expectDynamic(2)}); | 
|  | } |