[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 <johnniwinther@google.com> Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
This commit is contained in:
committed by
Commit Queue
parent
bda10d7987
commit
9fecc29dbb
@@ -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<void> h1<X extends Future<A>?>(X x) async {
|
||||
var x2 = await x; // Remains null.
|
||||
print([x2].runtimeType); // 'List<A>`.
|
||||
print(x2); // 'null': A soundness violation.
|
||||
}
|
||||
|
||||
void main() async => await h1<Null>(null);
|
||||
@@ -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<X extends asy::Future<self::A>?>(self::h1::X% x) → asy::Future<void> async /* futureValueType= void */ {
|
||||
self::A? x2 = await x /* runtimeCheckType= asy::Future<self::A?> */ ;
|
||||
core::print(<self::A?>[x2].{core::Object::runtimeType}{core::Type});
|
||||
core::print(x2);
|
||||
}
|
||||
static method main() → void async /* futureValueType= void */
|
||||
return await self::h1<Null>(null);
|
||||
@@ -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<X extends asy::Future<self::A>?>(self::h1::X% x) → asy::Future<void> async /* futureValueType= void */ {
|
||||
self::A? x2 = await x /* runtimeCheckType= asy::Future<self::A?> */ ;
|
||||
core::print(core::_GrowableList::_literal1<self::A?>(x2).{core::Object::runtimeType}{core::Type});
|
||||
core::print(x2);
|
||||
}
|
||||
static method main() → void async /* futureValueType= void */
|
||||
return await self::h1<Null>(null);
|
||||
@@ -0,0 +1,4 @@
|
||||
class A {}
|
||||
|
||||
Future<void> h1<X extends Future<A>?>(X x) async {}
|
||||
void main() async => await h1<Null>(null);
|
||||
@@ -0,0 +1,5 @@
|
||||
Future<void> h1<X extends Future<A>?>(X x) async {}
|
||||
|
||||
class A {}
|
||||
|
||||
void main() async => await h1<Null>(null);
|
||||
@@ -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<X extends asy::Future<self::A>?>(self::h1::X% x) → asy::Future<void> async /* futureValueType= void */ {
|
||||
self::A? x2 = await x /* runtimeCheckType= asy::Future<self::A?> */ ;
|
||||
core::print(<self::A?>[x2].{core::Object::runtimeType}{core::Type});
|
||||
core::print(x2);
|
||||
}
|
||||
static method main() → void async /* futureValueType= void */
|
||||
return await self::h1<Null>(null);
|
||||
@@ -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<X extends asy::Future<self::A>?>(self::h1::X% x) → asy::Future<void> async /* futureValueType= void */ {
|
||||
self::A? x2 = await x /* runtimeCheckType= asy::Future<self::A?> */ ;
|
||||
core::print(<self::A?>[x2].{core::Object::runtimeType}{core::Type});
|
||||
core::print(x2);
|
||||
}
|
||||
static method main() → void async /* futureValueType= void */
|
||||
return await self::h1<Null>(null);
|
||||
@@ -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<X extends asy::Future<self::A>?>(self::h1::X% x) → asy::Future<void> async
|
||||
;
|
||||
static method main() → void async
|
||||
;
|
||||
@@ -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<X extends asy::Future<self::A>?>(self::h1::X% x) → asy::Future<void> async /* futureValueType= void */ {
|
||||
self::A? x2 = await x /* runtimeCheckType= asy::Future<self::A?> */ ;
|
||||
core::print(core::_GrowableList::_literal1<self::A?>(x2).{core::Object::runtimeType}{core::Type});
|
||||
core::print(x2);
|
||||
}
|
||||
static method main() → void async /* futureValueType= void */
|
||||
return await self::h1<Null>(null);
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user