// 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>([for (; false;) 1]); Expect.type>([for (; false;) 1, for (; false;) 2]); Expect.type>([for (; false;) 1, for (; false;) 0.2]); Expect.type>([for (; false;) 1, 2]); Expect.type>([for (; false;) 1, 0.2]); Expect.type>([for (; false;) ...[]]); Expect.type>([for (; false;) ...[]]); // Maps. Expect.type>({for (; false;) 1: 1}); Expect.type>({for (; false;) 1: 1, for (; false;) 2: 2}); Expect.type>({for (; false;) 1: 0.1, for (; false;) 0.2: 2}); Expect.type>({for (; false;) 1: 1, 2: 2}); Expect.type>({for (; false;) 1: 0.1, 0.2: 2}); Expect.type>({for (; false;) ...{}}); Expect.type>({for (; false;) ...{}}); // Sets. Expect.type>({for (; false;) 1}); Expect.type>({for (; false;) 1, for (; false;) 2}); Expect.type>({for (; false;) 1, for (; false;) 0.2}); Expect.type>({for (; false;) 1, 2}); Expect.type>({for (; false;) 1, 0.2}); Expect.type>({for (; false;) ...[]}); Expect.type>({for (; false;) ...[]}); // If a nested iterable's type is dynamic, the element type is dynamic. Expect.type>([for (; false;) ...([] as dynamic)]); Expect.type>({1, for (; false;) ...([] as dynamic)}); // If a nested maps's type is dynamic, the key and value types are dynamic. Expect.type>({1: 1, for (; false;) ...({} as dynamic)}); } void testLoopVariableInference() { // Infers loop variable from iterable. Expect.type>([for (var i in [1]) i]); Expect.type>([for (var i in [1]) i.toRadixString(10)]); // Infers loop variable from initializer. Expect.type>([for (var i = 1; i < 2; i++) i]); Expect.type>([for (var i = 1; i < 2; i++) i.toRadixString(10)]); // Loop variable type is pushed into sequence. Expect.listEquals([1], [for (int i in expectIntIterable([1])) i]); // Loop variable type is pushed into initializer. Expect.listEquals([1], [for (int i = expectInt(1); i < 2; i++) i]); } void testTopDownInference() { // Lists. // The context element type is pushed into the body. Expect.listEquals([1], [for (var i = 0; i < 1; i++) expectInt(1)]); // Bottom up-inference from elements is not pushed back down into the body. Expect.listEquals([1, 2], [1, for (var i = 0; i < 1; i++) expectDynamic(2)]); // Maps. // The context element type is pushed into the body. Expect.mapEquals({1: "s"}, { 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({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({1}, {for (var i = 0; i < 1; i++) expectInt(1)}); // Bottom up-inference from elements is not pushed back down into the body. Expect.setEquals({1, 2}, {1, for (var i = 0; i < 1; i++) expectDynamic(2)}); }