From 49466188455d411c8a15ec7d9dfa441530946a5b Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Tue, 9 Jan 2024 21:50:49 +0000 Subject: [PATCH] Extension type. Issue 54548. Don't consider Never? to be a bottom type. Bug: https://github.com/dart-lang/sdk/issues/54548 Change-Id: I56b734c24a84c8188983605eca69de28869b6de0 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/345440 Reviewed-by: Brian Wilkerson Commit-Queue: Konstantin Shcheglov --- pkg/analyzer/lib/src/dart/element/type.dart | 3 ++ .../lib/src/dart/element/type_system.dart | 10 ++++-- .../dart/element/upper_lower_bound_test.dart | 4 +-- ..._type_representation_type_bottom_test.dart | 33 +++++++++++++++++++ 4 files changed, 45 insertions(+), 5 deletions(-) diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart index 78f430823cf9..8688b4547ec2 100644 --- a/pkg/analyzer/lib/src/dart/element/type.dart +++ b/pkg/analyzer/lib/src/dart/element/type.dart @@ -1436,6 +1436,9 @@ class TypeParameterTypeImpl extends TypeImpl implements TypeParameterType { Set seenTypes = {}; TypeParameterType type = this; while (seenTypes.add(type.element)) { + if (type.nullabilitySuffix == NullabilitySuffix.question) { + return false; + } var bound = type.bound; if (bound is TypeParameterType) { type = bound; diff --git a/pkg/analyzer/lib/src/dart/element/type_system.dart b/pkg/analyzer/lib/src/dart/element/type_system.dart index 68236f2048f3..592696abfa61 100644 --- a/pkg/analyzer/lib/src/dart/element/type_system.dart +++ b/pkg/analyzer/lib/src/dart/element/type_system.dart @@ -982,11 +982,15 @@ class TypeSystemImpl implements TypeSystem { /// Return `true` for things in the equivalence class of `Never`. bool isBottom(DartType type) { + if (type.nullabilitySuffix == NullabilitySuffix.question) { + assert(!type.isBottom); + return false; + } + // BOTTOM(Never) is true if (type is NeverType) { - var result = type.nullabilitySuffix != NullabilitySuffix.question; - assert(type.isBottom == result); - return result; + assert(type.isBottom); + return true; } // BOTTOM(X&T) is true iff BOTTOM(T) diff --git a/pkg/analyzer/test/src/dart/element/upper_lower_bound_test.dart b/pkg/analyzer/test/src/dart/element/upper_lower_bound_test.dart index 298cf12f4f1e..068dc520f090 100644 --- a/pkg/analyzer/test/src/dart/element/upper_lower_bound_test.dart +++ b/pkg/analyzer/test/src/dart/element/upper_lower_bound_test.dart @@ -114,7 +114,7 @@ class BoundsHelperPredicatesTest extends _BoundsTestBase { T = typeParameter('T', bound: objectQuestion); isBottom(promotedTypeParameterTypeNone(T, neverNone)); - isBottom(promotedTypeParameterTypeQuestion(T, neverNone)); + isNotBottom(promotedTypeParameterTypeQuestion(T, neverNone)); isBottom(promotedTypeParameterTypeStar(T, neverNone)); isNotBottom(promotedTypeParameterTypeNone(T, neverQuestion)); @@ -124,7 +124,7 @@ class BoundsHelperPredicatesTest extends _BoundsTestBase { // BOTTOM(X extends T) is true iff BOTTOM(T) T = typeParameter('T', bound: neverNone); isBottom(typeParameterTypeNone(T)); - isBottom(typeParameterTypeQuestion(T)); + isNotBottom(typeParameterTypeQuestion(T)); isBottom(typeParameterTypeStar(T)); T = typeParameter('T', bound: neverQuestion); diff --git a/pkg/analyzer/test/src/diagnostics/extension_type_representation_type_bottom_test.dart b/pkg/analyzer/test/src/diagnostics/extension_type_representation_type_bottom_test.dart index 2278e11a33ff..03d59932e58d 100644 --- a/pkg/analyzer/test/src/diagnostics/extension_type_representation_type_bottom_test.dart +++ b/pkg/analyzer/test/src/diagnostics/extension_type_representation_type_bottom_test.dart @@ -24,4 +24,37 @@ extension type A(Never it) {} 5), ]); } + + test_neverQuestion() async { + await assertNoErrorsInCode(''' +extension type A(Never? it) {} +'''); + } + + test_typeParameter_never_none() async { + await assertErrorsInCode(''' +extension type A(T it) {} +''', [ + error(CompileTimeErrorCode.EXTENSION_TYPE_REPRESENTATION_TYPE_BOTTOM, 34, + 1), + ]); + } + + test_typeParameter_never_question() async { + await assertNoErrorsInCode(''' +extension type A(T? it) {} +'''); + } + + test_typeParameter_never_question2() async { + await assertNoErrorsInCode(''' +extension type A(S? it) {} +'''); + } + + test_typeParameter_never_question3() async { + await assertNoErrorsInCode(''' +extension type A(S it) {} +'''); + } }