Skip to content

Commit bafd4e8

Browse files
scheglovcommit-bot@chromium.org
authored andcommitted
Issue 39668. Use 'read type' to check dead '??='.
Bug: #39668 Change-Id: I20bd3ae7806b409d6c4b9b72b4968651db207ea4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/127681 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
1 parent 8894b88 commit bafd4e8

File tree

2 files changed

+112
-97
lines changed

2 files changed

+112
-97
lines changed

pkg/analyzer/lib/src/error/dead_code_verifier.dart

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import 'package:analyzer/src/error/codes.dart';
1717
import 'package:analyzer/src/generated/constant.dart';
1818
import 'package:analyzer/src/generated/resolver.dart';
1919
import 'package:analyzer/src/generated/type_system.dart';
20+
import 'package:analyzer/src/task/strong/checker.dart';
2021

2122
/// A visitor that finds dead code and unused labels.
2223
class DeadCodeVerifier extends RecursiveAstVisitor<void> {
@@ -51,7 +52,7 @@ class DeadCodeVerifier extends RecursiveAstVisitor<void> {
5152
TokenType operatorType = node.operator.type;
5253
if (operatorType == TokenType.QUESTION_QUESTION_EQ) {
5354
_checkForDeadNullCoalesce(
54-
node.leftHandSide.staticType, node.rightHandSide);
55+
getReadType(node.leftHandSide), node.rightHandSide);
5556
}
5657
super.visitAssignmentExpression(node);
5758
}
@@ -104,8 +105,9 @@ class DeadCodeVerifier extends RecursiveAstVisitor<void> {
104105
// return null;
105106
// }
106107
// }
107-
} else if (isQuestionQuestion && _isNonNullableUnit) {
108-
_checkForDeadNullCoalesce(node.leftOperand.staticType, node.rightOperand);
108+
} else if (isQuestionQuestion) {
109+
_checkForDeadNullCoalesce(
110+
getReadType(node.leftOperand), node.rightOperand);
109111
}
110112
super.visitBinaryExpression(node);
111113
}

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

Lines changed: 107 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,116 @@ import '../dart/resolution/driver_resolution.dart';
1313
main() {
1414
defineReflectiveSuite(() {
1515
defineReflectiveTests(DeadCodeTest);
16-
defineReflectiveTests(UncheckedUseOfNullableValueTest);
16+
defineReflectiveTests(DeadCodeNullCoalesceTest);
1717
});
1818
}
1919

20+
@reflectiveTest
21+
class DeadCodeNullCoalesceTest extends DriverResolutionTest {
22+
@override
23+
AnalysisOptionsImpl get analysisOptions =>
24+
AnalysisOptionsImpl()..enabledExperiments = [EnableString.non_nullable];
25+
26+
test_assignCompound_dynamic() async {
27+
await assertNoErrorsInCode(r'''
28+
@pragma('analyzer:non-nullable')
29+
library foo;
30+
31+
m() {
32+
dynamic x;
33+
x ??= 1;
34+
}
35+
''');
36+
}
37+
38+
test_assignCompound_map() async {
39+
await assertNoErrorsInCode(r'''
40+
class MyMap<K, V> {
41+
V? operator[](K key) => null;
42+
void operator[]=(K key, V value) {}
43+
}
44+
45+
f(MyMap<int, int> map) {
46+
map[0] ??= 0;
47+
}
48+
''');
49+
}
50+
51+
test_assignCompound_nonNullable() async {
52+
await assertErrorsInCode(r'''
53+
@pragma('analyzer:non-nullable')
54+
library foo;
55+
56+
m(int x) {
57+
x ??= 1;
58+
}
59+
''', [
60+
error(HintCode.DEAD_CODE, 66, 1),
61+
]);
62+
}
63+
64+
test_assignCompound_nullable() async {
65+
await assertNoErrorsInCode(r'''
66+
@pragma('analyzer:non-nullable')
67+
library foo;
68+
69+
m() {
70+
int? x;
71+
x ??= 1;
72+
}
73+
''');
74+
}
75+
76+
test_binary_dynamic() async {
77+
await assertNoErrorsInCode(r'''
78+
@pragma('analyzer:non-nullable')
79+
library foo;
80+
81+
m() {
82+
dynamic x;
83+
x ?? 1;
84+
}
85+
''');
86+
}
87+
88+
test_binary_nonNullable() async {
89+
await assertErrorsInCode(r'''
90+
@pragma('analyzer:non-nullable')
91+
library foo;
92+
93+
m(int x) {
94+
x ?? 1;
95+
}
96+
''', [
97+
error(HintCode.DEAD_CODE, 65, 1),
98+
]);
99+
}
100+
101+
test_binary_nullable() async {
102+
await assertNoErrorsInCode(r'''
103+
@pragma('analyzer:non-nullable')
104+
library foo;
105+
106+
m() {
107+
int? x;
108+
x ?? 1;
109+
}
110+
''');
111+
}
112+
113+
test_binary_nullType() async {
114+
await assertNoErrorsInCode(r'''
115+
@pragma('analyzer:non-nullable')
116+
library foo;
117+
118+
m() {
119+
Null x;
120+
x ?? 1;
121+
}
122+
''');
123+
}
124+
}
125+
20126
@reflectiveTest
21127
class DeadCodeTest extends DriverResolutionTest with PackageMixin {
22128
test_afterForEachWithBreakLabel() async {
@@ -700,96 +806,3 @@ f() {
700806
]);
701807
}
702808
}
703-
704-
@reflectiveTest
705-
class UncheckedUseOfNullableValueTest extends DriverResolutionTest {
706-
@override
707-
AnalysisOptionsImpl get analysisOptions =>
708-
AnalysisOptionsImpl()..enabledExperiments = [EnableString.non_nullable];
709-
710-
test_nullCoalesce_dynamic() async {
711-
await assertNoErrorsInCode(r'''
712-
@pragma('analyzer:non-nullable')
713-
library foo;
714-
715-
m() {
716-
dynamic x;
717-
x ?? 1;
718-
}
719-
''');
720-
}
721-
722-
test_nullCoalesce_nonNullable() async {
723-
await assertErrorsInCode(r'''
724-
@pragma('analyzer:non-nullable')
725-
library foo;
726-
727-
m(int x) {
728-
x ?? 1;
729-
}
730-
''', [
731-
error(HintCode.DEAD_CODE, 65, 1),
732-
]);
733-
}
734-
735-
test_nullCoalesce_nullable() async {
736-
await assertNoErrorsInCode(r'''
737-
@pragma('analyzer:non-nullable')
738-
library foo;
739-
740-
m() {
741-
int? x;
742-
x ?? 1;
743-
}
744-
''');
745-
}
746-
747-
test_nullCoalesce_nullType() async {
748-
await assertNoErrorsInCode(r'''
749-
@pragma('analyzer:non-nullable')
750-
library foo;
751-
752-
m() {
753-
Null x;
754-
x ?? 1;
755-
}
756-
''');
757-
}
758-
759-
test_nullCoalesceAssign_dynamic() async {
760-
await assertNoErrorsInCode(r'''
761-
@pragma('analyzer:non-nullable')
762-
library foo;
763-
764-
m() {
765-
dynamic x;
766-
x ??= 1;
767-
}
768-
''');
769-
}
770-
771-
test_nullCoalesceAssign_nonNullable() async {
772-
await assertErrorsInCode(r'''
773-
@pragma('analyzer:non-nullable')
774-
library foo;
775-
776-
m(int x) {
777-
x ??= 1;
778-
}
779-
''', [
780-
error(HintCode.DEAD_CODE, 66, 1),
781-
]);
782-
}
783-
784-
test_nullCoalesceAssign_nullable() async {
785-
await assertNoErrorsInCode(r'''
786-
@pragma('analyzer:non-nullable')
787-
library foo;
788-
789-
m() {
790-
int? x;
791-
x ??= 1;
792-
}
793-
''');
794-
}
795-
}

0 commit comments

Comments
 (0)