From 261e283a0a56efe97e64086e0fffdf8cb489c344 Mon Sep 17 00:00:00 2001 From: Johnni Winther Date: Tue, 16 Jun 2020 12:28:04 +0000 Subject: [PATCH] [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 Commit-Queue: Johnni Winther --- .../fasta/builder/nullability_builder.dart | 11 ++++---- .../fasta/builder/type_variable_builder.dart | 26 ++++++++++++------- pkg/front_end/testcases/nnbd/issue42143.dart | 6 +++++ .../nnbd/issue42143.dart.outline.expect | 11 ++++++++ .../nnbd/issue42143.dart.strong.expect | 8 ++++++ .../issue42143.dart.strong.transformed.expect | 8 ++++++ .../issue42143.dart.textual_outline.expect | 5 ++++ ...42143.dart.textual_outline_modelled.expect | 5 ++++ .../nnbd/issue42143.dart.weak.expect | 8 ++++++ .../issue42143.dart.weak.transformed.expect | 8 ++++++ 10 files changed, 80 insertions(+), 16 deletions(-) create mode 100644 pkg/front_end/testcases/nnbd/issue42143.dart create mode 100644 pkg/front_end/testcases/nnbd/issue42143.dart.outline.expect create mode 100644 pkg/front_end/testcases/nnbd/issue42143.dart.strong.expect create mode 100644 pkg/front_end/testcases/nnbd/issue42143.dart.strong.transformed.expect create mode 100644 pkg/front_end/testcases/nnbd/issue42143.dart.textual_outline.expect create mode 100644 pkg/front_end/testcases/nnbd/issue42143.dart.textual_outline_modelled.expect create mode 100644 pkg/front_end/testcases/nnbd/issue42143.dart.weak.expect create mode 100644 pkg/front_end/testcases/nnbd/issue42143.dart.weak.transformed.expect diff --git a/pkg/front_end/lib/src/fasta/builder/nullability_builder.dart b/pkg/front_end/lib/src/fasta/builder/nullability_builder.dart index 54a2786e653..4d7b983d819 100644 --- a/pkg/front_end/lib/src/fasta/builder/nullability_builder.dart +++ b/pkg/front_end/lib/src/fasta/builder/nullability_builder.dart @@ -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) { diff --git a/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart index 8ec76cbce8b..b73ea200f26 100644 --- a/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart +++ b/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart @@ -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 { diff --git a/pkg/front_end/testcases/nnbd/issue42143.dart b/pkg/front_end/testcases/nnbd/issue42143.dart new file mode 100644 index 00000000000..a711b13e8cc --- /dev/null +++ b/pkg/front_end/testcases/nnbd/issue42143.dart @@ -0,0 +1,6 @@ +import 'dart:async'; + +void h1?>(T? t) {} +void h2>(S? s) {} + +main() {} diff --git a/pkg/front_end/testcases/nnbd/issue42143.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue42143.dart.outline.expect new file mode 100644 index 00000000000..a3735a10ef5 --- /dev/null +++ b/pkg/front_end/testcases/nnbd/issue42143.dart.outline.expect @@ -0,0 +1,11 @@ +library /*isNonNullableByDefault*/; +import self as self; + +import "dart:async"; + +static method h1? = FutureOr?>(self::h1::T? t) → void + ; +static method h2 = FutureOr>(self::h2::S? s) → void + ; +static method main() → dynamic + ; diff --git a/pkg/front_end/testcases/nnbd/issue42143.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue42143.dart.strong.expect new file mode 100644 index 00000000000..dd9388c37d7 --- /dev/null +++ b/pkg/front_end/testcases/nnbd/issue42143.dart.strong.expect @@ -0,0 +1,8 @@ +library /*isNonNullableByDefault*/; +import self as self; + +import "dart:async"; + +static method h1? = FutureOr?>(self::h1::T? t) → void {} +static method h2 = FutureOr>(self::h2::S? s) → void {} +static method main() → dynamic {} diff --git a/pkg/front_end/testcases/nnbd/issue42143.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue42143.dart.strong.transformed.expect new file mode 100644 index 00000000000..dd9388c37d7 --- /dev/null +++ b/pkg/front_end/testcases/nnbd/issue42143.dart.strong.transformed.expect @@ -0,0 +1,8 @@ +library /*isNonNullableByDefault*/; +import self as self; + +import "dart:async"; + +static method h1? = FutureOr?>(self::h1::T? t) → void {} +static method h2 = FutureOr>(self::h2::S? s) → void {} +static method main() → dynamic {} diff --git a/pkg/front_end/testcases/nnbd/issue42143.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue42143.dart.textual_outline.expect new file mode 100644 index 00000000000..ea78e4726a5 --- /dev/null +++ b/pkg/front_end/testcases/nnbd/issue42143.dart.textual_outline.expect @@ -0,0 +1,5 @@ +import 'dart:async'; + +void h1?>(T? t) {} +void h2>(S? s) {} +main() {} diff --git a/pkg/front_end/testcases/nnbd/issue42143.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue42143.dart.textual_outline_modelled.expect new file mode 100644 index 00000000000..993350a05b7 --- /dev/null +++ b/pkg/front_end/testcases/nnbd/issue42143.dart.textual_outline_modelled.expect @@ -0,0 +1,5 @@ +import 'dart:async'; + +main() {} +void h1?>(T? t) {} +void h2>(S? s) {} diff --git a/pkg/front_end/testcases/nnbd/issue42143.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue42143.dart.weak.expect new file mode 100644 index 00000000000..dd9388c37d7 --- /dev/null +++ b/pkg/front_end/testcases/nnbd/issue42143.dart.weak.expect @@ -0,0 +1,8 @@ +library /*isNonNullableByDefault*/; +import self as self; + +import "dart:async"; + +static method h1? = FutureOr?>(self::h1::T? t) → void {} +static method h2 = FutureOr>(self::h2::S? s) → void {} +static method main() → dynamic {} diff --git a/pkg/front_end/testcases/nnbd/issue42143.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42143.dart.weak.transformed.expect new file mode 100644 index 00000000000..dd9388c37d7 --- /dev/null +++ b/pkg/front_end/testcases/nnbd/issue42143.dart.weak.transformed.expect @@ -0,0 +1,8 @@ +library /*isNonNullableByDefault*/; +import self as self; + +import "dart:async"; + +static method h1? = FutureOr?>(self::h1::T? t) → void {} +static method h2 = FutureOr>(self::h2::S? s) → void {} +static method main() → dynamic {}