Skip to content

Commit d213d3c

Browse files
Dmitry Stefantsovcommit-bot@chromium.org
Dmitry Stefantsov
authored and
commit-bot@chromium.org
committed
[cfe] Start implementing reachability analysis involving type Never
Change-Id: I80edd4dd1b46b533a4f50243e1d3b18aa00f80ac Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/123250 Commit-Queue: Dmitry Stefantsov <dmitryas@google.com> Reviewed-by: Paul Berry <paulberry@google.com> Reviewed-by: Johnni Winther <johnniwinther@google.com>
1 parent cdb1ed7 commit d213d3c

File tree

6 files changed

+44
-2
lines changed

6 files changed

+44
-2
lines changed

pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart

+3
Original file line numberDiff line numberDiff line change
@@ -1045,10 +1045,13 @@ class InferenceVisitor
10451045
Expression condition =
10461046
inferrer.ensureAssignableResult(expectedType, conditionResult);
10471047
node.condition = condition..parent = node;
1048+
inferrer.flowAnalysis.ifStatement_thenBegin(condition);
10481049
inferrer.inferStatement(node.then);
10491050
if (node.otherwise != null) {
1051+
inferrer.flowAnalysis.ifStatement_elseBegin();
10501052
inferrer.inferStatement(node.otherwise);
10511053
}
1054+
inferrer.flowAnalysis.ifStatement_end(node.otherwise != null);
10521055
}
10531056

10541057
ExpressionInferenceResult visitIntJudgment(

pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart

+3
Original file line numberDiff line numberDiff line change
@@ -1452,6 +1452,9 @@ class TypeInferrerImpl implements TypeInferrer {
14521452
messageVoidExpression, expression.fileOffset, noLength);
14531453
}
14541454
}
1455+
if (result.inferredType is NeverType) {
1456+
flowAnalysis.handleExit();
1457+
}
14551458
return result;
14561459
}
14571460

pkg/front_end/lib/src/testing/id_extractor.dart

+14
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,14 @@ abstract class DataExtractor<T> extends Visitor with DataRegistry<T> {
140140
return new NodeId(node.fileOffset, IdKind.moveNext);
141141
}
142142

143+
NodeId createExpressionStatementId(ExpressionStatement node) {
144+
if (node.expression.fileOffset == TreeNode.noOffset) {
145+
// TODO(johnniwinther): Find out why we something have no offset.
146+
return null;
147+
}
148+
return new NodeId(node.expression.fileOffset, IdKind.stmt);
149+
}
150+
143151
NodeId createLabeledStatementId(LabeledStatement node) =>
144152
computeDefaultNodeId(node.body);
145153
NodeId createLoopId(TreeNode node) => computeDefaultNodeId(node);
@@ -272,6 +280,12 @@ abstract class DataExtractor<T> extends Visitor with DataRegistry<T> {
272280
super.visitVariableSet(node);
273281
}
274282

283+
@override
284+
visitExpressionStatement(ExpressionStatement node) {
285+
computeForNode(node, createExpressionStatementId(node));
286+
return super.visitExpressionStatement(node);
287+
}
288+
275289
@override
276290
visitIfStatement(IfStatement node) {
277291
computeForNode(node, computeDefaultNodeId(node));

pkg/front_end/test/flow_analysis/reachability/data/never_return_type.dart

+15
Original file line numberDiff line numberDiff line change
@@ -162,14 +162,29 @@ Never topLevelFunction() => throw 'foo';
162162
class C {
163163
final dynamic field1;
164164
final dynamic field2;
165+
166+
/*cfe.member: C.method:doesNotComplete*/
165167
Never method() => throw 'foo';
168+
169+
/*cfe.member: C.staticMethod:doesNotComplete*/
166170
static Never staticMethod() => throw 'foo';
171+
167172
void methodTakingArgument(arg) {}
168173
void methodTakingNamedArgument({arg}) {}
174+
175+
/*cfe.member: C.getter:doesNotComplete*/
169176
Never get getter => throw 'foo';
177+
178+
/*cfe.member: C.staticGetter:doesNotComplete*/
170179
static Never get staticGetter => throw 'foo';
180+
181+
/*cfe.member: C.+:doesNotComplete*/
171182
Never operator +(other) => throw 'foo';
183+
184+
/*cfe.member: C.[]:doesNotComplete*/
172185
Never operator [](other) => throw 'foo';
186+
187+
/*cfe.member: C.unary-:doesNotComplete*/
173188
Never operator -() => throw 'foo';
174189

175190
/*member: C.constructor_initializer:doesNotComplete*/

pkg/front_end/test/flow_analysis/reachability/reachability_test.dart

+8-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ main(List<String> args) async {
3232
'assert.dart',
3333
'do.dart',
3434
'for.dart',
35-
'never_return_type.dart',
3635
'switch.dart',
3736
'try_catch.dart',
3837
]);
@@ -84,7 +83,14 @@ class ReachabilityDataExtractor
8483
@override
8584
Set<_ReachabilityAssertion> computeNodeValue(Id id, TreeNode node) {
8685
Set<_ReachabilityAssertion> result = {};
87-
if (_flowResult.unreachableNodes.contains(node)) {
86+
if (node is Expression && node.parent is ExpressionStatement) {
87+
// The reachability of an expression statement and the statement it
88+
// contains should always be the same. We check this with an assert
89+
// statement, and only annotate the expression statement, to reduce the
90+
// amount of redundancy in the test files.
91+
assert(_flowResult.unreachableNodes.contains(node) ==
92+
_flowResult.unreachableNodes.contains(node.parent));
93+
} else if (_flowResult.unreachableNodes.contains(node)) {
8894
result.add(_ReachabilityAssertion.unreachable);
8995
}
9096
if (node is FunctionDeclaration) {

pkg/front_end/test/spell_checking_list_common.txt

+1
Original file line numberDiff line numberDiff line change
@@ -2250,6 +2250,7 @@ redirects
22502250
reduce
22512251
reduced
22522252
reduces
2253+
redundancy
22532254
redundant
22542255
refactor
22552256
refer

0 commit comments

Comments
 (0)