blob: 4e022e022c161573684ec4de2308aca17ed47326 [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.
// 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)});
}