blob: 02598598387e1d2ba4ada32c18f4b185076ed28a [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 spread interacts with inference.
import 'package:expect/expect.dart';
void main() {
testBottomUpInference();
testTopDownInference();
}
void testBottomUpInference() {
// Lists.
Expect.type<List<dynamic>>([...[]]);
Expect.type<List<int>>([...<int>[]]);
Expect.type<List<int>>([
...[1],
]);
Expect.type<List<int>>([
1,
...[2],
]);
Expect.type<List<num>>([
1,
...[0.2],
]);
Expect.type<List<int>>([
...[1, 2],
]);
Expect.type<List<num>>([
...[1, 0.2],
]);
Expect.type<List<int>>([
...[1],
...[2],
]);
Expect.type<List<num>>([
...[1],
...[0.2],
]);
// Maps.
Expect.type<Map<dynamic, dynamic>>({...{}});
Expect.type<Map<int, int>>({...<int, int>{}});
Expect.type<Map<int, int>>({
...{1: 1},
});
Expect.type<Map<int, int>>({
1: 1,
...{2: 2},
});
Expect.type<Map<num, num>>({
1: 1,
...{0.2: 0.2},
});
Expect.type<Map<int, int>>({
...{1: 1, 2: 2},
});
Expect.type<Map<num, num>>({
...{1: 1, 0.2: 0.2},
});
Expect.type<Map<int, int>>({
...{1: 1},
...{2: 2},
});
Expect.type<Map<num, num>>({
...{1: 1},
...{0.2: 0.2},
});
// Sets.
Expect.type<Set<dynamic>>({...[]});
Expect.type<Set<int>>({...<int>[]});
Expect.type<Set<int>>({
...[1],
});
Expect.type<Set<int>>({
1,
...[2],
});
Expect.type<Set<num>>({
1,
...[0.2],
});
Expect.type<Set<int>>({
...[1, 2],
});
Expect.type<Set<num>>({
...[1, 0.2],
});
Expect.type<Set<int>>({
...[1],
...[2],
});
Expect.type<Set<num>>({
...[1],
...[0.2],
});
Expect.type<Set<num>>({
...{1},
...[0.2],
});
Expect.type<Set<num>>({
...{1},
...{0.2},
});
// If the iterable's type is dynamic, the element type is inferred as dynamic.
Expect.type<List<dynamic>>([...([] as dynamic)]);
Expect.type<Set<dynamic>>({1, ...([] as dynamic)});
// If the iterable's type is dynamic, the key and value types are inferred as
// dynamic.
Expect.type<Map<dynamic, dynamic>>({1: 1, ...({} as dynamic)});
}
void testTopDownInference() {
// Lists.
Iterable<T> expectIntIterable<T>() {
Expect.equals(int, T);
return [];
}
Iterable<T> expectDynamicIterable<T>() {
Expect.equals(dynamic, T);
return [];
}
// The context element type is pushed into the spread expression if it is
// Iterable<T>.
Expect.listEquals(<int>[], <int>[...expectIntIterable()]);
// Bottom up-inference from elements is not pushed back down into spread.
Expect.listEquals(<int>[1], [1, ...expectDynamicIterable()]);
// Maps.
Map<K, V> expectIntStringMap<K, V>() {
Expect.equals(int, K);
Expect.equals(String, V);
return {};
}
Map<K, V> expectDynamicDynamicMap<K, V>() {
Expect.equals(dynamic, K);
Expect.equals(dynamic, V);
return {};
}
// The context element type is pushed into the spread expression if it is
// Map<K, V>.
Expect.mapEquals(<int, String>{}, <int, String>{...expectIntStringMap()});
// Bottom up-inference from elements is not pushed back down into spread.
Expect.mapEquals(
<int, String>{1: "s"},
{1: "s", ...expectDynamicDynamicMap()},
);
// Sets.
Set<T> expectIntSet<T>() {
Expect.equals(int, T);
return Set();
}
Set<T> expectDynamicSet<T>() {
Expect.equals(dynamic, T);
return Set();
}
// The context element type is pushed into the spread expression if it is
// Iterable<T>.
Expect.setEquals(<int>{}, <int>{...expectIntSet()});
// Bottom up-inference from elements is not pushed back down into spread.
Expect.setEquals(<int>{1}, {1, ...expectDynamicSet()});
}