Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(884)

Unified Diff: pkg/analyzer/test/generated/strong_mode_test.dart

Issue 2653833003: Strong mode inference tests. (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/analyzer/test/generated/strong_mode_driver_test.dart ('k') | pkg/analyzer/test/utils.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/test/generated/strong_mode_test.dart
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index 81f02697c62e11cc1be282377edf02fe7427461a..2dd77c61888126eb6ecfe69342e4994a9ec03e2b 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -22,17 +22,17 @@ import 'resolver_test_case.dart';
main() {
defineReflectiveSuite(() {
- defineReflectiveTests(StrongModeDownwardsInferenceTest);
+ defineReflectiveTests(StrongModeLocalInferenceTest);
defineReflectiveTests(StrongModeStaticTypeAnalyzer2Test);
defineReflectiveTests(StrongModeTypePropagationTest);
});
}
/**
- * Strong mode static analyzer downwards inference tests
+ * Strong mode static analyzer local type inference tests
*/
@reflectiveTest
-class StrongModeDownwardsInferenceTest extends ResolverTestCase {
+class StrongModeLocalInferenceTest extends ResolverTestCase {
TypeAssertions _assertions;
Asserter<DartType> _isDynamic;
@@ -40,6 +40,7 @@ class StrongModeDownwardsInferenceTest extends ResolverTestCase {
Asserter<InterfaceType> _isFutureOfInt;
Asserter<DartType> _isInt;
Asserter<DartType> _isNum;
+ Asserter<DartType> _isObject;
Asserter<DartType> _isString;
AsserterBuilder2<Asserter<DartType>, Asserter<DartType>, DartType>
@@ -66,6 +67,7 @@ class StrongModeDownwardsInferenceTest extends ResolverTestCase {
_isInstantiationOf = _assertions.isInstantiationOf;
_isInt = _assertions.isInt;
_isNum = _assertions.isNum;
+ _isObject = _assertions.isObject;
_isString = _assertions.isString;
_isDynamic = _assertions.isDynamic;
_isListOf = _assertions.isListOf;
@@ -80,6 +82,176 @@ class StrongModeDownwardsInferenceTest extends ResolverTestCase {
return result;
}
+ fail_constrainedByBounds3() async {
+ // Test that upwards inference with two type variables does
+ // not propogate from the constrained variable to the unconstrained
+ // variable if they are ordered right to left, and that if the result
+ // is not a valid instantiation an error is issued
+ String code = r'''
+ T f<T extends S, S extends int>(S x) => null;
+ void test() { var x = f(3); }
+ ''';
+ Source source = addSource(code);
+ TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+ assertErrors(
+ source, [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
Jennifer Messerly 2017/01/24 19:03:35 might be worth a comment that the error is what we
Leaf 2017/01/24 19:23:30 I think that's already in the comment, and in the
+ verify([source]);
+ CompilationUnit unit = analysisResult.unit;
+ List<Statement> statements =
+ AstFinder.getStatementsInTopLevelFunction(unit, "test");
+ VariableDeclarationStatement stmt = statements[0];
+ VariableDeclaration decl = stmt.variables.variables[0];
+ Expression call = decl.initializer;
+ _isDynamic(call.staticType);
+ }
+
+ fail_constrainedByBounds5() async {
+ // Test that upwards inference with two type variables does not
+ // propogate from the constrained variable to the unconstrained
+ // variable if they are ordered right to left, when the variable
+ // appears co and contra variantly, and that an error is issued
+ // for the non-matching bound.
+ String code = r'''
+ typedef To Func1<From, To>(From x);
+ T f<T extends Func1<S, S>, S>(S x) => null;
+ void test() { var x = f(3)(4); }
+ ''';
+ Source source = addSource(code);
+ TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+ assertErrors(
+ source, [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+ verify([source]);
+ CompilationUnit unit = analysisResult.unit;
+ List<Statement> statements =
+ AstFinder.getStatementsInTopLevelFunction(unit, "test");
+ VariableDeclarationStatement stmt = statements[0];
+ VariableDeclaration decl = stmt.variables.variables[0];
+ Expression call = decl.initializer;
+ _isInt(call.staticType);
+ }
+
+ fail_pinning_multipleConstraints1() async {
+ // Test that downwards inference with two different downwards covariant
+ // constraints on the same parameter correctly fails to infer when
+ // the types do not share a common subtype
+ String code = r'''
+ class A<S, T> {
+ S s;
+ T t;
+ }
+ class B<S> extends A<S, S> { B(S s); }
+ A<int, String> test() => new B(3);
+ ''';
+ Source source = addSource(code);
+ TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+ assertErrors(source, [StrongModeCode.COULD_NOT_INFER]);
+ verify([source]);
+ CompilationUnit unit = analysisResult.unit;
+ FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, "test");
+ ExpressionFunctionBody body = test.functionExpression.body;
+ DartType type = body.expression.staticType;
+
+ Element elementB = AstFinder.getClass(unit, "B").element;
+
+ _isInstantiationOf(_hasElement(elementB))([_isDynamic])(type);
Jennifer Messerly 2017/01/24 19:03:35 FYI: we don't pick "dynamic" in case of inference
Leaf 2017/01/24 19:23:30 Are you saying the expectation of B<dynamic> is wr
+ }
+
+ fail_pinning_multipleConstraints2() async {
+ // Test that downwards inference with two identical downwards covariant
+ // constraints on the same parameter correctly infers and pins the type
+ String code = r'''
+ class A<S, T> {
+ S s;
+ T t;
+ }
+ class B<S> extends A<S, S> { B(S s); }
+ A<num, num> test() => new B(3);
+ ''';
+ Source source = addSource(code);
+ TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ CompilationUnit unit = analysisResult.unit;
+ FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, "test");
+ ExpressionFunctionBody body = test.functionExpression.body;
+ DartType type = body.expression.staticType;
+
+ Element elementB = AstFinder.getClass(unit, "B").element;
+
+ _isInstantiationOf(_hasElement(elementB))([_isNum])(type);
+ }
+
+ fail_pinning_multipleConstraints3() async {
+ // Test that downwards inference with two different downwards covariant
+ // constraints on the same parameter correctly fails to infer when
+ // the types do not share a common subtype, but do share a common supertype
+ String code = r'''
+ class A<S, T> {
+ S s;
+ T t;
+ }
+ class B<S> extends A<S, S> { B(S s); }
+ A<int, double> test() => new B(3);
+ ''';
+ Source source = addSource(code);
+ TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+ assertErrors(source, [
+ StrongModeCode.COULD_NOT_INFER,
+ StaticTypeWarningCode.RETURN_OF_INVALID_TYPE
+ ]);
+ verify([source]);
+ CompilationUnit unit = analysisResult.unit;
+ FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, "test");
+ ExpressionFunctionBody body = test.functionExpression.body;
+ DartType type = body.expression.staticType;
+
+ Element elementB = AstFinder.getClass(unit, "B").element;
+
+ _isInstantiationOf(_hasElement(elementB))([_isDynamic])(type);
+ }
+
+ fail_returnType_variance2() async {
+ // Check that downwards inference correctly pins a type parameter
+ // when the parameter is constrained in a covariant position
+ String code = r'''
+ typedef To Func1<From, To>(From x);
+ Func1<String, T> f<T>(T x) => null;
+ Func1<String, num> test() => f(42);
+ ''';
+ Source source = addSource(code);
+ TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ CompilationUnit unit = analysisResult.unit;
+ FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, "test");
+ ExpressionFunctionBody body = test.functionExpression.body;
+ MethodInvocation invoke = body.expression;
+ _isFunction2Of(_isNum, _isFunction2Of(_isString, _isNum))(
+ invoke.staticInvokeType);
+ }
+
+ fail_returnType_variance6() async {
+ // Check that pinning works correctly with a partial type
+ // when the return type uses the variable in a covariant position
+ String code = r'''
+ typedef To Func1<From, To>(From x);
+ Func1<String, T> f<T>(T x) => null;
+ T g<T, S>(Func1<S, T> f) => null;
+ num test() => g(f(3));
+ ''';
+ Source source = addSource(code);
+ TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ CompilationUnit unit = analysisResult.unit;
+ FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, "test");
+ ExpressionFunctionBody body = test.functionExpression.body;
+ MethodInvocation call = body.expression;
+ _isNum(call.staticType);
+ _isFunction2Of(_isFunction2Of(_isString, _isNum), _isNum)(
+ call.staticInvokeType);
+ }
+
@override
void setUp() {
super.setUp();
@@ -287,6 +459,71 @@ class StrongModeDownwardsInferenceTest extends ResolverTestCase {
expect(f0.type.normalParameterTypes[0], typeProvider.intType);
}
+ test_constrainedByBounds1() async {
+ // Test that upwards inference with two type variables correctly
+ // propogates from the constrained variable to the unconstrained
+ // variable if they are ordered left to right.
+ String code = r'''
+ T f<S, T extends S>(S x) => null;
+ void test() { var x = f(3); }
+ ''';
+ Source source = addSource(code);
+ TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ CompilationUnit unit = analysisResult.unit;
+ List<Statement> statements =
+ AstFinder.getStatementsInTopLevelFunction(unit, "test");
+ VariableDeclarationStatement stmt = statements[0];
+ VariableDeclaration decl = stmt.variables.variables[0];
+ Expression call = decl.initializer;
+ _isInt(call.staticType);
+ }
+
+ test_constrainedByBounds2() async {
+ // Test that upwards inference with two type variables does
+ // not propogate from the constrained variable to the unconstrained
+ // variable if they are ordered right to left.
+ String code = r'''
+ T f<T extends S, S>(S x) => null;
+ void test() { var x = f(3); }
+ ''';
+ Source source = addSource(code);
+ TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ CompilationUnit unit = analysisResult.unit;
+ List<Statement> statements =
+ AstFinder.getStatementsInTopLevelFunction(unit, "test");
+ VariableDeclarationStatement stmt = statements[0];
+ VariableDeclaration decl = stmt.variables.variables[0];
+ Expression call = decl.initializer;
+ _isDynamic(call.staticType);
+ }
+
+ test_constrainedByBounds4() async {
+ // Test that upwards inference with two type variables correctly
+ // propogates from the constrained variable to the unconstrained
+ // variable if they are ordered left to right, when the variable
+ // appears co and contra variantly
+ String code = r'''
+ typedef To Func1<From, To>(From x);
+ T f<S, T extends Func1<S, S>>(S x) => null;
+ void test() { var x = f(3)(4); }
+ ''';
+ Source source = addSource(code);
+ TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ CompilationUnit unit = analysisResult.unit;
+ List<Statement> statements =
+ AstFinder.getStatementsInTopLevelFunction(unit, "test");
+ VariableDeclarationStatement stmt = statements[0];
+ VariableDeclaration decl = stmt.variables.variables[0];
+ Expression call = decl.initializer;
+ _isInt(call.staticType);
+ }
+
test_constructorInitializer_propagation() async {
String code = r'''
class A {
@@ -1212,6 +1449,171 @@ class StrongModeDownwardsInferenceTest extends ResolverTestCase {
assertListOfString(methodReturnValue("m1").staticType);
}
+ test_partialTypes1() async {
+ // Test that downwards inference with a partial type
+ // correctly uses the partial information to fill in subterm
+ // types
+ String code = r'''
+ typedef To Func1<From, To>(From x);
+ S f<S, T>(Func1<S, T> g) => null;
+ String test() => f((l) => l.length);
+ ''';
+ Source source = addSource(code);
+ TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ CompilationUnit unit = analysisResult.unit;
+ FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, "test");
+ ExpressionFunctionBody body = test.functionExpression.body;
+ _isString(body.expression.staticType);
+ MethodInvocation invoke = body.expression;
+ FunctionExpression function = invoke.argumentList.arguments[0];
+ ExecutableElement f0 = function.element;
+ FunctionType type = f0.type;
+ _isFunction2Of(_isString, _isInt)(type);
+ }
+
+ test_pinning_multipleConstraints4() async {
+ // Test that downwards inference with two subtype related downwards
+ // covariant constraints on the same parameter correctly infers and pins
+ // the type
+ String code = r'''
+ class A<S, T> {
+ S s;
+ T t;
+ }
+ class B<S> extends A<S, S> {}
+ A<int, num> test() => new B();
+ ''';
+ Source source = addSource(code);
+ TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ CompilationUnit unit = analysisResult.unit;
+ FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, "test");
+ ExpressionFunctionBody body = test.functionExpression.body;
+ DartType type = body.expression.staticType;
+
+ Element elementB = AstFinder.getClass(unit, "B").element;
+
+ _isInstantiationOf(_hasElement(elementB))([_isInt])(type);
+ }
+
+ test_pinning_multipleConstraints_contravariant1() async {
+ // Test that downwards inference with two different downwards contravariant
+ // constraints on the same parameter chooses the upper bound
+ // when the only supertype is Object
+ String code = r'''
+ class A<S, T> {
+ S s;
+ T t;
+ }
+ class B<S> extends A<S, S> {}
+ typedef void Contra1<T>(T x);
+ Contra1<A<S, S>> mkA<S>() => (A<S, S> x) {};
+ Contra1<A<int, String>> test() => mkA();
+ ''';
+ Source source = addSource(code);
+ TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ CompilationUnit unit = analysisResult.unit;
+ FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, "test");
+ ExpressionFunctionBody body = test.functionExpression.body;
+ FunctionType functionType = body.expression.staticType;
+ DartType type = functionType.normalParameterTypes[0];
+
+ Element elementA = AstFinder.getClass(unit, "A").element;
+
+ _isInstantiationOf(_hasElement(elementA))([_isObject, _isObject])(type);
+ }
+
+ test_pinning_multipleConstraints_contravariant2() async {
+ // Test that downwards inference with two identical downwards contravariant
+ // constraints on the same parameter correctly pins the type
+ String code = r'''
+ class A<S, T> {
+ S s;
+ T t;
+ }
+ class B<S> extends A<S, S> {}
+ typedef void Contra1<T>(T x);
+ Contra1<A<S, S>> mkA<S>() => (A<S, S> x) {};
+ Contra1<A<num, num>> test() => mkA();
+ ''';
+ Source source = addSource(code);
+ TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ CompilationUnit unit = analysisResult.unit;
+ FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, "test");
+ ExpressionFunctionBody body = test.functionExpression.body;
+ FunctionType functionType = body.expression.staticType;
+ DartType type = functionType.normalParameterTypes[0];
+
+ Element elementA = AstFinder.getClass(unit, "A").element;
+
+ _isInstantiationOf(_hasElement(elementA))([_isNum, _isNum])(type);
+ }
+
+ test_pinning_multipleConstraints_contravariant3() async {
+ // Test that downwards inference with two different downwards contravariant
+ // constraints on the same parameter correctly choose the least upper bound
+ // when they share a common supertype
+ String code = r'''
+ class A<S, T> {
+ S s;
+ T t;
+ }
+ class B<S> extends A<S, S> {}
+ typedef void Contra1<T>(T x);
+ Contra1<A<S, S>> mkA<S>() => (A<S, S> x) {};
+ Contra1<A<int, double>> test() => mkA();
+ ''';
+ Source source = addSource(code);
+ TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ CompilationUnit unit = analysisResult.unit;
+ FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, "test");
+ ExpressionFunctionBody body = test.functionExpression.body;
+ FunctionType functionType = body.expression.staticType;
+ DartType type = functionType.normalParameterTypes[0];
+
+ Element elementA = AstFinder.getClass(unit, "A").element;
+
+ _isInstantiationOf(_hasElement(elementA))([_isNum, _isNum])(type);
+ }
+
+ test_pinning_multipleConstraints_contravariant4() async {
+ // Test that downwards inference with two different downwards contravariant
+ // constraints on the same parameter correctly choose the least upper bound
+ // when one is a subtype of the other
+ String code = r'''
+ class A<S, T> {
+ S s;
+ T t;
+ }
+ class B<S> extends A<S, S> {}
+ typedef void Contra1<T>(T x);
+ Contra1<A<S, S>> mkA<S>() => (A<S, S> x) {};
+ Contra1<A<int, num>> test() => mkA();
+ ''';
+ Source source = addSource(code);
+ TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ CompilationUnit unit = analysisResult.unit;
+ FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, "test");
+ ExpressionFunctionBody body = test.functionExpression.body;
+ FunctionType functionType = body.expression.staticType;
+ DartType type = functionType.normalParameterTypes[0];
+
+ Element elementA = AstFinder.getClass(unit, "A").element;
+
+ _isInstantiationOf(_hasElement(elementA))([_isNum, _isNum])(type);
+ }
+
test_redirectingConstructor_propagation() async {
String code = r'''
class A {
@@ -1228,6 +1630,90 @@ class StrongModeDownwardsInferenceTest extends ResolverTestCase {
_isListOf(_isString)(exp.staticType);
}
+ test_returnType_variance1() async {
+ // Check that downwards inference correctly pins a type parameter
+ // when the parameter is constrained in a contravariant position
+ String code = r'''
+ typedef To Func1<From, To>(From x);
+ Func1<T, String> f<T>(T x) => null;
+ Func1<num, String> test() => f(42);
+ ''';
+ Source source = addSource(code);
+ TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ CompilationUnit unit = analysisResult.unit;
+ FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, "test");
+ ExpressionFunctionBody body = test.functionExpression.body;
+ MethodInvocation invoke = body.expression;
+ _isFunction2Of(_isNum, _isFunction2Of(_isNum, _isString))(
+ invoke.staticInvokeType);
+ }
+
+ test_returnType_variance3() async {
+ // Check that the variance heuristic chooses the less precise type
+ // when the return type uses the variable in a contravariant position
+ // and there is no downwards constraint.
+ String code = r'''
+ typedef To Func1<From, To>(From x);
+ Func1<T, String> f<T>(T x, g(T x)) => null;
+ dynamic test() => f(42, (num x) => x);
+ ''';
+ Source source = addSource(code);
+ TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ CompilationUnit unit = analysisResult.unit;
+ FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, "test");
+ ExpressionFunctionBody body = test.functionExpression.body;
+ FunctionType functionType = body.expression.staticType;
+ DartType type = functionType.normalParameterTypes[0];
+ _isNum(type);
+ }
+
+ test_returnType_variance4() async {
+ // Check that the variance heuristic chooses the more precise type
+ // when the return type uses the variable in a covariant position
+ // and there is no downwards constraint
+ String code = r'''
+ typedef To Func1<From, To>(From x);
+ Func1<String, T> f<T>(T x, g(T x)) => null;
+ dynamic test() => f(42, (num x) => x);
+ ''';
+ Source source = addSource(code);
+ TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ CompilationUnit unit = analysisResult.unit;
+ FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, "test");
+ ExpressionFunctionBody body = test.functionExpression.body;
+ FunctionType functionType = body.expression.staticType;
+ DartType type = functionType.returnType;
+ _isInt(type);
+ }
+
+ test_returnType_variance5() async {
+ // Check that pinning works correctly with a partial type
+ // when the return type uses the variable in a contravariant position
+ String code = r'''
+ typedef To Func1<From, To>(From x);
+ Func1<T, String> f<T>(T x) => null;
+ T g<T, S>(Func1<T, S> f) => null;
+ num test() => g(f(3));
+ ''';
+ Source source = addSource(code);
+ TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ CompilationUnit unit = analysisResult.unit;
+ FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, "test");
+ ExpressionFunctionBody body = test.functionExpression.body;
+ MethodInvocation call = body.expression;
+ _isNum(call.staticType);
+ _isFunction2Of(_isFunction2Of(_isNum, _isString), _isNum)(
+ call.staticInvokeType);
+ }
+
test_superConstructorInvocation_propagation() async {
String code = r'''
class B {
« no previous file with comments | « pkg/analyzer/test/generated/strong_mode_driver_test.dart ('k') | pkg/analyzer/test/utils.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698