Test logical-and in variable declaration, report REFUTABLE_PATTERN_IN_IRREFUTABLE_CONTEXT.

Change-Id: I7fcffea3b591fbe3a181a8bb8a8a461d18ec3d64
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/273340
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Konstantin Shcheglov 2022-12-02 17:53:19 +00:00 committed by Commit Queue
parent cdf5aa216e
commit 46bffdabb1
9 changed files with 205 additions and 11 deletions

View file

@ -946,6 +946,8 @@ CompileTimeErrorCode.REDIRECT_TO_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER:
status: needsEvaluation
CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION:
status: needsEvaluation
CompileTimeErrorCode.REFUTABLE_PATTERN_IN_IRREFUTABLE_CONTEXT:
status: needsEvaluation
CompileTimeErrorCode.RELATIONAL_PATTERN_OPERATOR_RETURN_TYPE_NOT_ASSIGNABLE_TO_BOOL:
status: noFix
CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH:

View file

@ -1120,8 +1120,14 @@ class BinaryPatternImpl extends DartPatternImpl implements BinaryPattern {
E? accept<E>(AstVisitor<E> visitor) => visitor.visitBinaryPattern(this);
@override
DartType computePatternSchema(ResolverVisitor resolverVisitor) =>
throw UnimplementedError('TODO(paulberry)');
DartType computePatternSchema(ResolverVisitor resolverVisitor) {
return resolverVisitor.analyzeLogicalPatternSchema(
leftOperand,
rightOperand,
isAnd: operator.type == TokenType.AMPERSAND ||
operator.type == TokenType.AMPERSAND_AMPERSAND,
);
}
@override
void resolvePattern(
@ -2810,8 +2816,9 @@ class ConstantPatternImpl extends DartPatternImpl implements ConstantPattern {
E? accept<E>(AstVisitor<E> visitor) => visitor.visitConstantPattern(this);
@override
DartType computePatternSchema(ResolverVisitor resolverVisitor) =>
throw UnimplementedError('TODO(paulberry)');
DartType computePatternSchema(ResolverVisitor resolverVisitor) {
return resolverVisitor.analyzeConstantPatternSchema();
}
@override
void resolvePattern(
@ -2819,7 +2826,8 @@ class ConstantPatternImpl extends DartPatternImpl implements ConstantPattern {
DartType matchedType,
SharedMatchContext context,
) {
resolverVisitor.analyzeExpression(expression, matchedType);
resolverVisitor.analyzeConstantPattern(
matchedType, context, this, expression);
expression = resolverVisitor.popRewrite()!;
}
@ -10985,8 +10993,9 @@ class RelationalPatternImpl extends DartPatternImpl
E? accept<E>(AstVisitor<E> visitor) => visitor.visitRelationalPattern(this);
@override
DartType computePatternSchema(ResolverVisitor resolverVisitor) =>
throw UnimplementedError('TODO(paulberry)');
DartType computePatternSchema(ResolverVisitor resolverVisitor) {
return resolverVisitor.analyzeRelationalPatternSchema();
}
@override
void resolvePattern(

View file

@ -40,9 +40,7 @@ class SharedTypeAnalyzerErrors
}
@override
void assertInErrorRecovery() {
throw UnimplementedError('TODO(paulberry)');
}
void assertInErrorRecovery() {}
@override
void caseExpressionTypeMismatch(
@ -129,7 +127,10 @@ class SharedTypeAnalyzerErrors
@override
void refutablePatternInIrrefutableContext(AstNode pattern, AstNode context) {
throw UnimplementedError('TODO(paulberry)');
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.REFUTABLE_PATTERN_IN_IRREFUTABLE_CONTEXT,
pattern,
);
}
@override

View file

@ -4004,6 +4004,15 @@ class CompileTimeErrorCode extends AnalyzerErrorCode {
hasPublishedDocs: true,
);
static const CompileTimeErrorCode REFUTABLE_PATTERN_IN_IRREFUTABLE_CONTEXT =
CompileTimeErrorCode(
'REFUTABLE_PATTERN_IN_IRREFUTABLE_CONTEXT',
"Refutable patterns can't be used in an irrefutable context.",
correctionMessage:
"Try using an if-case, a 'switch' statement, or a 'switch' expression "
"instead.",
);
static const CompileTimeErrorCode
RELATIONAL_PATTERN_OPERATOR_RETURN_TYPE_NOT_ASSIGNABLE_TO_BOOL =
CompileTimeErrorCode(

View file

@ -401,6 +401,7 @@ const List<ErrorCode> errorCodeValues = [
CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONSTRUCTOR,
CompileTimeErrorCode.REDIRECT_TO_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION,
CompileTimeErrorCode.REFUTABLE_PATTERN_IN_IRREFUTABLE_CONTEXT,
CompileTimeErrorCode
.RELATIONAL_PATTERN_OPERATOR_RETURN_TYPE_NOT_ASSIGNABLE_TO_BOOL,
CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH,

View file

@ -12269,6 +12269,9 @@ CompileTimeErrorCode:
print(x);
}
```
REFUTABLE_PATTERN_IN_IRREFUTABLE_CONTEXT:
problemMessage: Refutable patterns can't be used in an irrefutable context.
correctionMessage: Try using an if-case, a 'switch' statement, or a 'switch' expression instead.
RELATIONAL_PATTERN_OPERATOR_RETURN_TYPE_NOT_ASSIGNABLE_TO_BOOL:
problemMessage: The return type of operators used in relational patterns must be assignable to 'bool'.
correctionMessage: Try updating the operator declaration to return 'bool'.

View file

@ -75,6 +75,38 @@ BinaryPattern
''');
}
test_logicalAnd_variableDeclaration() async {
await assertNoErrorsInCode(r'''
void f() {
var (a && b) = 0;
}
''');
final node = findNode.singlePatternVariableDeclarationStatement;
assertResolvedNodeText(node, r'''
PatternVariableDeclarationStatement
declaration: PatternVariableDeclaration
keyword: var
pattern: ParenthesizedPattern
leftParenthesis: (
pattern: BinaryPattern
leftOperand: VariablePattern
name: a
declaredElement: hasImplicitType a@18
type: int
operator: &&
rightOperand: VariablePattern
name: b
declaredElement: hasImplicitType b@23
type: int
rightParenthesis: )
equals: =
expression: IntegerLiteral
literal: 0
staticType: int
semicolon: ;
''');
}
test_logicalOr_ifCase() async {
await assertNoErrorsInCode(r'''
void f(x) {

View file

@ -0,0 +1,134 @@
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/src/error/codes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../dart/resolution/context_collection_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(RefutablePatternInIrrefutableContextTest);
});
}
@reflectiveTest
class RefutablePatternInIrrefutableContextTest
extends PubPackageResolutionTest {
test_declaration_constantPattern() async {
await assertErrorsInCode(r'''
void f() {
var (0) = 0;
}
''', [
error(
CompileTimeErrorCode.REFUTABLE_PATTERN_IN_IRREFUTABLE_CONTEXT, 18, 1),
]);
var node = findNode.singlePatternVariableDeclaration;
assertResolvedNodeText(node, r'''
PatternVariableDeclaration
keyword: var
pattern: ParenthesizedPattern
leftParenthesis: (
pattern: ConstantPattern
expression: IntegerLiteral
literal: 0
staticType: int
rightParenthesis: )
equals: =
expression: IntegerLiteral
literal: 0
staticType: int
''');
}
test_declaration_logicalOrPattern() async {
await assertErrorsInCode(r'''
void f() {
var (_ || _) = 0;
}
''', [
error(
CompileTimeErrorCode.REFUTABLE_PATTERN_IN_IRREFUTABLE_CONTEXT, 18, 6),
]);
var node = findNode.singlePatternVariableDeclaration;
assertResolvedNodeText(node, r'''
PatternVariableDeclaration
keyword: var
pattern: ParenthesizedPattern
leftParenthesis: (
pattern: BinaryPattern
leftOperand: VariablePattern
name: _
operator: ||
rightOperand: VariablePattern
name: _
rightParenthesis: )
equals: =
expression: IntegerLiteral
literal: 0
staticType: int
''');
}
test_declaration_nullCheckPattern() async {
await assertErrorsInCode(r'''
void f() {
var (_?) = 0;
}
''', [
error(
CompileTimeErrorCode.REFUTABLE_PATTERN_IN_IRREFUTABLE_CONTEXT, 18, 2),
]);
var node = findNode.singlePatternVariableDeclaration;
assertResolvedNodeText(node, r'''
PatternVariableDeclaration
keyword: var
pattern: ParenthesizedPattern
leftParenthesis: (
pattern: PostfixPattern
operand: VariablePattern
name: _
operator: ?
rightParenthesis: )
equals: =
expression: IntegerLiteral
literal: 0
staticType: int
''');
}
test_declaration_relationalPattern() async {
await assertErrorsInCode(r'''
void f() {
var (> 0) = 0;
}
''', [
error(
CompileTimeErrorCode.REFUTABLE_PATTERN_IN_IRREFUTABLE_CONTEXT, 18, 3),
]);
var node = findNode.singlePatternVariableDeclaration;
assertResolvedNodeText(node, r'''
PatternVariableDeclaration
keyword: var
pattern: ParenthesizedPattern
leftParenthesis: (
pattern: RelationalPattern
operator: >
operand: IntegerLiteral
literal: 0
staticType: int
element: dart:core::@class::num::@method::>
rightParenthesis: )
equals: =
expression: IntegerLiteral
literal: 0
staticType: int
''');
}
}

View file

@ -652,6 +652,8 @@ import 'redirect_to_type_alias_expands_to_type_parameter_test.dart'
as redirect_to_type_alias_expands_to_type_parameter;
import 'referenced_before_declaration_test.dart'
as referenced_before_declaration;
import 'refutable_pattern_in_irrefutable_context_test.dart'
as refutable_pattern_in_irrefutable_context;
import 'relational_pattern_operator_return_type_not_assignable_to_bool_test.dart'
as relational_pattern_operator_return_type_not_assignable_to_bool;
import 'rethrow_outside_catch_test.dart' as rethrow_outside_catch;
@ -1241,6 +1243,7 @@ main() {
redirect_to_non_const_constructor.main();
redirect_to_type_alias_expands_to_type_parameter.main();
referenced_before_declaration.main();
refutable_pattern_in_irrefutable_context.main();
relational_pattern_operator_return_type_not_assignable_to_bool.main();
rethrow_outside_catch.main();
return_in_generative_constructor.main();