da4ccd0855
This brings Analyzer's type inference in line with the language spec. Similar to CFE, the inference function now takes an isConst parameter, which if set, tells it to eliminate type variables from the context type. Change-Id: Ied67bac39d73c9ecd7e0a482a0c8db77272637cc Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/98707 Reviewed-by: Paul Berry <paulberry@google.com> Commit-Queue: Jenny Messerly <jmesserly@google.com>
141 lines
4.2 KiB
Dart
141 lines
4.2 KiB
Dart
// 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 _) => null;
|
|
|
|
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 `Null` is a subtype of all
|
|
// types that can be written in Dart 2.0, 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<Null>>(getC<int>());
|
|
expectOfType<C<Null>>(getC<String>());
|
|
expectOfType<C<Null>>(getC());
|
|
}
|
|
|
|
testImplicitConstClassInstance() {
|
|
expectOfType<C<Null>>(getImplicitConstC<int>());
|
|
expectOfType<C<Null>>(getImplicitConstC<String>());
|
|
expectOfType<C<Null>>(getImplicitConstC());
|
|
}
|
|
|
|
testDownwardsClassInference() {
|
|
expectOfType<Null Function(Null)>(getC<int>().fn);
|
|
expectOfType<Null Function(Null)>(getC<String>().fn);
|
|
expectOfType<Null Function(Null)>(getC().fn);
|
|
}
|
|
|
|
testList() {
|
|
expectOfType<List<Null>>(getList<int>());
|
|
expectOfType<List<Null>>(getList<String>());
|
|
expectOfType<List<Null>>(getList());
|
|
}
|
|
|
|
testImplicitConstList() {
|
|
expectOfType<List<Null>>(getImplicitConstList<int>());
|
|
expectOfType<List<Null>>(getImplicitConstList<String>());
|
|
expectOfType<List<Null>>(getImplicitConstList());
|
|
}
|
|
|
|
testImplicitConstSet() {
|
|
expectOfType<Set<Null>>(getImplicitConstSet<int>());
|
|
expectOfType<Set<Null>>(getImplicitConstSet<String>());
|
|
expectOfType<Set<Null>>(getImplicitConstSet());
|
|
}
|
|
|
|
testSet() {
|
|
expectOfType<Set<Null>>(getSet<int>());
|
|
expectOfType<Set<Null>>(getSet<String>());
|
|
expectOfType<Set<Null>>(getSet());
|
|
}
|
|
|
|
testMap() {
|
|
expectOfType<Map<Null, Null>>(getMap<int, int>());
|
|
expectOfType<Map<Null, Null>>(getMap<int, String>());
|
|
expectOfType<Map<Null, Null>>(getMap<String, int>());
|
|
expectOfType<Map<Null, Null>>(getMap<String, String>());
|
|
expectOfType<Map<Null, Null>>(getMap<Null, Null>());
|
|
expectOfType<Map<Null, Null>>(getMap());
|
|
}
|
|
|
|
testImplicitConstMap() {
|
|
expectOfType<Map<Null, Null>>(getImplicitConstMap<int, int>());
|
|
expectOfType<Map<Null, Null>>(getImplicitConstMap<int, String>());
|
|
expectOfType<Map<Null, Null>>(getImplicitConstMap<String, int>());
|
|
expectOfType<Map<Null, Null>>(getImplicitConstMap<String, String>());
|
|
expectOfType<Map<Null, Null>>(getImplicitConstMap<Null, Null>());
|
|
expectOfType<Map<Null, Null>>(getImplicitConstMap());
|
|
}
|
|
|
|
testFunction() {
|
|
expectOfType<Null Function(Object)>(getFunction<int, int>());
|
|
expectOfType<Null Function(Object)>(getFunction<int, String>());
|
|
expectOfType<Null Function(Object)>(getFunction<String, int>());
|
|
expectOfType<Null Function(Object)>(getFunction<String, String>());
|
|
expectOfType<Null Function(Object)>(getFunction<Null, Null>());
|
|
expectOfType<Null Function(Object)>(getFunction());
|
|
}
|
|
|
|
/// Tests that type inference for constants does not reference the type
|
|
/// parameter. Instead, free type parameters should substituted to obtain the
|
|
/// least closure (e.g. `List<T>` becomes `List<Null>` and `R Function(T)`
|
|
/// becomes `Null Function(Object)`).
|
|
main() {
|
|
testClassInstance();
|
|
testImplicitConstClassInstance();
|
|
testDownwardsClassInference();
|
|
testList();
|
|
testImplicitConstList();
|
|
testSet();
|
|
testImplicitConstSet();
|
|
testMap();
|
|
testImplicitConstMap();
|
|
testFunction();
|
|
}
|