blob: 42e5686dd13a21294d9203adde9e3ba88c9e10b5 [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=spread-collections
// 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.identical(int, T);
return [];
}
Iterable<T> expectDynamicIterable<T>() {
Expect.identical(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.identical(int, K);
Expect.identical(String, V);
return {};
}
Map<K, V> expectDynamicDynamicMap<K, V>() {
Expect.identical(dynamic, K);
Expect.identical(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.identical(int, T);
return Set();
}
Set<T> expectDynamicSet<T>() {
Expect.identical(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()});
}