From 9fecc29dbb0c836ba6772be004ee3957b2a7ade6 Mon Sep 17 00:00:00 2001 From: Chloe Stefantsova Date: Wed, 31 May 2023 07:33:37 +0000 Subject: [PATCH] [cfe] Adjust the resulting nullabilities in 'flatten' Closes https://github.com/dart-lang/sdk/issues/52485 Change-Id: I428933193611ffc68c750e6dc91f54ee2385036b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/306400 Reviewed-by: Johnni Winther Commit-Queue: Chloe Stefantsova --- .../testcases/general/issue52485.dart | 13 +++++++++++ .../general/issue52485.dart.strong.expect | 17 ++++++++++++++ .../issue52485.dart.strong.transformed.expect | 17 ++++++++++++++ .../issue52485.dart.textual_outline.expect | 4 ++++ ...52485.dart.textual_outline_modelled.expect | 5 ++++ .../general/issue52485.dart.weak.expect | 17 ++++++++++++++ .../issue52485.dart.weak.modular.expect | 17 ++++++++++++++ .../issue52485.dart.weak.outline.expect | 13 +++++++++++ .../issue52485.dart.weak.transformed.expect | 17 ++++++++++++++ pkg/kernel/lib/type_environment.dart | 23 +++++++++++++++---- 10 files changed, 139 insertions(+), 4 deletions(-) create mode 100644 pkg/front_end/testcases/general/issue52485.dart create mode 100644 pkg/front_end/testcases/general/issue52485.dart.strong.expect create mode 100644 pkg/front_end/testcases/general/issue52485.dart.strong.transformed.expect create mode 100644 pkg/front_end/testcases/general/issue52485.dart.textual_outline.expect create mode 100644 pkg/front_end/testcases/general/issue52485.dart.textual_outline_modelled.expect create mode 100644 pkg/front_end/testcases/general/issue52485.dart.weak.expect create mode 100644 pkg/front_end/testcases/general/issue52485.dart.weak.modular.expect create mode 100644 pkg/front_end/testcases/general/issue52485.dart.weak.outline.expect create mode 100644 pkg/front_end/testcases/general/issue52485.dart.weak.transformed.expect diff --git a/pkg/front_end/testcases/general/issue52485.dart b/pkg/front_end/testcases/general/issue52485.dart new file mode 100644 index 00000000000..e231542e291 --- /dev/null +++ b/pkg/front_end/testcases/general/issue52485.dart @@ -0,0 +1,13 @@ +// Copyright (c) 2023, 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. + +class A {} + +Future h1?>(X x) async { + var x2 = await x; // Remains null. + print([x2].runtimeType); // 'List`. + print(x2); // 'null': A soundness violation. +} + +void main() async => await h1(null); diff --git a/pkg/front_end/testcases/general/issue52485.dart.strong.expect b/pkg/front_end/testcases/general/issue52485.dart.strong.expect new file mode 100644 index 00000000000..a7bf23575fc --- /dev/null +++ b/pkg/front_end/testcases/general/issue52485.dart.strong.expect @@ -0,0 +1,17 @@ +library /*isNonNullableByDefault*/; +import self as self; +import "dart:core" as core; +import "dart:async" as asy; + +class A extends core::Object { + synthetic constructor •() → self::A + : super core::Object::•() + ; +} +static method h1?>(self::h1::X% x) → asy::Future async /* futureValueType= void */ { + self::A? x2 = await x /* runtimeCheckType= asy::Future */ ; + core::print([x2].{core::Object::runtimeType}{core::Type}); + core::print(x2); +} +static method main() → void async /* futureValueType= void */ + return await self::h1(null); diff --git a/pkg/front_end/testcases/general/issue52485.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue52485.dart.strong.transformed.expect new file mode 100644 index 00000000000..3471777bdbc --- /dev/null +++ b/pkg/front_end/testcases/general/issue52485.dart.strong.transformed.expect @@ -0,0 +1,17 @@ +library /*isNonNullableByDefault*/; +import self as self; +import "dart:core" as core; +import "dart:async" as asy; + +class A extends core::Object { + synthetic constructor •() → self::A + : super core::Object::•() + ; +} +static method h1?>(self::h1::X% x) → asy::Future async /* futureValueType= void */ { + self::A? x2 = await x /* runtimeCheckType= asy::Future */ ; + core::print(core::_GrowableList::_literal1(x2).{core::Object::runtimeType}{core::Type}); + core::print(x2); +} +static method main() → void async /* futureValueType= void */ + return await self::h1(null); diff --git a/pkg/front_end/testcases/general/issue52485.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue52485.dart.textual_outline.expect new file mode 100644 index 00000000000..e7d14fd3383 --- /dev/null +++ b/pkg/front_end/testcases/general/issue52485.dart.textual_outline.expect @@ -0,0 +1,4 @@ +class A {} + +Future h1?>(X x) async {} +void main() async => await h1(null); diff --git a/pkg/front_end/testcases/general/issue52485.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue52485.dart.textual_outline_modelled.expect new file mode 100644 index 00000000000..9ea9b72839e --- /dev/null +++ b/pkg/front_end/testcases/general/issue52485.dart.textual_outline_modelled.expect @@ -0,0 +1,5 @@ +Future h1?>(X x) async {} + +class A {} + +void main() async => await h1(null); diff --git a/pkg/front_end/testcases/general/issue52485.dart.weak.expect b/pkg/front_end/testcases/general/issue52485.dart.weak.expect new file mode 100644 index 00000000000..a7bf23575fc --- /dev/null +++ b/pkg/front_end/testcases/general/issue52485.dart.weak.expect @@ -0,0 +1,17 @@ +library /*isNonNullableByDefault*/; +import self as self; +import "dart:core" as core; +import "dart:async" as asy; + +class A extends core::Object { + synthetic constructor •() → self::A + : super core::Object::•() + ; +} +static method h1?>(self::h1::X% x) → asy::Future async /* futureValueType= void */ { + self::A? x2 = await x /* runtimeCheckType= asy::Future */ ; + core::print([x2].{core::Object::runtimeType}{core::Type}); + core::print(x2); +} +static method main() → void async /* futureValueType= void */ + return await self::h1(null); diff --git a/pkg/front_end/testcases/general/issue52485.dart.weak.modular.expect b/pkg/front_end/testcases/general/issue52485.dart.weak.modular.expect new file mode 100644 index 00000000000..a7bf23575fc --- /dev/null +++ b/pkg/front_end/testcases/general/issue52485.dart.weak.modular.expect @@ -0,0 +1,17 @@ +library /*isNonNullableByDefault*/; +import self as self; +import "dart:core" as core; +import "dart:async" as asy; + +class A extends core::Object { + synthetic constructor •() → self::A + : super core::Object::•() + ; +} +static method h1?>(self::h1::X% x) → asy::Future async /* futureValueType= void */ { + self::A? x2 = await x /* runtimeCheckType= asy::Future */ ; + core::print([x2].{core::Object::runtimeType}{core::Type}); + core::print(x2); +} +static method main() → void async /* futureValueType= void */ + return await self::h1(null); diff --git a/pkg/front_end/testcases/general/issue52485.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue52485.dart.weak.outline.expect new file mode 100644 index 00000000000..c912c4fb8c9 --- /dev/null +++ b/pkg/front_end/testcases/general/issue52485.dart.weak.outline.expect @@ -0,0 +1,13 @@ +library /*isNonNullableByDefault*/; +import self as self; +import "dart:core" as core; +import "dart:async" as asy; + +class A extends core::Object { + synthetic constructor •() → self::A + ; +} +static method h1?>(self::h1::X% x) → asy::Future async + ; +static method main() → void async + ; diff --git a/pkg/front_end/testcases/general/issue52485.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue52485.dart.weak.transformed.expect new file mode 100644 index 00000000000..3471777bdbc --- /dev/null +++ b/pkg/front_end/testcases/general/issue52485.dart.weak.transformed.expect @@ -0,0 +1,17 @@ +library /*isNonNullableByDefault*/; +import self as self; +import "dart:core" as core; +import "dart:async" as asy; + +class A extends core::Object { + synthetic constructor •() → self::A + : super core::Object::•() + ; +} +static method h1?>(self::h1::X% x) → asy::Future async /* futureValueType= void */ { + self::A? x2 = await x /* runtimeCheckType= asy::Future */ ; + core::print(core::_GrowableList::_literal1(x2).{core::Object::runtimeType}{core::Type}); + core::print(x2); +} +static method main() → void async /* futureValueType= void */ + return await self::h1(null); diff --git a/pkg/kernel/lib/type_environment.dart b/pkg/kernel/lib/type_environment.dart index 5fbd0efcb08..4b1585feeea 100644 --- a/pkg/kernel/lib/type_environment.dart +++ b/pkg/kernel/lib/type_environment.dart @@ -129,18 +129,33 @@ abstract class TypeEnvironment extends Types { DartType bound = t.right; DartType? futureType = _futureTypeOf(bound); if (futureType != null) { - return _withDeclaredNullability(flatten(futureType), t.nullability); + DartType flattenedFutureType = flatten(futureType); + return _withDeclaredNullability(flattenedFutureType, + uniteNullabilities(t.nullability, flattenedFutureType.nullability)); } else { - return _withDeclaredNullability(flatten(t.left), t.nullability); + DartType flattenedFutureType = flatten(t.left); + return _withDeclaredNullability(flattenedFutureType, + uniteNullabilities(t.nullability, flattenedFutureType.nullability)); } } else { DartType? futureType = _futureTypeOf(t); if (futureType is InterfaceType) { assert(futureType.classNode == coreTypes.futureClass); + DartType typeArgument = futureType.typeArguments.single; return _withDeclaredNullability( - futureType.typeArguments.single, t.nullability); + typeArgument, + uniteNullabilities( + t.nullability, + uniteNullabilities( + futureType.nullability, typeArgument.nullability))); } else if (futureType is FutureOrType) { - return _withDeclaredNullability(futureType.typeArgument, t.nullability); + DartType typeArgument = futureType.typeArgument; + return _withDeclaredNullability( + typeArgument, + uniteNullabilities( + t.nullability, + uniteNullabilities( + futureType.nullability, typeArgument.nullability))); } else { return t; }