[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:
Johnni Winther
2020-06-16 12:28:04 +00:00
committed by commit-bot@chromium.org
parent 21222b64c4
commit 261e283a0a
10 changed files with 80 additions and 16 deletions
@@ -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 {}