| // 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(); |
| 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)}); |
| } |