Skip to content

Commit e423e85

Browse files
scheglovcommit-bot@chromium.org
authored andcommitted
Make null check to participate in null shorting.
Bug: dart-lang/language#1163 Change-Id: I6e648f76413c5036a867b2125359f28eb03027c2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163727 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Konstantin Shcheglov <[email protected]>
1 parent 7c5df91 commit e423e85

File tree

3 files changed

+63
-2
lines changed

3 files changed

+63
-2
lines changed

pkg/analyzer/lib/src/dart/ast/ast.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8092,8 +8092,7 @@ class PostfixExpressionImpl extends ExpressionImpl
80928092
}
80938093

80948094
@override
8095-
bool _extendsNullShorting(Expression child) =>
8096-
operator.type != TokenType.BANG && identical(child, operand);
8095+
bool _extendsNullShorting(Expression child) => identical(child, operand);
80978096
}
80988097

80998098
/// An identifier that is prefixed or an access to an object property where the

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ class PostfixExpressionResolver {
232232
var type = _typeSystem.promoteToNonNull(operandType);
233233
_inferenceHelper.recordStaticType(node, type);
234234

235+
_resolver.nullShortingTermination(node);
235236
_flowAnalysis?.flow?.nonNullAssert_end(operand);
236237
}
237238
}

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

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,67 @@ int g() => f(null)!;
641641
);
642642
}
643643

644+
/// See https://github.com/dart-lang/language/issues/1163
645+
test_nullCheck_participatesNullShorting() async {
646+
await assertErrorsInCode('''
647+
class A {
648+
int zero;
649+
int? zeroOrNull;
650+
651+
A(this.zero, [this.zeroOrNull]);
652+
}
653+
654+
void test1(A? a) => a?.zero!;
655+
void test2(A? a) => a?.zeroOrNull!;
656+
void test3(A? a) => a?.zero!.isEven;
657+
void test4(A? a) => a?.zeroOrNull!.isEven;
658+
659+
class Foo {
660+
Bar? bar;
661+
662+
Foo(this.bar);
663+
664+
Bar? operator [](int? index) => null;
665+
}
666+
667+
class Bar {
668+
int baz;
669+
670+
Bar(this.baz);
671+
672+
int operator [](int index) => index;
673+
}
674+
675+
void test5(Foo? foo) => foo?.bar!;
676+
void test6(Foo? foo) => foo?.bar!.baz;
677+
void test7(Foo? foo, int a) => foo?.bar![a];
678+
void test8(Foo? foo, int? a) => foo?[a]!;
679+
void test9(Foo? foo, int? a) => foo?[a]!.baz;
680+
void test10(Foo? foo, int? a, int b) => foo?[a]![b];
681+
''', [
682+
error(StaticWarningCode.UNNECESSARY_NON_NULL_ASSERTION, 107, 1),
683+
error(StaticWarningCode.UNNECESSARY_NON_NULL_ASSERTION, 173, 1),
684+
]);
685+
686+
void assertTestType(int index, String expected) {
687+
var function = findNode.functionDeclaration('test$index(');
688+
var body = function.functionExpression.body as ExpressionFunctionBody;
689+
assertType(body.expression, expected);
690+
}
691+
692+
assertTestType(1, 'int?');
693+
assertTestType(2, 'int?');
694+
assertTestType(3, 'bool?');
695+
assertTestType(4, 'bool?');
696+
697+
assertTestType(5, 'Bar?');
698+
assertTestType(6, 'int?');
699+
assertTestType(7, 'int?');
700+
assertTestType(8, 'Bar?');
701+
assertTestType(9, 'int?');
702+
assertTestType(10, 'int?');
703+
}
704+
644705
test_nullCheck_superExpression() async {
645706
await assertErrorsInCode(r'''
646707
class A {

0 commit comments

Comments
 (0)