From c9e2b012b1132a4fc10ee9a8793651f6b1c807ba Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Tue, 13 Feb 2024 22:25:41 +0000 Subject: [PATCH] Make the type schema for null-aware spread operations consistent. Prior to this CL, the CFE used a nullable type schema for null-aware spread operators in list literals, but a non-nullable type schema for null-aware spread operators in set and map literals. This was clearly an oversight; a nullable type schema should be used for for null-aware spread operators in all kinds of collection literals. This change brings the CFE into alignment with the analyzer. Fixes https://github.com/dart-lang/sdk/issues/54828. Change-Id: I0d5aa128656c22211228f0dd35ccee40925b4ef0 Bug: https://github.com/dart-lang/sdk/issues/54828 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/349921 Commit-Queue: Paul Berry Reviewed-by: Chloe Stefantsova --- CHANGELOG.md | 8 ++++ .../type_inference/inference_visitor.dart | 3 ++ .../null_spread_context_test.dart | 37 +++++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 tests/language/spread_collections/null_spread_context_test.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 3db516fda4c..b8ff19c6c96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,15 @@ type), to align with the specification. This change is not expected to make any difference in practice. +- **Breaking Change** [#54828][]: The type schema used by the compiler front end + to perform type inference on the operand of a null-aware spread operator + (`...?`) in map and set literals has been made nullable, to match what + currently happens in list literals. This makes the compiler front end behavior + consistent with that of the analyzer. This change is expected to be very low + impact. + [#54640]: https://github.com/dart-lang/sdk/issues/54640 +[#54828]: https://github.com/dart-lang/sdk/issues/54828 ### Tools diff --git a/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart b/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart index f167c87adc6..aa143417b7e 100644 --- a/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart +++ b/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart @@ -3888,6 +3888,9 @@ class InferenceVisitorImpl extends InferenceVisitorBase Map inferredSpreadTypes, Map inferredConditionTypes, _MapLiteralEntryOffsets offsets) { + if (entry.isNullAware) { + spreadContext = computeNullable(spreadContext); + } ExpressionInferenceResult spreadResult = inferExpression(entry.expression, spreadContext, isVoidAllowed: true); if (entry.isNullAware) { diff --git a/tests/language/spread_collections/null_spread_context_test.dart b/tests/language/spread_collections/null_spread_context_test.dart new file mode 100644 index 00000000000..ac41bc0e96a --- /dev/null +++ b/tests/language/spread_collections/null_spread_context_test.dart @@ -0,0 +1,37 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Test that the context type schema for a null-aware spread is correct (it +// should be nullable compared to context type schema for a non-null-aware +// spread). + +import '../static_type_helper.dart'; + +main() { + { + List notNullAware = [ + ...(contextType([])..expectStaticType>>()) + ]; + List nullAware = [ + ...?(contextType([])..expectStaticType?>>()) + ]; + } + { + Set notNullAware = { + ...(contextType([])..expectStaticType>>()) + }; + Set nullAware = { + ...?(contextType([])..expectStaticType?>>()) + }; + } + { + Map notNullAware = { + ...(contextType({})..expectStaticType>>()) + }; + Map nullAware = { + ...?(contextType({}) + ..expectStaticType?>>()) + }; + } +}