blob: 3d9773b36956476b942788c85881c99e58eded69 [file] [log] [blame]
// 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.
// SharedOptions=--enable-experiment=set-literals,control-flow-collections,spread-collections
// 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>>({if (true) ...[]});
Expect.type<Set<int>>({if (true) ...<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 not pushed into iterable.
Expect.listEquals(<int>[1], [for (int i in expectDynamic([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 (; false;) expectInt(1)]);
// Bottom up-inference from elements is not pushed back down into the body.
Expect.listEquals(<int>[1, 2], [1, for (; false;) expectDynamic(2)]);
// Maps.
// The context element type is pushed into the body.
Expect.mapEquals(<int, String>{1: "s"},
<int, String>{for (; false;) 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 (; false;) expectDynamic(2): expectDynamic("t")});
// Sets.
// The context element type is pushed into the body.
Expect.setEquals(<int>{1}, <int>{for (; false;) expectInt(1)});
// Bottom up-inference from elements is not pushed back down into the body.
Expect.setEquals(<int>{1, 2}, {1, for (; false;) expectDynamic(2)});
}