Skip to content

Commit 15c0239

Browse files
stereotype441Commit Queue
authored and
Commit Queue
committed
Fix context type for == and != patterns.
According to the patterns spec (https://github.com/dart-lang/language/blob/main/accepted/3.0/patterns/feature-specification.md), if `A` is the type of the formal parameter of the operator declaration, then operand should be type checked with context type `A?` when op is `==` or `!=`, and with context type `A` otherwise. Prior to this commit, context type `A` was always used. There should be no observable behavior difference, because the operand of a relational operator is required to be a constant expression, and there is no constant expression that behaves differently when its context is `A?` vs `A`. However, we are contemplating some possible future language changes that *would* make the difference observable (e.g., dart-lang/language#3471), so it seems prudent to fix the behavior to match the spec. Change-Id: Ib3a1c82de45c65a851cbd613899ba1f72c215fbe Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/346420 Commit-Queue: Paul Berry <[email protected]> Reviewed-by: Konstantin Shcheglov <[email protected]>
1 parent 5ad284b commit 15c0239

File tree

2 files changed

+16
-23
lines changed

2 files changed

+16
-23
lines changed

pkg/_fe_analyzer_shared/lib/src/type_inference/type_analyzer.dart

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1608,33 +1608,26 @@ mixin TypeAnalyzer<
16081608
RelationalOperatorResolution<Type>? operator =
16091609
resolveRelationalPatternOperator(node, matchedValueType);
16101610
Type operandContext = operator?.parameterType ?? operations.unknownType;
1611+
bool isEquality = switch (operator?.kind) {
1612+
RelationalOperatorKind.equals => true,
1613+
RelationalOperatorKind.notEquals => true,
1614+
_ => false
1615+
};
1616+
if (isEquality) {
1617+
operandContext = operations.makeNullable(operandContext);
1618+
}
16111619
Type operandType = analyzeExpression(operand, operandContext);
1612-
bool isEquality;
1613-
switch (operator?.kind) {
1614-
case RelationalOperatorKind.equals:
1615-
isEquality = true;
1616-
flow.equalityRelationalPattern_end(operand, operandType,
1617-
notEqual: false);
1618-
break;
1619-
case RelationalOperatorKind.notEquals:
1620-
isEquality = true;
1621-
flow.equalityRelationalPattern_end(operand, operandType,
1622-
notEqual: true);
1623-
break;
1624-
default:
1625-
isEquality = false;
1626-
flow.nonEqualityRelationalPattern_end();
1627-
break;
1620+
if (isEquality) {
1621+
flow.equalityRelationalPattern_end(operand, operandType,
1622+
notEqual: operator?.kind == RelationalOperatorKind.notEquals);
1623+
} else {
1624+
flow.nonEqualityRelationalPattern_end();
16281625
}
16291626
// Stack: (Expression)
16301627
Error? argumentTypeNotAssignableError;
16311628
Error? operatorReturnTypeNotAssignableToBoolError;
16321629
if (operator != null) {
1633-
Type parameterType = operator.parameterType;
1634-
if (isEquality) {
1635-
parameterType = operations.makeNullable(parameterType);
1636-
}
1637-
if (!operations.isAssignableTo(operandType, parameterType)) {
1630+
if (!operations.isAssignableTo(operandType, operandContext)) {
16381631
argumentTypeNotAssignableError =
16391632
errors.relationalPatternOperandTypeNotAssignable(
16401633
pattern: node,

pkg/_fe_analyzer_shared/test/type_inference/type_inference_test.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3571,7 +3571,7 @@ main() {
35713571
h.run([
35723572
ifCase(
35733573
expr('Object').checkContext('?'),
3574-
relationalPattern('==', expr('int?').checkContext('Object')),
3574+
relationalPattern('==', expr('int?').checkContext('Object?')),
35753575
[],
35763576
).checkIR('ifCase(expr(Object), ==(expr(int?), '
35773577
'matchedType: Object), variables(), true, block(), noop)')
@@ -3581,7 +3581,7 @@ main() {
35813581
h.run([
35823582
ifCase(
35833583
expr('Object').checkContext('?'),
3584-
relationalPattern('!=', expr('int?').checkContext('Object')),
3584+
relationalPattern('!=', expr('int?').checkContext('Object?')),
35853585
[],
35863586
).checkIR('ifCase(expr(Object), !=(expr(int?), '
35873587
'matchedType: Object), variables(), true, block(), noop)')

0 commit comments

Comments
 (0)