Skip to content

Commit fe6f87f

Browse files
stereotype441Commit Queue
authored andcommitted
[analyzer] Fix dead code reporting in property access and is/as.
The way dead code detection works in the analyzer is that at various ad hoc times during the process of resolution (typically before visiting an expression or statement), the `ResolverVisitor` calls `checkUnreachableNode`, which asks flow analysis whether the current point in execution is reachable, and if it isn't, arranges for an unreachable code warning to be produced. This wasn't working for property extractions, type casts, and type tests because there's no subexpression whose execution follows the subexpression that returns `Never`, so `checkUnreachableNode` wasn't getting called. The fix is simple; just add some calls to `checkUnreachableNode` to cover the RHS of a property access, type cast, or type test. Note that property accesses in the analyzer can be represented either as `PrefixedIdentifier` or `PropertyAccess`, so the property access fix had to be done in two places (and accordingly there are two tests for it). Fixes #60247. Bug: #60247 Change-Id: I49e739784f629b77443ce6d31e67809f48de75be Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/413521 Reviewed-by: Konstantin Shcheglov <[email protected]> Commit-Queue: Paul Berry <[email protected]> Auto-Submit: Paul Berry <[email protected]>
1 parent 29c24db commit fe6f87f

File tree

5 files changed

+51
-0
lines changed

5 files changed

+51
-0
lines changed

pkg/analyzer/lib/src/dart/resolver/prefixed_identifier_resolver.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class PrefixedIdentifierResolver {
2929
}) {
3030
_resolver.analyzeExpression(node.prefix, _resolver.operations.unknownType);
3131
_resolver.popRewrite();
32+
_resolver.checkUnreachableNode(node.identifier);
3233

3334
var prefixElement = node.prefix.element;
3435
if (prefixElement is! PrefixElement2) {

pkg/analyzer/lib/src/generated/resolver.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1822,6 +1822,7 @@ class ResolverVisitor extends ThrowingAstVisitor<void>
18221822
node.expression, SharedTypeSchemaView(UnknownInferredType.instance));
18231823
popRewrite();
18241824

1825+
checkUnreachableNode(node.type);
18251826
node.type.accept(this);
18261827

18271828
typeAnalyzer.visitAsExpression(node);
@@ -3070,6 +3071,7 @@ class ResolverVisitor extends ThrowingAstVisitor<void>
30703071
node.expression, SharedTypeSchemaView(UnknownInferredType.instance));
30713072
popRewrite();
30723073

3074+
checkUnreachableNode(node.type);
30733075
node.type.accept(this);
30743076

30753077
typeAnalyzer.visitIsExpression(node);
@@ -3455,6 +3457,7 @@ class ResolverVisitor extends ThrowingAstVisitor<void>
34553457
popRewrite();
34563458
}
34573459

3460+
checkUnreachableNode(node.propertyName);
34583461
_resolvePropertyAccessRhs(node, contextType);
34593462
inferenceLogWriter?.exitExpression(node);
34603463
}

pkg/analyzer/test/src/dart/resolution/extension_method_test.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,6 +1044,7 @@ extension E on Never {
10441044
}
10451045
10461046
f(Never a) {
1047+
// ignore: dead_code
10471048
a.foo;
10481049
}
10491050
''');

pkg/analyzer/test/src/diagnostics/dead_code_test.dart

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,16 @@ main() {
1717
@reflectiveTest
1818
class DeadCodeTest extends PubPackageResolutionTest
1919
with DeadCodeTestCases_Language212 {
20+
test_asExpression_type() async {
21+
await assertErrorsInCode(r'''
22+
Never doNotReturn() => throw 0;
23+
24+
test() => doNotReturn() as int;
25+
''', [
26+
error(WarningCode.DEAD_CODE, 60, 4),
27+
]);
28+
}
29+
2030
test_deadBlock_conditionalElse_recordPropertyAccess() async {
2131
await assertErrorsInCode(r'''
2232
void f(({int x, int y}) p) {
@@ -157,6 +167,17 @@ void f(int a) {
157167
]);
158168
}
159169

170+
test_isExpression_type() async {
171+
await assertErrorsInCode(r'''
172+
Never doNotReturn() => throw 0;
173+
174+
// ignore: unnecessary_type_check_true
175+
test() => doNotReturn() is int;
176+
''', [
177+
error(WarningCode.DEAD_CODE, 99, 4),
178+
]);
179+
}
180+
160181
test_localFunction_wildcard() async {
161182
await assertErrorsInCode(r'''
162183
void f() {
@@ -194,6 +215,26 @@ void f(Object x) {
194215
error(WarningCode.DEAD_CODE, 84, 2),
195216
]);
196217
}
218+
219+
test_prefixedIdentifier_identifier() async {
220+
await assertErrorsInCode(r'''
221+
Never get doNotReturn => throw 0;
222+
223+
test() => doNotReturn.hashCode;
224+
''', [
225+
error(WarningCode.DEAD_CODE, 57, 9),
226+
]);
227+
}
228+
229+
test_propertyAccess_property() async {
230+
await assertErrorsInCode(r'''
231+
Never doNotReturn() => throw 0;
232+
233+
test() => doNotReturn().hashCode;
234+
''', [
235+
error(WarningCode.DEAD_CODE, 57, 9),
236+
]);
237+
}
197238
}
198239

199240
@reflectiveTest

pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -889,6 +889,7 @@ PrefixExpression
889889
test_propertyAccess_never_read() async {
890890
await assertNoErrorsInCode(r'''
891891
void f(Never x) {
892+
// ignore: dead_code
892893
x.foo;
893894
}
894895
''');
@@ -916,6 +917,7 @@ PrefixedIdentifier
916917
test_propertyAccess_never_read_hashCode() async {
917918
await assertNoErrorsInCode(r'''
918919
void f(Never x) {
920+
// ignore: dead_code
919921
x.hashCode;
920922
}
921923
''');
@@ -987,6 +989,7 @@ AssignmentExpression
987989
test_propertyAccess_never_tearOff_toString() async {
988990
await assertNoErrorsInCode(r'''
989991
void f(Never x) {
992+
// ignore: dead_code
990993
x.toString;
991994
}
992995
''');
@@ -1142,6 +1145,7 @@ PrefixedIdentifier
11421145
test_propertyAccess_toString() async {
11431146
await assertNoErrorsInCode(r'''
11441147
void f() {
1148+
// ignore: dead_code
11451149
(throw '').toString;
11461150
}
11471151
''');
@@ -1171,6 +1175,7 @@ PropertyAccess
11711175
test_throw_getter_hashCode() async {
11721176
await assertNoErrorsInCode(r'''
11731177
void f() {
1178+
// ignore: dead_code
11741179
(throw '').hashCode;
11751180
}
11761181
''');

0 commit comments

Comments
 (0)