Skip to content

Commit

Permalink
[vm, dart2wasm, tfa] Do not infer nullable return type when static ty…
Browse files Browse the repository at this point in the history
…pe is non-nullable

With sound null safety, implicit "return null" at the end of function
should be taken into account only if return type is nullable.

TEST=pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter148617.dart

Issue: flutter/flutter#148617
Change-Id: I209fc9a3b10639fd4024d4b1807591498349e1f0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/367980
Reviewed-by: Martin Kustermann <[email protected]>
Commit-Queue: Alexander Markov <[email protected]>
  • Loading branch information
alexmarkov authored and Commit Queue committed May 23, 2024
1 parent 8c26c35 commit 345b437
Show file tree
Hide file tree
Showing 12 changed files with 81 additions and 33 deletions.
3 changes: 2 additions & 1 deletion pkg/vm/lib/transformations/type_flow/summary_collector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -837,7 +837,8 @@ class SummaryCollector extends RecursiveResultVisitor<TypeExpr?> {
} else {
_visitWithoutResult(function.body!);

if (_currentCondition is! EmptyType) {
if (function.returnType.nullability != Nullability.nonNullable &&
_currentCondition is! EmptyType) {
_returnValue!.values.add(_nullType);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ static method main() → void {
final self::MyFinalizable finalizable = new self::MyFinalizable::•();
{
synthesized core::Iterator<core::int> :sync-for-iterator = [@vm.direct-call.metadata=dart.async::_SyncStarIterable.iterator] [@vm.inferred-type.metadata=dart.async::_SyncStarIterator] [@vm.inferred-type.metadata=dart.async::_SyncStarIterable] self::useFinalizableSyncStar(finalizable).{core::Iterable::iterator}{core::Iterator<core::int>};
for (; [@vm.direct-call.metadata=dart.async::_SyncStarIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool? (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
for (; [@vm.direct-call.metadata=dart.async::_SyncStarIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
final core::int element = [@vm.direct-call.metadata=dart.async::_SyncStarIterator.current] [@vm.inferred-type.metadata=int] :sync-for-iterator.{core::Iterator::current}{core::int};
{
core::print(element);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
------------ A. ------------
%this = _Parameter #0 [_T (#lib::A)+]
t1 = _Call direct [dart.core::Object.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ A.foo1 ------------
%this = _Parameter #0 [_T (#lib::A)+]
%x = _Parameter #1 [_T (dart.core::Object)+]
RESULT: _T {}?
------------ B. ------------
%this = _Parameter #0 [_T (#lib::B)+]
t1 = _Call direct [dart.core::Object.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ B.bar1 ------------
%this = _Parameter #0 [_T (#lib::B)+]
%arg = _Parameter #1 [_T (dart.core::Object)+]
Expand All @@ -27,7 +27,7 @@ RESULT: _T {}?
------------ C. ------------
%this = _Parameter #0 [_T (#lib::C)+]
t1 = _Call direct [dart.core::Object.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ C.interfaceCalls ------------
%this = _Parameter #0 [_T (#lib::C)+]
%aa = _Parameter #1 [_T (#lib::A)+]
Expand Down Expand Up @@ -61,7 +61,7 @@ RESULT: t11
------------ D. ------------
%this = _Parameter #0 [_T (#lib::D)+]
t1 = _Call direct [#lib::B.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ D.superCalls ------------
%this = _Parameter #0 [_T (#lib::D)+]
%a1 = _Parameter #1 [_T (dart.core::Object)+]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
------------ C. ------------
%this = _Parameter #0 [_T (#lib::C)+]
t1 = _Call direct [dart.core::Object.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ C.foo ------------
%this = _Parameter #0 [_T (#lib::C)+]
t1 = _Extract (%this[#lib::C/0])
Expand All @@ -23,11 +23,11 @@ RESULT: t3
------------ D. ------------
%this = _Parameter #0 [_T (#lib::D)+]
t1 = _Call direct [dart.core::Object.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ E. ------------
%this = _Parameter #0 [_T (#lib::E)+]
t1 = _Call direct [#lib::C.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ E.foo ------------
%this = _Parameter #0 [_T (#lib::E)+]
t1* = _Call direct [#lib::C.foo] (%this)
Expand All @@ -47,31 +47,31 @@ RESULT: t3
------------ X. ------------
%this = _Parameter #0 [_T (#lib::X)+]
t1 = _Call direct [dart.core::Object.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ Y. ------------
%this = _Parameter #0 [_T (#lib::Y)+]
t1 = _Call direct [#lib::X.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ Z. ------------
%this = _Parameter #0 [_T (#lib::Z)+]
t1 = _Call direct [#lib::X.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ I. ------------
%this = _Parameter #0 [_T (#lib::I)+]
t1 = _Call direct [dart.core::Object.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ J. ------------
%this = _Parameter #0 [_T (#lib::J)+]
t1 = _Call direct [#lib::I.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ K. ------------
%this = _Parameter #0 [_T (#lib::K)+]
t1 = _Call direct [dart.core::Object.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ C2. ------------
%this = _Parameter #0 [_T (#lib::C2)+]
t1 = _Call direct [dart.core::Object.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ C2.id3 ------------
%this = _Parameter #0 [_T (#lib::C2)+]
%x = _Parameter #1
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
------------ Element. ------------
%this = _Parameter #0 [_T (#lib::Element)+]
t1 = _Call direct [dart.core::Object.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ MockHashMap. ------------
%K = _Parameter #0
%V = _Parameter #1
Expand All @@ -11,7 +11,7 @@ RESULT: t3
------------ _NotRealHashMap. ------------
%this = _Parameter #0 [_T (#lib::_NotRealHashMap)+]
t1 = _Call direct [dart.core::Object.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ _NotRealHashMap.setEntry ------------
%this = _Parameter #0 [_T (#lib::_NotRealHashMap)+]
%key = _Parameter #1
Expand All @@ -24,7 +24,7 @@ RESULT: _T {}?
------------ InheritedElement. ------------
%this = _Parameter #0 [_T (#lib::InheritedElement)+]
t1 = _Call direct [#lib::Element.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ InheritedElement.setDependencies ------------
%this = _Parameter #0 [_T (#lib::InheritedElement)+]
%dependent = _Parameter #1 [_T (#lib::Element)+]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
------------ C1. ------------
%this = _Parameter #0 [_T (#lib::C1)+]
t1 = _Call direct [dart.core::Object.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ C2. ------------
%this = _Parameter #0 [_T (#lib::C2)+]
t1 = _Call direct [dart.core::Object.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ C3. ------------
%this = _Parameter #0 [_T (#lib::C3)+]
t1 = _Call direct [dart.core::Object.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ C4. ------------
%this = _Parameter #0 [_T (#lib::C4)+]
t1 = _Call direct [dart.core::Object.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ C5. ------------
%this = _Parameter #0 [_T (#lib::C5)+]
t1 = _Call direct [dart.core::Object.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ TestEnum. ------------
%this = _Parameter #0 [_T (#lib::TestEnum)+]
%#index = _Parameter #1 [_T (dart.core::int)+]
%#name = _Parameter #2 [_T (dart.core::String)+]
t3 = _Call direct [dart.core::_Enum.] (%this, %#index, %#name)
RESULT: _T {}?
RESULT: _T {}
------------ TestEnum._enumToString ------------
%this = _Parameter #0 [_T (#lib::TestEnum)+]
t1 = _Call virtual get [dart.core::_Enum._name] (%this)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
------------ T. ------------
%this = _Parameter #0 [_T (#lib::T)+]
t1 = _Call direct [dart.core::Object.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ empty1 ------------

RESULT: _T {}?
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
------------ T. ------------
%this = _Parameter #0 [_T (#lib::T)+]
t1 = _Call direct [dart.core::Object.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ A. ------------
%this = _Parameter #0 [_T (#lib::A)+]
t1 = _Call direct [dart.core::Object.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ A.foo ------------
%this = _Parameter #0 [_T (#lib::A)+]
RESULT: _T {}?
------------ B. ------------
%this = _Parameter #0 [_T (#lib::B)+]
t1 = _Call direct [#lib::A.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ B.foo ------------
%this = _Parameter #0 [_T (#lib::B)+]
%x = _Parameter #1 [_T ANY?]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
------------ A. ------------
%this = _Parameter #0 [_T (#lib::A)+]
t1 = _Call direct [dart.core::Object.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ B. ------------
%this = _Parameter #0 [_T (#lib::B)+]
t1 = _Call direct [dart.core::Object.] (%this)
RESULT: _T {}?
RESULT: _T {}
------------ foo ------------
%a1 = _Parameter #0 [_T (dart.core::Object)+]
%a2 = _Parameter #1 [_T (dart.core::Object)+?]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ static method isPrime([@vm.inferred-arg-type.metadata=int] dynamic n) → core::
return true;
}

[@vm.inferred-return-type.metadata=int?]
[@vm.inferred-return-type.metadata=int]
[@vm.unboxing-info.metadata=()->i]
static method nThPrimeNumber() → core::int {
core::int counter = 0;
for (core::int i = 1; ; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num) → core::int}) {
Expand All @@ -31,7 +32,7 @@ static method nThPrimeNumber() → core::int {
[@vm.inferred-return-type.metadata=dart.core::Null? (value: null)]
static method run() → void {
core::int e = 611953;
core::int p = [@vm.inferred-type.metadata=int?] self::nThPrimeNumber();
core::int p = [@vm.inferred-type.metadata=int] self::nThPrimeNumber();
if(!([@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] p =={core::num::==}{(core::Object) → core::bool} e)) {
throw core::Exception::•("Unexpected result: ${p} != ${e}");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// 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.

// Regression test for https://github.com/flutter/flutter/issues/148617.
// Verifies that TFA should not infer nullable return type if
// static return type is non-nullable.

int foo() => int.parse('1');

int bar() {
try {
return foo();
} catch (e, st) {
Error.throwWithStackTrace(e, st);
}
}

main() {
print(bar());
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
library #lib;
import self as self;
import "dart:core" as core;


[@vm.inferred-return-type.metadata=int]
[@vm.unboxing-info.metadata=()->i]
static method foo() → core::int
return [@vm.inferred-type.metadata=int] core::int::parse("1");

[@vm.inferred-return-type.metadata=int]
[@vm.unboxing-info.metadata=()->i]
static method bar() → core::int {
try {
return [@vm.inferred-type.metadata=int] self::foo();
}
on core::Object catch(final core::Object e, final core::StackTrace st) {
core::Error::throwWithStackTrace(e, st);
}
}

[@vm.inferred-return-type.metadata=dart.core::Null? (value: null)]
static method main() → dynamic {
core::print([@vm.inferred-type.metadata=int] self::bar());
}

0 comments on commit 345b437

Please sign in to comment.