|  | // 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. | 
|  |  | 
|  | import "package:expect/expect.dart"; | 
|  |  | 
|  | R constFunction<T, R>(T _) => throw "uncalled"; | 
|  |  | 
|  | C<T> getC<T>() => const C(constFunction); | 
|  |  | 
|  | List<T> getList<T>() => const []; | 
|  |  | 
|  | Set<T> getSet<T>() => const {}; | 
|  |  | 
|  | Map<K, V> getMap<K, V>() => const {}; | 
|  |  | 
|  | R Function(T) getFunction<T, R>() { | 
|  | List<R Function(T)> list = const [constFunction]; | 
|  | return list[0]; | 
|  | } | 
|  |  | 
|  | C<T> getImplicitConstC<T>() { | 
|  | List<C<T>> list = const [C(constFunction)]; | 
|  | return list[0]; | 
|  | } | 
|  |  | 
|  | List<T> getImplicitConstList<T>() { | 
|  | List<List<T>> list = const [[]]; | 
|  | return list[0]; | 
|  | } | 
|  |  | 
|  | Set<T> getImplicitConstSet<T>() { | 
|  | List<Set<T>> list = const [{}]; | 
|  | return list[0]; | 
|  | } | 
|  |  | 
|  | Map<K, V> getImplicitConstMap<K, V>() { | 
|  | List<Map<K, V>> list = const [{}]; | 
|  | return list[0]; | 
|  | } | 
|  |  | 
|  | class C<T> { | 
|  | final Object fn; | 
|  | const C(T Function(T) this.fn); | 
|  | } | 
|  |  | 
|  | void expectOfType<T>(Object obj) { | 
|  | // An exact type test would be better, but since `Never` is a subtype of all | 
|  | // types that can be written in Dart, it should not matter in practice. | 
|  | // | 
|  | // (`obj.runtimeType == T` does not work for List/Map/Sets because the runtime | 
|  | // type is an implementation-specific subtype of those interfaces.) | 
|  | Expect.isTrue(obj is T, "`$obj` should be of type `$T`"); | 
|  | } | 
|  |  | 
|  | testClassInstance() { | 
|  | expectOfType<C<Never>>(getC<int>()); | 
|  | expectOfType<C<Never>>(getC<String>()); | 
|  | expectOfType<C<Never>>(getC()); | 
|  | } | 
|  |  | 
|  | testImplicitConstClassInstance() { | 
|  | expectOfType<C<Never>>(getImplicitConstC<int>()); | 
|  | expectOfType<C<Never>>(getImplicitConstC<String>()); | 
|  | expectOfType<C<Never>>(getImplicitConstC()); | 
|  | } | 
|  |  | 
|  | testDownwardsClassInference() { | 
|  | expectOfType<Never Function(Never)>(getC<int>().fn); | 
|  | expectOfType<Never Function(Never)>(getC<String>().fn); | 
|  | expectOfType<Never Function(Never)>(getC().fn); | 
|  | } | 
|  |  | 
|  | testList() { | 
|  | expectOfType<List<Never>>(getList<int>()); | 
|  | expectOfType<List<Never>>(getList<String>()); | 
|  | expectOfType<List<Never>>(getList()); | 
|  | } | 
|  |  | 
|  | testImplicitConstList() { | 
|  | expectOfType<List<Never>>(getImplicitConstList<int>()); | 
|  | expectOfType<List<Never>>(getImplicitConstList<String>()); | 
|  | expectOfType<List<Never>>(getImplicitConstList()); | 
|  | } | 
|  |  | 
|  | testImplicitConstSet() { | 
|  | expectOfType<Set<Never>>(getImplicitConstSet<int>()); | 
|  | expectOfType<Set<Never>>(getImplicitConstSet<String>()); | 
|  | expectOfType<Set<Never>>(getImplicitConstSet()); | 
|  | } | 
|  |  | 
|  | testSet() { | 
|  | expectOfType<Set<Never>>(getSet<int>()); | 
|  | expectOfType<Set<Never>>(getSet<String>()); | 
|  | expectOfType<Set<Never>>(getSet()); | 
|  | } | 
|  |  | 
|  | testMap() { | 
|  | expectOfType<Map<Never, Never>>(getMap<int, int>()); | 
|  | expectOfType<Map<Never, Never>>(getMap<int, String>()); | 
|  | expectOfType<Map<Never, Never>>(getMap<String, int>()); | 
|  | expectOfType<Map<Never, Never>>(getMap<String, String>()); | 
|  | expectOfType<Map<Never, Never>>(getMap<Never, Never>()); | 
|  | expectOfType<Map<Never, Never>>(getMap()); | 
|  | } | 
|  |  | 
|  | testImplicitConstMap() { | 
|  | expectOfType<Map<Never, Never>>(getImplicitConstMap<int, int>()); | 
|  | expectOfType<Map<Never, Never>>(getImplicitConstMap<int, String>()); | 
|  | expectOfType<Map<Never, Never>>(getImplicitConstMap<String, int>()); | 
|  | expectOfType<Map<Never, Never>>(getImplicitConstMap<String, String>()); | 
|  | expectOfType<Map<Never, Never>>(getImplicitConstMap<Never, Never>()); | 
|  | expectOfType<Map<Never, Never>>(getImplicitConstMap()); | 
|  | } | 
|  |  | 
|  | testFunction() { | 
|  | expectOfType<Never Function(Object?)>(getFunction<int, int>()); | 
|  | expectOfType<Never Function(Object?)>(getFunction<int, String>()); | 
|  | expectOfType<Never Function(Object?)>(getFunction<String, int>()); | 
|  | expectOfType<Never Function(Object?)>(getFunction<String, String>()); | 
|  | expectOfType<Never Function(Object?)>(getFunction<Never, Never>()); | 
|  | expectOfType<Never Function(Object?)>(getFunction()); | 
|  | } | 
|  |  | 
|  | /// Tests that use type inference for constants do not reference the type | 
|  | /// parameter. Instead, free type parameters are substituted to obtain the | 
|  | /// least closure (e.g. `List<T>` becomes `List<Never>` and `R Function(T)` | 
|  | /// becomes `Never Function(Object)`). | 
|  | main() { | 
|  | testClassInstance(); | 
|  | testImplicitConstClassInstance(); | 
|  | testDownwardsClassInference(); | 
|  | testList(); | 
|  | testImplicitConstList(); | 
|  | testSet(); | 
|  | testImplicitConstSet(); | 
|  | testMap(); | 
|  | testImplicitConstMap(); | 
|  | testFunction(); | 
|  | } |