Fix isNullable / isNonNullable, expand tests.
This addresses the issue in a previous CL.
https://dart-review.googlesource.com/c/sdk/+/106620/3/tests/language_2/nnbd/static_errors/equals_parameter_made_nullable_at_invoke_test.dart#30
Change-Id: Ib510ddbfe42c8e6d7cb0c4793a30e050b7e56bd0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/106962
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Leaf Petersen <leafp@google.com>
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 879f4e7..59dedf3 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -2112,11 +2112,11 @@
bool isNonNullable(DartType type) {
if (type.isDynamic || type.isVoid || type.isDartCoreNull) {
return false;
- } else if (type.isDartAsyncFutureOr) {
- isNonNullable((type as InterfaceType).typeArguments[0]);
} else if ((type as TypeImpl).nullabilitySuffix ==
NullabilitySuffix.question) {
return false;
+ } else if (type.isDartAsyncFutureOr) {
+ return isNonNullable((type as InterfaceType).typeArguments[0]);
} else if (type is TypeParameterType) {
return isNonNullable(type.bound);
}
@@ -2127,10 +2127,13 @@
bool isNullable(DartType type) {
if (type.isDynamic || type.isVoid || type.isDartCoreNull) {
return true;
+ } else if ((type as TypeImpl).nullabilitySuffix ==
+ NullabilitySuffix.question) {
+ return true;
} else if (type.isDartAsyncFutureOr) {
- isNullable((type as InterfaceType).typeArguments[0]);
+ return isNullable((type as InterfaceType).typeArguments[0]);
}
- return (type as TypeImpl).nullabilitySuffix != NullabilitySuffix.none;
+ return false;
}
/// Check that [f1] is a subtype of [f2] for a member override.
diff --git a/pkg/analyzer/test/generated/type_system_test.dart b/pkg/analyzer/test/generated/type_system_test.dart
index abbf98e..fc17f6d 100644
--- a/pkg/analyzer/test/generated/type_system_test.dart
+++ b/pkg/analyzer/test/generated/type_system_test.dart
@@ -54,6 +54,7 @@
InterfaceType get intType => typeProvider.intType;
InterfaceType get iterableType => typeProvider.iterableType;
InterfaceType get listType => typeProvider.listType;
+ DartType get neverType => typeProvider.neverType;
DartType get nullType => typeProvider.nullType;
InterfaceType get numType => typeProvider.numType;
InterfaceType get objectType => typeProvider.objectType;
@@ -2728,56 +2729,222 @@
@reflectiveTest
class TypeSystemTest extends AbstractTypeSystemTest {
- DartType get futureOrWithNoneType =>
- typeProvider.futureOrType.instantiate([noneType]);
+ DartType get functionClassTypeNone {
+ return InterfaceTypeImpl.explicit(
+ typeProvider.functionType.element,
+ const <DartType>[],
+ nullabilitySuffix: NullabilitySuffix.none,
+ );
+ }
- DartType get futureOrWithQuestionType =>
- typeProvider.futureOrType.instantiate([questionType]);
+ DartType get functionClassTypeQuestion {
+ return InterfaceTypeImpl.explicit(
+ typeProvider.functionType.element,
+ const <DartType>[],
+ nullabilitySuffix: NullabilitySuffix.question,
+ );
+ }
- DartType get futureOrWithStarType =>
- typeProvider.futureOrType.instantiate([starType]);
+ DartType get functionClassTypeStar {
+ return InterfaceTypeImpl.explicit(
+ typeProvider.functionType.element,
+ const <DartType>[],
+ nullabilitySuffix: NullabilitySuffix.star,
+ );
+ }
DartType get noneType => (typeProvider.stringType as TypeImpl)
.withNullability(NullabilitySuffix.none);
+ FunctionType get nothingToVoidFunctionTypeNone {
+ return FunctionTypeImpl.synthetic(
+ voidType,
+ const <TypeParameterElement>[],
+ const <ParameterElement>[],
+ nullabilitySuffix: NullabilitySuffix.none,
+ );
+ }
+
+ FunctionType get nothingToVoidFunctionTypeQuestion {
+ return FunctionTypeImpl.synthetic(
+ voidType,
+ const <TypeParameterElement>[],
+ const <ParameterElement>[],
+ nullabilitySuffix: NullabilitySuffix.question,
+ );
+ }
+
+ FunctionType get nothingToVoidFunctionTypeStar {
+ return FunctionTypeImpl.synthetic(
+ voidType,
+ const <TypeParameterElement>[],
+ const <ParameterElement>[],
+ nullabilitySuffix: NullabilitySuffix.star,
+ );
+ }
+
DartType get questionType => (typeProvider.stringType as TypeImpl)
.withNullability(NullabilitySuffix.question);
DartType get starType => (typeProvider.stringType as TypeImpl)
.withNullability(NullabilitySuffix.star);
+ DartType futureOrTypeNone({@required DartType argument}) {
+ var element = typeProvider.futureOrType.element;
+ return InterfaceTypeImpl.explicit(
+ element,
+ <DartType>[argument],
+ nullabilitySuffix: NullabilitySuffix.none,
+ );
+ }
+
+ DartType futureOrTypeQuestion({@required DartType argument}) {
+ var element = typeProvider.futureOrType.element;
+ return InterfaceTypeImpl.explicit(
+ element,
+ <DartType>[argument],
+ nullabilitySuffix: NullabilitySuffix.question,
+ );
+ }
+
+ DartType futureOrTypeStar({@required DartType argument}) {
+ var element = typeProvider.futureOrType.element;
+ return InterfaceTypeImpl.explicit(
+ element,
+ <DartType>[argument],
+ nullabilitySuffix: NullabilitySuffix.star,
+ );
+ }
+
test_isNonNullable_dynamic() {
expect(typeSystem.isNonNullable(dynamicType), false);
}
- test_isNonNullable_futureOr_noneArg() {
- expect(typeSystem.isNonNullable(futureOrWithNoneType), true);
+ test_isNonNullable_function_none() {
+ expect(typeSystem.isNonNullable(nothingToVoidFunctionTypeNone), true);
}
- test_isNonNullable_futureOr_questionArg() {
- expect(typeSystem.isNonNullable(futureOrWithQuestionType), true);
+ test_isNonNullable_function_question() {
+ expect(typeSystem.isNonNullable(nothingToVoidFunctionTypeQuestion), false);
}
- test_isNonNullable_futureOr_starArg() {
- expect(typeSystem.isNonNullable(futureOrWithStarType), true);
+ test_isNonNullable_function_star() {
+ expect(typeSystem.isNonNullable(nothingToVoidFunctionTypeStar), true);
}
- test_isNonNullable_none() {
+ test_isNonNullable_functionClass_none() {
+ expect(typeSystem.isNonNullable(functionClassTypeNone), true);
+ }
+
+ test_isNonNullable_functionClass_question() {
+ expect(typeSystem.isNonNullable(functionClassTypeQuestion), false);
+ }
+
+ test_isNonNullable_functionClass_star() {
+ expect(typeSystem.isNonNullable(functionClassTypeStar), true);
+ }
+
+ test_isNonNullable_futureOr_noneArgument_none() {
+ expect(
+ typeSystem.isNonNullable(
+ futureOrTypeNone(argument: noneType),
+ ),
+ true,
+ );
+ }
+
+ test_isNonNullable_futureOr_noneArgument_question() {
+ expect(
+ typeSystem.isNonNullable(
+ futureOrTypeQuestion(argument: noneType),
+ ),
+ false,
+ );
+ }
+
+ test_isNonNullable_futureOr_noneArgument_star() {
+ expect(
+ typeSystem.isNonNullable(
+ futureOrTypeStar(argument: noneType),
+ ),
+ true,
+ );
+ }
+
+ test_isNonNullable_futureOr_questionArgument_none() {
+ expect(
+ typeSystem.isNonNullable(
+ futureOrTypeNone(argument: questionType),
+ ),
+ false,
+ );
+ }
+
+ test_isNonNullable_futureOr_questionArgument_question() {
+ expect(
+ typeSystem.isNonNullable(
+ futureOrTypeQuestion(argument: questionType),
+ ),
+ false,
+ );
+ }
+
+ test_isNonNullable_futureOr_questionArgument_star() {
+ expect(
+ typeSystem.isNonNullable(
+ futureOrTypeStar(argument: questionType),
+ ),
+ false,
+ );
+ }
+
+ test_isNonNullable_futureOr_starArgument_none() {
+ expect(
+ typeSystem.isNonNullable(
+ futureOrTypeNone(argument: starType),
+ ),
+ true,
+ );
+ }
+
+ test_isNonNullable_futureOr_starArgument_question() {
+ expect(
+ typeSystem.isNonNullable(
+ futureOrTypeStar(argument: questionType),
+ ),
+ false,
+ );
+ }
+
+ test_isNonNullable_futureOr_starArgument_star() {
+ expect(
+ typeSystem.isNonNullable(
+ futureOrTypeStar(argument: starType),
+ ),
+ true,
+ );
+ }
+
+ test_isNonNullable_interface_none() {
expect(typeSystem.isNonNullable(noneType), true);
}
+ test_isNonNullable_interface_question() {
+ expect(typeSystem.isNonNullable(questionType), false);
+ }
+
+ test_isNonNullable_interface_star() {
+ expect(typeSystem.isNonNullable(starType), true);
+ }
+
+ test_isNonNullable_never() {
+ expect(typeSystem.isNonNullable(neverType), true);
+ }
+
test_isNonNullable_null() {
expect(typeSystem.isNonNullable(nullType), false);
}
- test_isNonNullable_question() {
- expect(typeSystem.isNonNullable(questionType), false);
- }
-
- test_isNonNullable_star() {
- expect(typeSystem.isNonNullable(starType), true);
- }
-
test_isNonNullable_typeParameter_noneBound_none() {
expect(
typeSystem.isNonNullable(
@@ -2831,34 +2998,131 @@
expect(typeSystem.isNullable(dynamicType), true);
}
- test_isNullable_futureOr_noneArg() {
- expect(typeSystem.isNullable(futureOrWithNoneType), true);
+ test_isNullable_function_none() {
+ expect(typeSystem.isNullable(nothingToVoidFunctionTypeNone), false);
}
- test_isNullable_futureOr_questionArg() {
- expect(typeSystem.isNullable(futureOrWithQuestionType), true);
+ test_isNullable_function_question() {
+ expect(typeSystem.isNullable(nothingToVoidFunctionTypeQuestion), true);
}
- test_isNullable_futureOr_starArg() {
- expect(typeSystem.isNullable(futureOrWithStarType), true);
+ test_isNullable_function_star() {
+ expect(typeSystem.isNullable(nothingToVoidFunctionTypeStar), false);
}
- test_isNullable_none() {
+ test_isNullable_functionClass_none() {
+ expect(typeSystem.isNullable(functionClassTypeNone), false);
+ }
+
+ test_isNullable_functionClass_question() {
+ expect(typeSystem.isNullable(functionClassTypeQuestion), true);
+ }
+
+ test_isNullable_functionClass_star() {
+ expect(typeSystem.isNullable(functionClassTypeStar), false);
+ }
+
+ test_isNullable_futureOr_noneArgument_none() {
+ expect(
+ typeSystem.isNullable(
+ futureOrTypeNone(argument: noneType),
+ ),
+ false,
+ );
+ }
+
+ test_isNullable_futureOr_noneArgument_question() {
+ expect(
+ typeSystem.isNullable(
+ futureOrTypeQuestion(argument: noneType),
+ ),
+ true,
+ );
+ }
+
+ test_isNullable_futureOr_noneArgument_star() {
+ expect(
+ typeSystem.isNullable(
+ futureOrTypeStar(argument: noneType),
+ ),
+ false,
+ );
+ }
+
+ test_isNullable_futureOr_questionArgument_none() {
+ expect(
+ typeSystem.isNullable(
+ futureOrTypeNone(argument: questionType),
+ ),
+ true,
+ );
+ }
+
+ test_isNullable_futureOr_questionArgument_question() {
+ expect(
+ typeSystem.isNullable(
+ futureOrTypeQuestion(argument: questionType),
+ ),
+ true,
+ );
+ }
+
+ test_isNullable_futureOr_questionArgument_star() {
+ expect(
+ typeSystem.isNullable(
+ futureOrTypeStar(argument: questionType),
+ ),
+ true,
+ );
+ }
+
+ test_isNullable_futureOr_starArgument_none() {
+ expect(
+ typeSystem.isNullable(
+ futureOrTypeNone(argument: starType),
+ ),
+ false,
+ );
+ }
+
+ test_isNullable_futureOr_starArgument_question() {
+ expect(
+ typeSystem.isNullable(
+ futureOrTypeQuestion(argument: starType),
+ ),
+ true,
+ );
+ }
+
+ test_isNullable_futureOr_starArgument_star() {
+ expect(
+ typeSystem.isNullable(
+ futureOrTypeStar(argument: starType),
+ ),
+ false,
+ );
+ }
+
+ test_isNullable_interface_none() {
expect(typeSystem.isNullable(noneType), false);
}
+ test_isNullable_interface_question() {
+ expect(typeSystem.isNullable(questionType), true);
+ }
+
+ test_isNullable_interface_star() {
+ expect(typeSystem.isNullable(starType), false);
+ }
+
+ test_isNullable_never() {
+ expect(typeSystem.isNullable(neverType), false);
+ }
+
test_isNullable_null() {
expect(typeSystem.isNullable(nullType), true);
}
- test_isNullable_question() {
- expect(typeSystem.isNullable(questionType), true);
- }
-
- test_isNullable_star() {
- expect(typeSystem.isNullable(starType), true);
- }
-
test_isNullable_typeParameter_noneBound_none() {
expect(
typeSystem.isNullable(
@@ -2900,7 +3164,7 @@
typeSystem.isNullable(
typeParameterTypeStar(bound: starType),
),
- true,
+ false,
);
}
@@ -2912,17 +3176,31 @@
expect(typeSystem.isPotentiallyNonNullable(dynamicType), false);
}
- test_isPotentiallyNonNullable_futureOr_noneArg() {
- expect(typeSystem.isPotentiallyNonNullable(futureOrWithNoneType), false);
- }
-
- test_isPotentiallyNonNullable_futureOr_questionArg() {
+ test_isPotentiallyNonNullable_futureOr_noneArgument_none() {
expect(
- typeSystem.isPotentiallyNonNullable(futureOrWithQuestionType), false);
+ typeSystem.isPotentiallyNonNullable(
+ futureOrTypeNone(argument: noneType),
+ ),
+ true,
+ );
}
- test_isPotentiallyNonNullable_futureOr_starArg() {
- expect(typeSystem.isPotentiallyNonNullable(futureOrWithStarType), false);
+ test_isPotentiallyNonNullable_futureOr_questionArgument_none() {
+ expect(
+ typeSystem.isPotentiallyNonNullable(
+ futureOrTypeNone(argument: questionType),
+ ),
+ false,
+ );
+ }
+
+ test_isPotentiallyNonNullable_futureOr_starArgument_none() {
+ expect(
+ typeSystem.isPotentiallyNonNullable(
+ futureOrTypeNone(argument: starType),
+ ),
+ true,
+ );
}
test_isPotentiallyNonNullable_none() {
@@ -2938,7 +3216,7 @@
}
test_isPotentiallyNonNullable_star() {
- expect(typeSystem.isPotentiallyNonNullable(starType), false);
+ expect(typeSystem.isPotentiallyNonNullable(starType), true);
}
test_isPotentiallyNonNullable_void() {
@@ -2949,16 +3227,31 @@
expect(typeSystem.isPotentiallyNullable(dynamicType), true);
}
- test_isPotentiallyNullable_futureOr_noneArg() {
- expect(typeSystem.isPotentiallyNullable(futureOrWithNoneType), false);
+ test_isPotentiallyNullable_futureOr_noneArgument_none() {
+ expect(
+ typeSystem.isPotentiallyNullable(
+ futureOrTypeNone(argument: noneType),
+ ),
+ false,
+ );
}
- test_isPotentiallyNullable_futureOr_questionArg() {
- expect(typeSystem.isPotentiallyNullable(futureOrWithQuestionType), false);
+ test_isPotentiallyNullable_futureOr_questionArgument_none() {
+ expect(
+ typeSystem.isPotentiallyNullable(
+ futureOrTypeNone(argument: questionType),
+ ),
+ true,
+ );
}
- test_isPotentiallyNullable_futureOr_starArg() {
- expect(typeSystem.isPotentiallyNullable(futureOrWithStarType), false);
+ test_isPotentiallyNullable_futureOr_starArgument_none() {
+ expect(
+ typeSystem.isPotentiallyNullable(
+ futureOrTypeNone(argument: starType),
+ ),
+ false,
+ );
}
test_isPotentiallyNullable_none() {
@@ -2985,23 +3278,29 @@
expect(bound, isNotNull);
var element = TypeParameterElementImpl.synthetic('T');
element.bound = bound;
- return TypeParameterTypeImpl(element,
- nullabilitySuffix: NullabilitySuffix.none);
+ return TypeParameterTypeImpl(
+ element,
+ nullabilitySuffix: NullabilitySuffix.none,
+ );
}
DartType typeParameterTypeQuestion({@required DartType bound}) {
expect(bound, isNotNull);
var element = TypeParameterElementImpl.synthetic('T');
element.bound = bound;
- return TypeParameterTypeImpl(element,
- nullabilitySuffix: NullabilitySuffix.question);
+ return TypeParameterTypeImpl(
+ element,
+ nullabilitySuffix: NullabilitySuffix.question,
+ );
}
DartType typeParameterTypeStar({@required DartType bound}) {
expect(bound, isNotNull);
var element = TypeParameterElementImpl.synthetic('T');
element.bound = bound;
- return TypeParameterTypeImpl(element,
- nullabilitySuffix: NullabilitySuffix.star);
+ return TypeParameterTypeImpl(
+ element,
+ nullabilitySuffix: NullabilitySuffix.star,
+ );
}
}
diff --git a/pkg/analyzer/test/src/diagnostics/not_initialized_non_nullable_top_level_variable_test.dart b/pkg/analyzer/test/src/diagnostics/not_initialized_non_nullable_top_level_variable_test.dart
index 9399e70..218e4ef 100644
--- a/pkg/analyzer/test/src/diagnostics/not_initialized_non_nullable_top_level_variable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/not_initialized_non_nullable_top_level_variable_test.dart
@@ -22,6 +22,14 @@
AnalysisOptionsImpl get analysisOptions =>
AnalysisOptionsImpl()..enabledExperiments = [EnableString.non_nullable];
+ test_futureOr_questionArgument_none() async {
+ assertNoErrorsInCode('''
+import 'dart:async';
+
+FutureOr<int?> v;
+''');
+ }
+
test_hasInitializer() async {
assertNoErrorsInCode('''
int v = 0;
diff --git a/pkg/analyzer/test/src/diagnostics/not_initialized_potentially_non_nullable_local_variable_test.dart b/pkg/analyzer/test/src/diagnostics/not_initialized_potentially_non_nullable_local_variable_test.dart
index fb5d0d0..5a63b51 100644
--- a/pkg/analyzer/test/src/diagnostics/not_initialized_potentially_non_nullable_local_variable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/not_initialized_potentially_non_nullable_local_variable_test.dart
@@ -74,6 +74,16 @@
''');
}
+ test_futureOr_questionArgument_none() async {
+ assertNoErrorsInCode('''
+import 'dart:async';
+
+f() {
+ FutureOr<int?> v;
+}
+''');
+ }
+
test_hasInitializer() async {
assertNoErrorsInCode('''
f() {
diff --git a/tests/language_2/nnbd/static_errors/equals_parameter_made_nullable_at_invoke_test.dart b/tests/language_2/nnbd/static_errors/equals_parameter_made_nullable_at_invoke_test.dart
index 9757f79..2d6c7a6 100644
--- a/tests/language_2/nnbd/static_errors/equals_parameter_made_nullable_at_invoke_test.dart
+++ b/tests/language_2/nnbd/static_errors/equals_parameter_made_nullable_at_invoke_test.dart
@@ -27,7 +27,7 @@
// Caveat: it is NOT that the argument is promoted to non-null. Otherwise,
// types which we can't cleanly promote, such as FutureOr<int?>, would not be
// assignable in comparisons.
- FutureOr<int?> foInt = Future.value(0);
+ FutureOr<int?> foInt;
// Valid comparison.
o == foInt;