Skip to content

Commit

Permalink
[vm,dart2wasm,tfa] Handle 'Never' static type as unreachable in TFA
Browse files Browse the repository at this point in the history
When building a data flow summary, break control and data flow after
invocations with static result type 'Never', expressing that code after
such invocation is unreachable.

TEST=pkg/vm/testcases/transformations/type_flow/summary_collector/control_flow.dart

Issue: #59941
Change-Id: I2e5acd861e4192bae231d356aeacf921a14766f5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/405443
Reviewed-by: Slava Egorov <[email protected]>
Commit-Queue: Alexander Markov <[email protected]>
  • Loading branch information
alexmarkov authored and Commit Queue committed Jan 23, 2025
1 parent bf35086 commit 11ea496
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 9 deletions.
28 changes: 19 additions & 9 deletions pkg/vm/lib/transformations/type_flow/summary_collector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1275,29 +1275,39 @@ class SummaryCollector extends RecursiveResultVisitor<TypeExpr?> {
_declareVariable(decl, _typesBuilder.fromStaticType(decl.type, true));
}

Call _makeCall(TreeNode node, Selector selector, Args<TypeExpr> args,
TypeExpr _makeCall(TreeNode node, Selector selector, Args<TypeExpr> args,
{bool isInstanceCreation = false}) {
Type? staticResultType = null;
Member? target;
if (selector is DirectSelector) {
target = selector.member;
} else if (selector is InterfaceSelector) {
target = selector.member;
}
if (target is Procedure && node is Expression) {
final returnType = target.function.returnType;
Type? staticResultType = null;
if (node is Expression) {
final staticDartType = _staticDartType(node);
// TODO(dartbug.com/54200): static type cannot be trusted when
// function type is returned.
if (returnType is TypeParameterType ||
(returnType != staticDartType && returnType is! FunctionType)) {
staticResultType = _typesBuilder.fromStaticType(staticDartType, true);
if (staticDartType is NeverType &&
staticDartType.declaredNullability == Nullability.nonNullable) {
staticResultType = emptyType;
} else if (target is Procedure) {
final returnType = target.function.returnType;
// TODO(dartbug.com/54200): static type cannot be trusted when
// function type is returned.
if (returnType is TypeParameterType ||
(returnType != staticDartType && returnType is! FunctionType)) {
staticResultType = _typesBuilder.fromStaticType(staticDartType, true);
}
}
}
Call call = new Call(selector, args, staticResultType, isInstanceCreation);
call.condition = _currentCondition;
_summary.add(call);
callSites[node] = call;
if (staticResultType is EmptyType) {
_currentCondition = emptyType;
_variableValues = _makeEmptyVariableValues();
return emptyType;
}
return call;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,4 +324,15 @@ void cast1(x) {
bar(x);
}

void never1(bool cond) {
int i = 1;
if (cond) {
i = 2;
returnNever();
}
foo(i);
}

Never returnNever() => throw 'bye';

main() {}
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,15 @@ t1 = _TypeCheck (%x against #lib::C1) (for x as #lib::C1)
t2 = _Call direct [#lib::foo] (t1)
t3 = _Call direct [#lib::bar] (t1)
RESULT: _T {}?
------------ never1 ------------
%cond = _Parameter #0 [_T (dart.core::bool)+]
t1 = _Call direct [#lib::returnNever] () {%cond}
t2 = Not (%cond)
t3 = _Call direct [#lib::foo] (_T (dart.core::_Smi, 1)) {t2}
RESULT: _T {}?
------------ returnNever ------------

RESULT: _T {}
------------ main ------------

RESULT: _T {}?

0 comments on commit 11ea496

Please sign in to comment.