[cfe] Handle explicit type parameter type nullability in bounds
Closes #42143 Change-Id: I05f181889481c48b183cef135f96dbf510ca788d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151381 Reviewed-by: Dmitry Stefantsov <dmitryas@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
21222b64c4
commit
261e283a0a
@@ -35,6 +35,8 @@ class NullabilityBuilder {
|
||||
const NullabilityBuilder.omitted()
|
||||
: _syntacticNullability = SyntacticNullability.omitted;
|
||||
|
||||
bool get isOmitted => _syntacticNullability == SyntacticNullability.omitted;
|
||||
|
||||
factory NullabilityBuilder.fromNullability(Nullability nullability) {
|
||||
switch (nullability) {
|
||||
case Nullability.nullable:
|
||||
@@ -47,13 +49,10 @@ class NullabilityBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
Nullability build(LibraryBuilder libraryBuilder, {Nullability ifOmitted}) {
|
||||
// TODO(dmitryas): Ensure that either ifOmitted is set or libraryBuilder is
|
||||
// provided;
|
||||
//assert(libraryBuilder != null || ifOmitted != null);
|
||||
ifOmitted ??= (libraryBuilder == null ? Nullability.legacy : null);
|
||||
Nullability build(LibraryBuilder libraryBuilder) {
|
||||
assert(libraryBuilder != null);
|
||||
|
||||
ifOmitted ??= libraryBuilder.isNonNullableByDefault
|
||||
Nullability ifOmitted = libraryBuilder.isNonNullableByDefault
|
||||
? Nullability.nonNullable
|
||||
: Nullability.legacy;
|
||||
switch (_syntacticNullability) {
|
||||
|
||||
@@ -89,16 +89,22 @@ class TypeVariableBuilder extends TypeDeclarationBuilderImpl {
|
||||
}
|
||||
// If the bound is not set yet, the actual value is not important yet as it
|
||||
// will be set later.
|
||||
Nullability nullabilityIfOmitted = parameter.bound != null &&
|
||||
library != null &&
|
||||
library.isNonNullableByDefault
|
||||
? TypeParameterType.computeNullabilityFromBound(parameter)
|
||||
: Nullability.legacy;
|
||||
DartType type = buildTypesWithBuiltArguments(
|
||||
library,
|
||||
nullabilityBuilder.build(library, ifOmitted: nullabilityIfOmitted),
|
||||
null);
|
||||
if (parameter.bound == null) {
|
||||
bool needsPostUpdate = false;
|
||||
Nullability nullability;
|
||||
if (nullabilityBuilder.isOmitted) {
|
||||
if (parameter.bound != null) {
|
||||
nullability = library.isNonNullableByDefault
|
||||
? TypeParameterType.computeNullabilityFromBound(parameter)
|
||||
: Nullability.legacy;
|
||||
} else {
|
||||
nullability = Nullability.legacy;
|
||||
needsPostUpdate = true;
|
||||
}
|
||||
} else {
|
||||
nullability = nullabilityBuilder.build(library);
|
||||
}
|
||||
DartType type = buildTypesWithBuiltArguments(library, nullability, null);
|
||||
if (needsPostUpdate) {
|
||||
if (library is SourceLibraryBuilder) {
|
||||
library.pendingNullabilities.add(type);
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import 'dart:async';
|
||||
|
||||
void h1<T extends FutureOr<T?>?>(T? t) {}
|
||||
void h2<S extends FutureOr<S?>>(S? s) {}
|
||||
|
||||
main() {}
|
||||
@@ -0,0 +1,11 @@
|
||||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
|
||||
import "dart:async";
|
||||
|
||||
static method h1<T extends FutureOr<self::h1::T?>? = FutureOr<dynamic>?>(self::h1::T? t) → void
|
||||
;
|
||||
static method h2<S extends FutureOr<self::h2::S?> = FutureOr<dynamic>>(self::h2::S? s) → void
|
||||
;
|
||||
static method main() → dynamic
|
||||
;
|
||||
@@ -0,0 +1,8 @@
|
||||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
|
||||
import "dart:async";
|
||||
|
||||
static method h1<T extends FutureOr<self::h1::T?>? = FutureOr<dynamic>?>(self::h1::T? t) → void {}
|
||||
static method h2<S extends FutureOr<self::h2::S?> = FutureOr<dynamic>>(self::h2::S? s) → void {}
|
||||
static method main() → dynamic {}
|
||||
@@ -0,0 +1,8 @@
|
||||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
|
||||
import "dart:async";
|
||||
|
||||
static method h1<T extends FutureOr<self::h1::T?>? = FutureOr<dynamic>?>(self::h1::T? t) → void {}
|
||||
static method h2<S extends FutureOr<self::h2::S?> = FutureOr<dynamic>>(self::h2::S? s) → void {}
|
||||
static method main() → dynamic {}
|
||||
@@ -0,0 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
void h1<T extends FutureOr<T?>?>(T? t) {}
|
||||
void h2<S extends FutureOr<S?>>(S? s) {}
|
||||
main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
main() {}
|
||||
void h1<T extends FutureOr<T?>?>(T? t) {}
|
||||
void h2<S extends FutureOr<S?>>(S? s) {}
|
||||
@@ -0,0 +1,8 @@
|
||||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
|
||||
import "dart:async";
|
||||
|
||||
static method h1<T extends FutureOr<self::h1::T?>? = FutureOr<dynamic>?>(self::h1::T? t) → void {}
|
||||
static method h2<S extends FutureOr<self::h2::S?> = FutureOr<dynamic>>(self::h2::S? s) → void {}
|
||||
static method main() → dynamic {}
|
||||
@@ -0,0 +1,8 @@
|
||||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
|
||||
import "dart:async";
|
||||
|
||||
static method h1<T extends FutureOr<self::h1::T?>? = FutureOr<dynamic>?>(self::h1::T? t) → void {}
|
||||
static method h2<S extends FutureOr<self::h2::S?> = FutureOr<dynamic>>(self::h2::S? s) → void {}
|
||||
static method main() → dynamic {}
|
||||
Reference in New Issue
Block a user