[_fe_analyzer_shared] Include errors in analysis result
This propagates information about reported error to the caller of
a shared type analysis. This is used to properly turn errors into
invalid expressions/patterns, as is normally done in the CFE in
face of errors.
Change-Id: Ibb8adedccb8314fabfe18ecaa3559e32ad7267ca
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/286145
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/_fe_analyzer_shared/lib/src/type_inference/type_analysis_result.dart b/pkg/_fe_analyzer_shared/lib/src/type_inference/type_analysis_result.dart
index 3560bd9..3e4f236 100644
--- a/pkg/_fe_analyzer_shared/lib/src/type_inference/type_analysis_result.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/type_inference/type_analysis_result.dart
@@ -160,8 +160,28 @@
Type resolveShorting() => type;
}
+/// Result for analyzing a switch expression in
+/// [TypeAnalyzer.analyzeSwitchExpression].
+class SwitchExpressionResult<Type extends Object, Error>
+ extends SimpleTypeAnalysisResult<Type> {
+ /// Errors for non-bool guards.
+ ///
+ /// The key is the case index of the erroneous guard.
+ ///
+ /// This is `null` if no such errors where found.
+ final Map<int, Error>? nonBooleanGuardErrors;
+
+ /// Error for when the switch statement was non exhaustive.
+ final Error? nonExhaustiveSwitchError;
+
+ SwitchExpressionResult(
+ {required super.type,
+ required this.nonBooleanGuardErrors,
+ required this.nonExhaustiveSwitchError});
+}
+
/// Container for the result of running type analysis on an integer literal.
-class SwitchStatementTypeAnalysisResult<Type> {
+class SwitchStatementTypeAnalysisResult<Type extends Object, Error> {
/// Whether the switch statement had a `default` clause.
final bool hasDefault;
@@ -182,12 +202,30 @@
/// The static type of the scrutinee expression.
final Type scrutineeType;
+ /// Errors for the cases that don't complete normally.
+ ///
+ /// This is `null` if no such errors where found.
+ final Map<int, Error>? switchCaseCompletesNormallyErrors;
+
+ /// Errors for non-bool guards.
+ ///
+ /// The keys of the maps are case and head indices of the erroneous guard.
+ ///
+ /// This is `null` if no such errors where found.
+ final Map<int, Map<int, Error>>? nonBooleanGuardErrors;
+
+ /// Error for when the switch statement was non exhaustive.
+ final Error? nonExhaustiveSwitchError;
+
SwitchStatementTypeAnalysisResult({
required this.hasDefault,
required this.isExhaustive,
required this.lastCaseTerminates,
required this.requiresExhaustivenessValidation,
required this.scrutineeType,
+ required this.switchCaseCompletesNormallyErrors,
+ required this.nonBooleanGuardErrors,
+ required this.nonExhaustiveSwitchError,
});
}
@@ -202,3 +240,226 @@
/// and can be removed.
logicalAndPatternOperand,
}
+
+/// Result for analyzing an assigned variable pattern in
+/// [TypeAnalyzer.analyzeAssignedVariablePattern].
+class AssignedVariablePatternResult<Error> {
+ /// Error for when a variable was assigned multiple times within a pattern.
+ final Error? duplicateAssignmentPatternVariableError;
+
+ /// Error for when the matched value type is not assignable to the variable
+ /// type in an irrefutable context.
+ final Error? patternTypeMismatchInIrrefutableContextError;
+
+ AssignedVariablePatternResult(
+ {required this.duplicateAssignmentPatternVariableError,
+ required this.patternTypeMismatchInIrrefutableContextError});
+}
+
+/// Result for analyzing an object pattern in
+/// [TypeAnalyzer.analyzeObjectPattern].
+class ObjectPatternResult<Type extends Object, Error> {
+ /// The required type of the object pattern.
+ final Type requiredType;
+
+ /// Errors for when the same property name was used multiple times in the
+ /// object pattern.
+ ///
+ /// The key is the index of the duplicate field within the object pattern.
+ ///
+ /// This is `null` if no such properties were found.
+ final Map<int, Error>? duplicateRecordPatternFieldErrors;
+
+ /// Error for when the matched value type is not assignable to the required
+ /// type in an irrefutable context.
+ final Error? patternTypeMismatchInIrrefutableContextError;
+
+ ObjectPatternResult(
+ {required this.requiredType,
+ required this.duplicateRecordPatternFieldErrors,
+ required this.patternTypeMismatchInIrrefutableContextError});
+}
+
+/// Result for analyzing a record pattern in
+/// [TypeAnalyzer.analyzeRecordPattern].
+class RecordPatternResult<Type extends Object, Error> {
+ /// The required type of the record pattern.
+ final Type requiredType;
+
+ /// Errors for when the same property name was used multiple times in the
+ /// record pattern.
+ ///
+ /// The key is the index of the duplicate field within the record pattern.
+ ///
+ /// This is `null` if no such errors where found.
+ final Map<int, Error>? duplicateRecordPatternFieldErrors;
+
+ /// Error for when the matched value type is not assignable to the required
+ /// type in an irrefutable context.
+ final Error? patternTypeMismatchInIrrefutableContextError;
+
+ RecordPatternResult(
+ {required this.requiredType,
+ required this.duplicateRecordPatternFieldErrors,
+ required this.patternTypeMismatchInIrrefutableContextError});
+}
+
+/// Result for analyzing a list pattern in [TypeAnalyzer.analyzeListPattern].
+class ListPatternResult<Type extends Object, Error> {
+ /// The required type of the list pattern.
+ final Type requiredType;
+
+ /// Errors for when multiple rest patterns occurred within the list pattern.
+ ///
+ /// The key is the index of the pattern within the list pattern.
+ ///
+ /// This is `null` if no such errors where found.
+ final Map<int, Error>? duplicateRestPatternErrors;
+
+ /// Error for when the matched value type is not assignable to the required
+ /// type in an irrefutable context.
+ final Error? patternTypeMismatchInIrrefutableContextError;
+
+ ListPatternResult(
+ {required this.requiredType,
+ required this.duplicateRestPatternErrors,
+ required this.patternTypeMismatchInIrrefutableContextError});
+}
+
+/// Result for analyzing a map pattern in [TypeAnalyzer.analyzeMapPattern].
+class MapPatternResult<Type extends Object, Error> {
+ /// The required type of the map pattern.
+ final Type requiredType;
+
+ /// Errors for when multiple rest patterns occurred within the map pattern.
+ ///
+ /// The key is the index of the pattern within the map pattern.
+ ///
+ /// This is `null` if no such errors where found.
+ final Map<int, Error>? duplicateRestPatternErrors;
+
+ /// Error for when the matched value type is not assignable to the required
+ /// type in an irrefutable context.
+ final Error? patternTypeMismatchInIrrefutableContextError;
+
+ MapPatternResult(
+ {required this.requiredType,
+ required this.duplicateRestPatternErrors,
+ required this.patternTypeMismatchInIrrefutableContextError});
+}
+
+/// Result for analyzing a constant pattern in
+/// [TypeAnalyzer.analyzeConstantPattern].
+class ConstantPatternResult<Type extends Object, Error> {
+ /// The static type of the constant expression.
+ final Type expressionType;
+
+ /// Error for when the pattern occurred in an irrefutable context.
+ final Error? refutablePatternInIrrefutableContextError;
+
+ /// Error for when the pattern, used as a case constant expression, does not
+ /// have a valid type wrt. the switch expression type.
+ final Error? caseExpressionTypeMismatchError;
+
+ ConstantPatternResult(
+ {required this.expressionType,
+ required this.refutablePatternInIrrefutableContextError,
+ required this.caseExpressionTypeMismatchError});
+}
+
+/// Result for analyzing a declared variable pattern in
+/// [TypeAnalyzer.analyzeDeclaredVariablePattern].
+class DeclaredVariablePatternResult<Type extends Object, Error> {
+ /// The static type of the variable.
+ final Type staticType;
+
+ /// Error for when the matched value type is not assignable to the static
+ /// type in an irrefutable context.
+ final Error? patternTypeMismatchInIrrefutableContextError;
+
+ DeclaredVariablePatternResult(
+ {required this.staticType,
+ required this.patternTypeMismatchInIrrefutableContextError});
+}
+
+/// Result for analyzing a logical or pattern in
+/// [TypeAnalyzer.analyzeLogicalOrPattern].
+class LogicalOrPatternResult<Error> {
+ /// Error for when the pattern occurred in an irrefutable context.
+ final Error? refutablePatternInIrrefutableContextError;
+
+ LogicalOrPatternResult(
+ {required this.refutablePatternInIrrefutableContextError});
+}
+
+/// Result for analyzing a relational pattern in
+/// [TypeAnalyzer.analyzeRelationalPattern].
+class RelationalPatternResult<Type extends Object, Error> {
+ /// The static type of the operand.
+ final Type operandType;
+
+ /// Error for when the pattern occurred in an irrefutable context.
+ final Error? refutablePatternInIrrefutableContextError;
+
+ /// Error for when the operand type is not assignable to the parameter type
+ /// of the relational operator.
+ final Error? argumentTypeNotAssignableError;
+
+ /// Error for when the relational operator does not return a bool.
+ final Error? operatorReturnTypeNotAssignableToBoolError;
+
+ RelationalPatternResult(
+ {required this.operandType,
+ required this.refutablePatternInIrrefutableContextError,
+ required this.argumentTypeNotAssignableError,
+ required this.operatorReturnTypeNotAssignableToBoolError});
+}
+
+/// Result for analyzing a null check or null assert pattern in
+/// [TypeAnalyzer.analyzeNullCheckOrAssertPattern].
+class NullCheckOrAssertPatternResult<Error> {
+ /// Error for when the pattern occurred in an irrefutable context.
+ final Error? refutablePatternInIrrefutableContextError;
+
+ /// Error for when the matched type is known to be non-null.
+ final Error? matchedTypeIsStrictlyNonNullableError;
+
+ NullCheckOrAssertPatternResult(
+ {required this.refutablePatternInIrrefutableContextError,
+ required this.matchedTypeIsStrictlyNonNullableError});
+}
+
+/// Result for analyzing a wildcard pattern
+/// [TypeAnalyzer.analyzeWildcardPattern].
+class WildcardPatternResult<Error> {
+ /// Error for when the matched value type is not assignable to the wildcard
+ /// type in an irrefutable context.
+ final Error? patternTypeMismatchInIrrefutableContextError;
+
+ WildcardPatternResult(
+ {required this.patternTypeMismatchInIrrefutableContextError});
+}
+
+/// Result for analyzing an if-case statement or element in
+/// [TypeAnalyzer.analyzeIfCaseStatement] and
+/// [TypeAnalyzer.analyzeIfCaseElement].
+class IfCaseStatementResult<Type extends Object, Error> {
+ /// The static type of the matched expression.
+ final Type matchedExpressionType;
+
+ /// Error for when the guard has a non-bool type.
+ final Error? nonBooleanGuardError;
+
+ IfCaseStatementResult(
+ {required this.matchedExpressionType,
+ required this.nonBooleanGuardError});
+}
+
+/// Result for analyzing a pattern-for-in statement or element in
+/// [TypeAnalyzer.analyzePatternForIn].
+class PatternForInResult<Error> {
+ /// Error for when the expression is not an iterable.
+ final Error? patternForInExpressionIsNotIterableError;
+
+ PatternForInResult({required this.patternForInExpressionIsNotIterableError});
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/type_inference/type_analyzer.dart b/pkg/_fe_analyzer_shared/lib/src/type_inference/type_analyzer.dart
index 9e07327..5c2a74f 100644
--- a/pkg/_fe_analyzer_shared/lib/src/type_inference/type_analyzer.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/type_inference/type_analyzer.dart
@@ -280,7 +280,8 @@
Expression extends Node,
Variable extends Object,
Type extends Object,
- Pattern extends Node> {
+ Pattern extends Node,
+ Error> {
/// Returns the type `bool`.
Type get boolType;
@@ -290,8 +291,8 @@
/// Returns the type `dynamic`.
Type get dynamicType;
- TypeAnalyzerErrors<Node, Statement, Expression, Variable, Type, Pattern>?
- get errors;
+ TypeAnalyzerErrors<Node, Statement, Expression, Variable, Type, Pattern,
+ Error> get errors;
/// Returns the type used by the client in the case of errors.
Type get errorType;
@@ -319,23 +320,28 @@
/// context. [node] is the pattern itself, and [variable] is the variable
/// being referenced.
///
+ /// Returns an [AssignedVariablePatternResult] with information about reported
+ /// errors.
+ ///
/// See [dispatchPattern] for the meaning of [context].
///
/// For wildcard patterns in an assignment context,
/// [analyzeDeclaredVariablePattern] should be used instead.
///
/// Stack effect: none.
- void analyzeAssignedVariablePattern(
+ AssignedVariablePatternResult<Error> analyzeAssignedVariablePattern(
MatchContext<Node, Expression, Pattern, Type, Variable> context,
Pattern node,
Variable variable) {
+ Error? duplicateAssignmentPatternVariableError;
Map<Variable, Pattern>? assignedVariables = context.assignedVariables;
if (assignedVariables != null) {
Pattern? original = assignedVariables[variable];
if (original == null) {
assignedVariables[variable] = node;
} else {
- errors?.duplicateAssignmentPatternVariable(
+ duplicateAssignmentPatternVariableError =
+ errors.duplicateAssignmentPatternVariable(
variable: variable,
original: original,
duplicate: node,
@@ -348,17 +354,24 @@
assert(irrefutableContext != null,
'Assigned variables must only appear in irrefutable pattern contexts');
Type matchedType = flow.getMatchedValueType();
+ Error? patternTypeMismatchInIrrefutableContextError;
if (irrefutableContext != null &&
!operations.isAssignableTo(matchedType, variableDeclaredType)) {
- errors?.patternTypeMismatchInIrrefutableContext(
- pattern: node,
- context: irrefutableContext,
- matchedType: matchedType,
- requiredType: variableDeclaredType);
+ patternTypeMismatchInIrrefutableContextError =
+ errors.patternTypeMismatchInIrrefutableContext(
+ pattern: node,
+ context: irrefutableContext,
+ matchedType: matchedType,
+ requiredType: variableDeclaredType);
}
flow.promoteForPattern(
matchedType: matchedType, knownType: variableDeclaredType);
flow.assignedVariablePattern(node, variable, matchedType);
+ return new AssignedVariablePatternResult(
+ duplicateAssignmentPatternVariableError:
+ duplicateAssignmentPatternVariableError,
+ patternTypeMismatchInIrrefutableContextError:
+ patternTypeMismatchInIrrefutableContextError);
}
/// Computes the type schema for a variable pattern appearing in an assignment
@@ -384,7 +397,7 @@
knownType: requiredType,
matchFailsIfWrongType: false);
if (matchedTypeIsSubtypeOfRequired) {
- errors?.matchedTypeIsSubtypeOfRequired(
+ errors.matchedTypeIsSubtypeOfRequired(
pattern: pattern,
matchedType: matchedValueType,
requiredType: requiredType,
@@ -413,27 +426,29 @@
///
/// See [dispatchPattern] for the meaning of [context].
///
- /// Returns the static type of [expression].
+ /// Returns a [ConstantPatternResult] with the static type of [expression]
+ /// and information about reported errors.
///
/// Stack effect: pushes (Expression).
- Type analyzeConstantPattern(
+ ConstantPatternResult<Type, Error> analyzeConstantPattern(
MatchContext<Node, Expression, Pattern, Type, Variable> context,
Node node,
Expression expression) {
// Stack: ()
- TypeAnalyzerErrors<Node, Node, Expression, Variable, Type, Pattern>?
- errors = this.errors;
Node? irrefutableContext = context.irrefutableContext;
+ Error? refutablePatternInIrrefutableContextError;
if (irrefutableContext != null) {
- errors?.refutablePatternInIrrefutableContext(
- pattern: node, context: irrefutableContext);
+ refutablePatternInIrrefutableContextError =
+ errors.refutablePatternInIrrefutableContext(
+ pattern: node, context: irrefutableContext);
}
Type matchedType = flow.getMatchedValueType();
Type expressionType = analyzeExpression(expression, matchedType);
flow.constantPattern_end(expression, expressionType,
patternsEnabled: options.patternsEnabled);
// Stack: (Expression)
- if (errors != null && !options.patternsEnabled) {
+ Error? caseExpressionTypeMismatchError;
+ if (!options.patternsEnabled) {
Expression? switchScrutinee = context.switchScrutinee;
if (switchScrutinee != null) {
bool nullSafetyEnabled = options.nullSafetyEnabled;
@@ -441,7 +456,7 @@
? operations.isSubtypeOf(expressionType, matchedType)
: operations.isAssignableTo(expressionType, matchedType);
if (!matches) {
- errors.caseExpressionTypeMismatch(
+ caseExpressionTypeMismatchError = errors.caseExpressionTypeMismatch(
caseExpression: expression,
scrutinee: switchScrutinee,
caseExpressionType: expressionType,
@@ -450,7 +465,11 @@
}
}
}
- return expressionType;
+ return new ConstantPatternResult(
+ expressionType: expressionType,
+ refutablePatternInIrrefutableContextError:
+ refutablePatternInIrrefutableContextError,
+ caseExpressionTypeMismatchError: caseExpressionTypeMismatchError);
}
/// Computes the type schema for a constant pattern.
@@ -460,7 +479,7 @@
// Constant patterns are only allowed in refutable contexts, and refutable
// contexts don't propagate a type schema into the scrutinee. So this
// code path is only reachable if the user's code contains errors.
- errors?.assertInErrorRecovery();
+ errors.assertInErrorRecovery();
return unknownType;
}
@@ -473,10 +492,11 @@
///
/// See [dispatchPattern] for the meaning of [context].
///
- /// Returns the static type of the variable (possibly inferred).
+ /// Returns a [DeclaredVariablePatternResult] with the static type of the
+ /// variable (possibly inferred) and information about reported errors.
///
/// Stack effect: none.
- Type analyzeDeclaredVariablePattern(
+ DeclaredVariablePatternResult<Type, Error> analyzeDeclaredVariablePattern(
MatchContext<Node, Expression, Pattern, Type, Variable> context,
Pattern node,
Variable variable,
@@ -487,13 +507,15 @@
Type staticType =
declaredType ?? variableTypeFromInitializerType(matchedType);
Node? irrefutableContext = context.irrefutableContext;
+ Error? patternTypeMismatchInIrrefutableContextError;
if (irrefutableContext != null &&
!operations.isAssignableTo(matchedType, staticType)) {
- errors?.patternTypeMismatchInIrrefutableContext(
- pattern: node,
- context: irrefutableContext,
- matchedType: matchedType,
- requiredType: staticType);
+ patternTypeMismatchInIrrefutableContextError =
+ errors.patternTypeMismatchInIrrefutableContext(
+ pattern: node,
+ context: irrefutableContext,
+ matchedType: matchedType,
+ requiredType: staticType);
}
flow.promoteForPattern(matchedType: matchedType, knownType: staticType);
bool isImplicitlyTyped = declaredType == null;
@@ -508,7 +530,10 @@
setVariableType(variable, staticType);
(context.componentVariables[variableName] ??= []).add(variable);
flow.assignMatchedPatternVariable(variable, promotionKey);
- return staticType;
+ return new DeclaredVariablePatternResult(
+ staticType: staticType,
+ patternTypeMismatchInIrrefutableContextError:
+ patternTypeMismatchInIrrefutableContextError);
}
/// Computes the type schema for a variable pattern in a non-assignment
@@ -550,12 +575,15 @@
/// wishes to use to represent that variable. This is used to join together
/// variables that appear in different branches of logical-or patterns.
///
+ /// Returns a [IfCaseStatementResult] with the static type of [expression] and
+ /// information about reported errors.
+ ///
/// Stack effect: pushes (Expression scrutinee, Pattern, Expression guard,
/// CollectionElement ifTrue, CollectionElement ifFalse). If there is no
/// `else` clause, the representation for `ifFalse` will be pushed by
/// [handleNoCollectionElement]. If there is no guard, the representation
/// for `guard` will be pushed by [handleNoGuard].
- void analyzeIfCaseElement({
+ IfCaseStatementResult<Type, Error> analyzeIfCaseElement({
required Node node,
required Expression expression,
required Pattern pattern,
@@ -585,14 +613,19 @@
_finishJoinedPatternVariables(
variables, componentVariables, patternVariablePromotionKeys,
location: JoinedPatternVariableLocation.singlePattern);
+ Error? nonBooleanGuardError;
if (guard != null) {
- _checkGuardType(guard, analyzeExpression(guard, boolType));
+ nonBooleanGuardError =
+ _checkGuardType(guard, analyzeExpression(guard, boolType));
} else {
handleNoGuard(node, 0);
}
// Stack: (Expression, Pattern, Guard)
flow.ifCaseStatement_thenBegin(guard);
_analyzeIfElementCommon(node, ifTrue, ifFalse, context);
+ return new IfCaseStatementResult(
+ matchedExpressionType: initializerType,
+ nonBooleanGuardError: nonBooleanGuardError);
}
/// Analyzes a statement of the form `if (expression case pattern) ifTrue` or
@@ -602,14 +635,15 @@
/// the expression, [pattern] for the pattern to match, [ifTrue] for the
/// "then" branch, and [ifFalse] for the "else" branch (if present).
///
- /// Returns the static type of [expression].
+ /// Returns a [IfCaseStatementResult] with the static type of [expression] and
+ /// information about reported errors.
///
/// Stack effect: pushes (Expression scrutinee, Pattern, Expression guard,
/// Statement ifTrue, Statement ifFalse). If there is no `else` clause, the
/// representation for `ifFalse` will be pushed by [handleNoStatement]. If
/// there is no guard, the representation for `guard` will be pushed by
/// [handleNoGuard].
- Type analyzeIfCaseStatement(
+ IfCaseStatementResult<Type, Error> analyzeIfCaseStatement(
Statement node,
Expression expression,
Pattern pattern,
@@ -644,15 +678,19 @@
handle_ifCaseStatement_afterPattern(node: node);
// Stack: (Expression, Pattern)
+ Error? nonBooleanGuardError;
if (guard != null) {
- _checkGuardType(guard, analyzeExpression(guard, boolType));
+ nonBooleanGuardError =
+ _checkGuardType(guard, analyzeExpression(guard, boolType));
} else {
handleNoGuard(node, 0);
}
// Stack: (Expression, Pattern, Guard)
flow.ifCaseStatement_thenBegin(guard);
_analyzeIfCommon(node, ifTrue, ifFalse);
- return initializerType;
+ return new IfCaseStatementResult(
+ matchedExpressionType: initializerType,
+ nonBooleanGuardError: nonBooleanGuardError);
}
/// Analyzes a collection element of the form `if (condition) ifTrue` or
@@ -718,10 +756,13 @@
/// the list element type (if explicitly supplied), and [elements] is the
/// list of subpatterns.
///
+ /// Returns a [ListPatternResult] with the required type and information about
+ /// reported errors.
+ ///
/// See [dispatchPattern] for the meaning of [context].
///
/// Stack effect: pushes (n * Pattern) where n = elements.length.
- Type analyzeListPattern(
+ ListPatternResult<Type, Error> analyzeListPattern(
MatchContext<Node, Expression, Pattern, Type, Variable> context,
Pattern node,
{Type? elementType,
@@ -747,10 +788,12 @@
matchMayFailEvenIfCorrectType: true);
// Stack: ()
Node? previousRestPattern;
- for (Node element in elements) {
+ Map<int, Error>? duplicateRestPatternErrors;
+ for (int i = 0; i < elements.length; i++) {
+ Node element = elements[i];
if (isRestPatternElement(element)) {
if (previousRestPattern != null) {
- errors?.duplicateRestPattern(
+ (duplicateRestPatternErrors ??= {})[i] = errors.duplicateRestPattern(
mapOrListPattern: node,
original: previousRestPattern,
duplicate: element,
@@ -774,15 +817,21 @@
}
// Stack: (n * Pattern) where n = elements.length
Node? irrefutableContext = context.irrefutableContext;
+ Error? patternTypeMismatchInIrrefutableContextError;
if (irrefutableContext != null &&
!operations.isAssignableTo(matchedType, requiredType)) {
- errors?.patternTypeMismatchInIrrefutableContext(
- pattern: node,
- context: irrefutableContext,
- matchedType: matchedType,
- requiredType: requiredType);
+ patternTypeMismatchInIrrefutableContextError =
+ errors.patternTypeMismatchInIrrefutableContext(
+ pattern: node,
+ context: irrefutableContext,
+ matchedType: matchedType,
+ requiredType: requiredType);
}
- return requiredType;
+ return new ListPatternResult(
+ requiredType: requiredType,
+ duplicateRestPatternErrors: duplicateRestPatternErrors,
+ patternTypeMismatchInIrrefutableContextError:
+ patternTypeMismatchInIrrefutableContextError);
}
/// Computes the type schema for a list pattern. [elementType] is the list
@@ -866,18 +915,22 @@
/// Analyzes a logical-or pattern. [node] is the pattern itself, and [lhs]
/// and [rhs] are the left and right sides of the `||` operator.
///
+ /// Returns a [LogicalOrPatternResult] with information about reported errors.
+ ///
/// See [dispatchPattern] for the meaning of [context].
///
/// Stack effect: pushes (Pattern left, Pattern right)
- void analyzeLogicalOrPattern(
+ LogicalOrPatternResult<Error> analyzeLogicalOrPattern(
MatchContext<Node, Expression, Pattern, Type, Variable> context,
Pattern node,
Node lhs,
Node rhs) {
Node? irrefutableContext = context.irrefutableContext;
+ Error? refutablePatternInIrrefutableContextError;
if (irrefutableContext != null) {
- errors?.refutablePatternInIrrefutableContext(
- pattern: node, context: irrefutableContext);
+ refutablePatternInIrrefutableContextError =
+ errors.refutablePatternInIrrefutableContext(
+ pattern: node, context: irrefutableContext);
// Avoid cascading errors
context = context.makeRefutable();
}
@@ -933,6 +986,9 @@
// flow control branches, the normal join process will combine promotions
// accordingly.
flow.logicalOrPattern_end();
+ return new LogicalOrPatternResult(
+ refutablePatternInIrrefutableContextError:
+ refutablePatternInIrrefutableContextError);
}
/// Computes the type schema for a logical-or pattern. [lhs] and [rhs] are
@@ -943,7 +999,7 @@
// Logical-or patterns are only allowed in refutable contexts, and
// refutable contexts don't propagate a type schema into the scrutinee.
// So this code path is only reachable if the user's code contains errors.
- errors?.assertInErrorRecovery();
+ errors.assertInErrorRecovery();
return unknownType;
}
@@ -951,10 +1007,13 @@
/// contain explicit type arguments (if specified), and [elements] is the
/// list of subpatterns.
///
+ /// Returns a [MapPatternResult] with the required type and information about
+ /// reported errors.
+ ///
/// See [dispatchPattern] for the meaning of [context].
///
/// Stack effect: pushes (n * MapPatternElement) where n = elements.length.
- Type analyzeMapPattern(
+ MapPatternResult<Type, Error> analyzeMapPattern(
MatchContext<Node, Expression, Pattern, Type, Variable> context,
Pattern node, {
required MapPatternTypeArguments<Type>? typeArguments,
@@ -996,10 +1055,12 @@
bool hasDuplicateRestPatternReported = false;
Node? previousRestPattern;
- for (Node element in elements) {
+ Map<int, Error>? duplicateRestPatternErrors;
+ for (int i = 0; i < elements.length; i++) {
+ Node element = elements[i];
if (isRestPatternElement(element)) {
if (previousRestPattern != null) {
- errors?.duplicateRestPattern(
+ (duplicateRestPatternErrors ??= {})[i] = errors.duplicateRestPattern(
mapOrListPattern: node,
original: previousRestPattern,
duplicate: element,
@@ -1026,12 +1087,12 @@
assert(isRestPatternElement(element));
if (!hasDuplicateRestPatternReported) {
if (i != elements.length - 1) {
- errors?.restPatternNotLastInMap(node: node, element: element);
+ errors.restPatternNotLastInMap(node: node, element: element);
}
}
Pattern? subPattern = getRestPatternElementPattern(element);
if (subPattern != null) {
- errors?.restPatternWithSubPatternInMap(node: node, element: element);
+ errors.restPatternWithSubPatternInMap(node: node, element: element);
flow.pushSubpattern(dynamicType);
dispatchPattern(
context.withUnnecessaryWildcardKind(null),
@@ -1044,16 +1105,22 @@
}
// Stack: (n * MapPatternElement) where n = elements.length
Node? irrefutableContext = context.irrefutableContext;
+ Error? patternTypeMismatchInIrrefutableContextError;
if (irrefutableContext != null &&
!operations.isAssignableTo(matchedType, requiredType)) {
- errors?.patternTypeMismatchInIrrefutableContext(
+ patternTypeMismatchInIrrefutableContextError =
+ errors.patternTypeMismatchInIrrefutableContext(
pattern: node,
context: irrefutableContext,
matchedType: matchedType,
requiredType: requiredType,
);
}
- return requiredType;
+ return new MapPatternResult(
+ requiredType: requiredType,
+ duplicateRestPatternErrors: duplicateRestPatternErrors,
+ patternTypeMismatchInIrrefutableContextError:
+ patternTypeMismatchInIrrefutableContextError);
}
/// Computes the type schema for a map pattern. [typeArguments] contain
@@ -1094,25 +1161,32 @@
/// itself, [innerPattern] is the sub-pattern, and [isAssert] indicates
/// whether this is a null-check or a null-assert pattern.
///
+ /// Returns a [NullCheckOrAssertPatternResult] with information about
+ /// reported errors.
+ ///
/// See [dispatchPattern] for the meaning of [context].
///
/// Stack effect: pushes (Pattern innerPattern).
- void analyzeNullCheckOrAssertPattern(
+ NullCheckOrAssertPatternResult<Error> analyzeNullCheckOrAssertPattern(
MatchContext<Node, Expression, Pattern, Type, Variable> context,
Pattern node,
Pattern innerPattern,
{required bool isAssert}) {
// Stack: ()
+ Error? refutablePatternInIrrefutableContextError;
+ Error? matchedTypeIsStrictlyNonNullableError;
Node? irrefutableContext = context.irrefutableContext;
bool matchedTypeIsStrictlyNonNullable =
flow.nullCheckOrAssertPattern_begin(isAssert: isAssert);
if (irrefutableContext != null && !isAssert) {
- errors?.refutablePatternInIrrefutableContext(
- pattern: node, context: irrefutableContext);
+ refutablePatternInIrrefutableContextError =
+ errors.refutablePatternInIrrefutableContext(
+ pattern: node, context: irrefutableContext);
// Avoid cascading errors
context = context.makeRefutable();
} else if (matchedTypeIsStrictlyNonNullable) {
- errors?.matchedTypeIsStrictlyNonNullable(
+ matchedTypeIsStrictlyNonNullableError =
+ errors.matchedTypeIsStrictlyNonNullable(
pattern: node,
matchedType: flow.getMatchedValueType(),
);
@@ -1123,6 +1197,12 @@
);
// Stack: (Pattern)
flow.nullCheckOrAssertPattern_end();
+
+ return new NullCheckOrAssertPatternResult(
+ refutablePatternInIrrefutableContextError:
+ refutablePatternInIrrefutableContextError,
+ matchedTypeIsStrictlyNonNullableError:
+ matchedTypeIsStrictlyNonNullableError);
}
/// Computes the type schema for a null-check or null-assert pattern.
@@ -1138,7 +1218,7 @@
// Null-check patterns are only allowed in refutable contexts, and
// refutable contexts don't propagate a type schema into the scrutinee.
// So this code path is only reachable if the user's code contains errors.
- errors?.assertInErrorRecovery();
+ errors.assertInErrorRecovery();
return unknownType;
}
}
@@ -1148,15 +1228,19 @@
/// irrefutable contexts, but can be `null` in refutable contexts, then
/// [downwardInferObjectPatternRequiredType] is invoked to infer the type.
///
+ /// Returns a [ObjectPatternResult] with the required type and information
+ /// about reported errors.
+ ///
/// See [dispatchPattern] for the meaning of [context].
///
/// Stack effect: pushes (n * Pattern) where n = fields.length.
- Type analyzeObjectPattern(
+ ObjectPatternResult<Type, Error> analyzeObjectPattern(
MatchContext<Node, Expression, Pattern, Type, Variable> context,
Pattern node, {
required List<RecordPatternField<Node, Pattern>> fields,
}) {
- _reportDuplicateRecordPatternFields(node, fields);
+ Map<int, Error>? duplicateRecordPatternFieldErrors =
+ _reportDuplicateRecordPatternFields(node, fields);
Type matchedType = flow.getMatchedValueType();
Type requiredType = downwardInferObjectPatternRequiredType(
@@ -1174,9 +1258,11 @@
}
Node? irrefutableContext = context.irrefutableContext;
+ Error? patternTypeMismatchInIrrefutableContextError;
if (irrefutableContext != null &&
!operations.isAssignableTo(matchedType, requiredType)) {
- errors?.patternTypeMismatchInIrrefutableContext(
+ patternTypeMismatchInIrrefutableContextError =
+ errors.patternTypeMismatchInIrrefutableContext(
pattern: node,
context: irrefutableContext,
matchedType: matchedType,
@@ -1200,7 +1286,11 @@
}
// Stack: (n * Pattern) where n = fields.length
- return requiredType;
+ return new ObjectPatternResult(
+ requiredType: requiredType,
+ duplicateRecordPatternFieldErrors: duplicateRecordPatternFieldErrors,
+ patternTypeMismatchInIrrefutableContextError:
+ patternTypeMismatchInIrrefutableContextError);
}
/// Computes the type schema for an object pattern. [type] is the type
@@ -1239,7 +1329,7 @@
if (componentVariables.isNotEmpty) {
// Declared pattern variables should never appear in a pattern assignment
// so this should never happen.
- errors?.assertInErrorRecovery();
+ errors.assertInErrorRecovery();
}
flow.patternAssignment_end();
// Stack: (Expression, Pattern)
@@ -1258,7 +1348,9 @@
/// `for (<keyword> <pattern> in <expression>) <body>`
///
/// Stack effect: pushes (Expression, Pattern).
- void analyzePatternForIn({
+ ///
+ /// Returns a [PatternForInResult] containing information on reported errors.
+ PatternForInResult<Error> analyzePatternForIn({
required Node node,
required bool hasAwait,
required Pattern pattern,
@@ -1273,6 +1365,7 @@
Type expressionType = analyzeExpression(expression, expressionTypeSchema);
// Stack: (Expression)
+ Error? patternForInExpressionIsNotIterableError;
Type? elementType = hasAwait
? operations.matchStreamType(expressionType)
: operations.matchIterableType(expressionType);
@@ -1280,7 +1373,8 @@
if (operations.isDynamic(expressionType)) {
elementType = dynamicType;
} else {
- errors?.patternForInExpressionIsNotIterable(
+ patternForInExpressionIsNotIterableError =
+ errors.patternForInExpressionIsNotIterable(
node: node,
expression: expression,
expressionType: expressionType,
@@ -1307,6 +1401,10 @@
dispatchBody();
flow.forEach_end();
flow.patternForIn_end();
+
+ return new PatternForInResult(
+ patternForInExpressionIsNotIterableError:
+ patternForInExpressionIsNotIterableError);
}
/// Analyzes a patternVariableDeclaration node of the form
@@ -1329,7 +1427,7 @@
{required bool isFinal, required bool isLate}) {
// Stack: ()
if (isLate && !isVariablePattern(pattern)) {
- errors?.patternDoesNotAllowLate(pattern: pattern);
+ errors.patternDoesNotAllowLate(pattern: pattern);
}
if (isLate) {
flow.lateInitializer_begin(node);
@@ -1365,10 +1463,13 @@
/// Analyzes a record pattern. [node] is the pattern itself, and [fields]
/// is the list of subpatterns.
///
+ /// Returns a [RecordPatternResult] with the required type and information
+ /// about reported errors.
+ ///
/// See [dispatchPattern] for the meaning of [context].
///
/// Stack effect: pushes (n * Pattern) where n = fields.length.
- Type analyzeRecordPattern(
+ RecordPatternResult<Type, Error> analyzeRecordPattern(
MatchContext<Node, Expression, Pattern, Type, Variable> context,
Pattern node, {
required List<RecordPatternField<Node, Pattern>> fields,
@@ -1400,7 +1501,8 @@
}
}
- _reportDuplicateRecordPatternFields(node, fields);
+ Map<int, Error>? duplicateRecordPatternFieldErrors =
+ _reportDuplicateRecordPatternFields(node, fields);
// Build the required type.
int requiredTypePositionalCount = 0;
@@ -1445,9 +1547,11 @@
// Stack: (n * Pattern) where n = fields.length
Node? irrefutableContext = context.irrefutableContext;
+ Error? patternTypeMismatchInIrrefutableContextError;
if (irrefutableContext != null &&
!operations.isAssignableTo(matchedType, requiredType)) {
- errors?.patternTypeMismatchInIrrefutableContext(
+ patternTypeMismatchInIrrefutableContextError =
+ errors.patternTypeMismatchInIrrefutableContext(
pattern: node,
context: irrefutableContext,
matchedType: matchedType,
@@ -1461,7 +1565,11 @@
matchedType: matchedType,
knownType: demonstratedType,
matchFailsIfWrongType: false);
- return requiredType;
+ return new RecordPatternResult(
+ requiredType: requiredType,
+ duplicateRecordPatternFieldErrors: duplicateRecordPatternFieldErrors,
+ patternTypeMismatchInIrrefutableContextError:
+ patternTypeMismatchInIrrefutableContextError);
}
/// Computes the type schema for a record pattern.
@@ -1491,22 +1599,23 @@
/// This method will invoke [resolveRelationalPatternOperator] to obtain
/// information about the operator.
///
- /// Returns the type of the [operand].
+ /// Returns a [RelationalPatternResult] with the type of the [operand] and
+ /// information about reported errors.
///
/// See [dispatchPattern] for the meaning of [context].
///
/// Stack effect: pushes (Expression).
- Type analyzeRelationalPattern(
+ RelationalPatternResult<Type, Error> analyzeRelationalPattern(
MatchContext<Node, Expression, Pattern, Type, Variable> context,
Pattern node,
Expression operand) {
// Stack: ()
- TypeAnalyzerErrors<Node, Node, Expression, Variable, Type, Pattern>?
- errors = this.errors;
+ Error? refutablePatternInIrrefutableContextError;
Node? irrefutableContext = context.irrefutableContext;
if (irrefutableContext != null) {
- errors?.refutablePatternInIrrefutableContext(
- pattern: node, context: irrefutableContext);
+ refutablePatternInIrrefutableContextError =
+ errors.refutablePatternInIrrefutableContext(
+ pattern: node, context: irrefutableContext);
}
Type matchedValueType = flow.getMatchedValueType();
RelationalOperatorResolution<Type>? operator =
@@ -1531,26 +1640,33 @@
break;
}
// Stack: (Expression)
- if (errors != null && operator != null) {
+ Error? argumentTypeNotAssignableError;
+ Error? operatorReturnTypeNotAssignableToBoolError;
+ if (operator != null) {
Type argumentType =
isEquality ? operations.promoteToNonNull(operandType) : operandType;
if (!operations.isAssignableTo(argumentType, operator.parameterType)) {
- errors.argumentTypeNotAssignable(
+ argumentTypeNotAssignableError = errors.argumentTypeNotAssignable(
argument: operand,
argumentType: argumentType,
parameterType: operator.parameterType,
);
}
if (!operations.isAssignableTo(operator.returnType, boolType)) {
- errors.relationalPatternOperatorReturnTypeNotAssignableToBool(
+ operatorReturnTypeNotAssignableToBoolError =
+ errors.relationalPatternOperatorReturnTypeNotAssignableToBool(
pattern: node,
returnType: operator.returnType,
);
}
}
- // TODO(johnniwinther): This doesn't scale. We probably need to pass more
- // information, for instance whether this was an erroneous case.
- return operandType;
+ return new RelationalPatternResult(
+ operandType: operandType,
+ refutablePatternInIrrefutableContextError:
+ refutablePatternInIrrefutableContextError,
+ operatorReturnTypeNotAssignableToBoolError:
+ operatorReturnTypeNotAssignableToBoolError,
+ argumentTypeNotAssignableError: argumentTypeNotAssignableError);
}
/// Computes the type schema for a relational pattern.
@@ -1560,15 +1676,18 @@
// Relational patterns are only allowed in refutable contexts, and refutable
// contexts don't propagate a type schema into the scrutinee. So this
// code path is only reachable if the user's code contains errors.
- errors?.assertInErrorRecovery();
+ errors.assertInErrorRecovery();
return unknownType;
}
/// Analyzes an expression of the form `switch (expression) { cases }`.
///
+ /// Returns a [SwitchExpressionResult] with the static type of the switch
+ /// expression and information about reported errors.
+ ///
/// Stack effect: pushes (Expression, n * ExpressionCase), where n is the
/// number of cases.
- SimpleTypeAnalysisResult<Type> analyzeSwitchExpression(
+ SwitchExpressionResult<Type, Error> analyzeSwitchExpression(
Expression node, Expression scrutinee, int numCases, Type context) {
// Stack: ()
Type expressionType = analyzeExpression(scrutinee, unknownType);
@@ -1576,6 +1695,7 @@
handleSwitchScrutinee(expressionType);
flow.switchStatement_expressionEnd(null, scrutinee, expressionType);
Type? lubType;
+ Map<int, Error>? nonBooleanGuardErrors;
for (int i = 0; i < numCases; i++) {
// Stack: (Expression, i * ExpressionCase)
SwitchExpressionMemberInfo<Node, Expression, Variable> memberInfo =
@@ -1607,7 +1727,11 @@
guard = memberInfo.head.guard;
bool hasGuard = guard != null;
if (hasGuard) {
- _checkGuardType(guard, analyzeExpression(guard, boolType));
+ Error? nonBooleanGuardError =
+ _checkGuardType(guard, analyzeExpression(guard, boolType));
+ if (nonBooleanGuardError != null) {
+ (nonBooleanGuardErrors ??= {})[i] = nonBooleanGuardError;
+ }
// Stack: (Expression, i * ExpressionCase, Pattern, Expression)
} else {
handleNoGuard(node, i);
@@ -1633,20 +1757,25 @@
}
lubType ??= dynamicType;
// Stack: (Expression, numCases * ExpressionCase)
+ Error? nonExhaustiveSwitchError;
bool isProvenExhaustive = flow.switchStatement_end(true);
if (options.errorOnSwitchExhaustiveness &&
!isProvenExhaustive &&
!isLegacySwitchExhaustive(node, expressionType)) {
- errors?.nonExhaustiveSwitch(node: node, scrutineeType: expressionType);
+ nonExhaustiveSwitchError =
+ errors.nonExhaustiveSwitch(node: node, scrutineeType: expressionType);
}
- return new SimpleTypeAnalysisResult<Type>(type: lubType);
+ return new SwitchExpressionResult(
+ type: lubType,
+ nonBooleanGuardErrors: nonBooleanGuardErrors,
+ nonExhaustiveSwitchError: nonExhaustiveSwitchError);
}
/// Analyzes a statement of the form `switch (expression) { cases }`.
///
/// Stack effect: pushes (Expression, n * StatementCase), where n is the
/// number of cases after merging together cases that share a body.
- SwitchStatementTypeAnalysisResult<Type> analyzeSwitchStatement(
+ SwitchStatementTypeAnalysisResult<Type, Error> analyzeSwitchStatement(
Statement node, Expression scrutinee, final int numCases) {
// Stack: ()
Type scrutineeType = analyzeExpression(scrutinee, unknownType);
@@ -1655,6 +1784,8 @@
flow.switchStatement_expressionEnd(node, scrutinee, scrutineeType);
bool hasDefault = false;
bool lastCaseTerminates = true;
+ Map<int, Error>? switchCaseCompletesNormallyErrors;
+ Map<int, Map<int, Error>>? nonBooleanGuardErrors;
for (int caseIndex = 0; caseIndex < numCases; caseIndex++) {
// Stack: (Expression, numExecutionPaths * StatementCase)
flow.switchStatement_beginAlternatives();
@@ -1694,7 +1825,12 @@
// numHeads * CaseHead, Pattern),
guard = head.guard;
if (guard != null) {
- _checkGuardType(guard, analyzeExpression(guard, boolType));
+ Error? nonBooleanGuardError =
+ _checkGuardType(guard, analyzeExpression(guard, boolType));
+ if (nonBooleanGuardError != null) {
+ ((nonBooleanGuardErrors ??= {})[caseIndex] ??= {})[headIndex] =
+ nonBooleanGuardError;
+ }
// Stack: (Expression, numExecutionPaths * StatementCase,
// numHeads * CaseHead, Pattern, Expression),
} else {
@@ -1736,7 +1872,8 @@
options.nullSafetyEnabled &&
!options.patternsEnabled &&
!lastCaseTerminates) {
- errors?.switchCaseCompletesNormally(node: node, caseIndex: caseIndex);
+ (switchCaseCompletesNormallyErrors ??= {})[caseIndex] = errors
+ .switchCaseCompletesNormally(node: node, caseIndex: caseIndex);
}
handleMergedStatementCase(node,
caseIndex: caseIndex, isTerminating: lastCaseTerminates);
@@ -1756,18 +1893,23 @@
requiresExhaustivenessValidation = false;
}
bool isProvenExhaustive = flow.switchStatement_end(isExhaustive);
+ Error? nonExhaustiveSwitchError;
if (options.errorOnSwitchExhaustiveness &&
requiresExhaustivenessValidation &&
!isProvenExhaustive &&
!isLegacySwitchExhaustive(node, scrutineeType)) {
- errors?.nonExhaustiveSwitch(node: node, scrutineeType: scrutineeType);
+ nonExhaustiveSwitchError =
+ errors.nonExhaustiveSwitch(node: node, scrutineeType: scrutineeType);
}
- return new SwitchStatementTypeAnalysisResult<Type>(
+ return new SwitchStatementTypeAnalysisResult(
hasDefault: hasDefault,
isExhaustive: isExhaustive,
lastCaseTerminates: lastCaseTerminates,
requiresExhaustivenessValidation: requiresExhaustivenessValidation,
scrutineeType: scrutineeType,
+ switchCaseCompletesNormallyErrors: switchCaseCompletesNormallyErrors,
+ nonBooleanGuardErrors: nonBooleanGuardErrors,
+ nonExhaustiveSwitchError: nonExhaustiveSwitchError,
);
}
@@ -1793,19 +1935,23 @@
/// Analyzes a wildcard pattern. [node] is the pattern.
///
+ /// Returns a [WildcardPattern] with information about reported errors.
+ ///
/// See [dispatchPattern] for the meaning of [context].
///
/// Stack effect: none.
- void analyzeWildcardPattern({
+ WildcardPatternResult<Error> analyzeWildcardPattern({
required MatchContext<Node, Expression, Pattern, Type, Variable> context,
required Pattern node,
required Type? declaredType,
}) {
Type matchedType = flow.getMatchedValueType();
Node? irrefutableContext = context.irrefutableContext;
+ Error? patternTypeMismatchInIrrefutableContextError;
if (irrefutableContext != null && declaredType != null) {
if (!operations.isAssignableTo(matchedType, declaredType)) {
- errors?.patternTypeMismatchInIrrefutableContext(
+ patternTypeMismatchInIrrefutableContextError =
+ errors.patternTypeMismatchInIrrefutableContext(
pattern: node,
context: irrefutableContext,
matchedType: matchedType,
@@ -1825,11 +1971,14 @@
UnnecessaryWildcardKind? unnecessaryWildcardKind =
context.unnecessaryWildcardKind;
if (isAlwaysMatching && unnecessaryWildcardKind != null) {
- errors?.unnecessaryWildcardPattern(
+ errors.unnecessaryWildcardPattern(
pattern: node,
kind: unnecessaryWildcardKind,
);
}
+ return new WildcardPatternResult(
+ patternTypeMismatchInIrrefutableContextError:
+ patternTypeMismatchInIrrefutableContextError);
}
/// Computes the type schema for a wildcard pattern. [declaredType] is the
@@ -2184,14 +2333,15 @@
// Stack: (CollectionElement ifTrue, CollectionElement ifFalse)
}
- void _checkGuardType(Expression expression, Type type) {
+ Error? _checkGuardType(Expression expression, Type type) {
// TODO(paulberry): harmonize this with analyzer's checkForNonBoolExpression
// TODO(paulberry): spec says the type must be `bool` or `dynamic`. This
// logic permits `T extends bool`, `T promoted to bool`, or `Never`. What
// do we want?
if (!operations.isAssignableTo(type, boolType)) {
- errors?.nonBooleanCondition(node: expression);
+ return errors.nonBooleanCondition(node: expression);
}
+ return null;
}
void _finishJoinedPatternVariables(
@@ -2242,7 +2392,7 @@
if (inconsistencyFound &&
location == JoinedPatternVariableLocation.singlePattern &&
variable != null) {
- errors?.inconsistentJoinedPatternVariable(
+ errors.inconsistentJoinedPatternVariable(
variable: variable, component: component);
}
}
@@ -2307,17 +2457,17 @@
}
/// Reports errors for duplicate named record fields.
- void _reportDuplicateRecordPatternFields(
- Pattern pattern,
- List<RecordPatternField<Node, Pattern>> fields,
- ) {
+ Map<int, Error>? _reportDuplicateRecordPatternFields(
+ Pattern pattern, List<RecordPatternField<Node, Pattern>> fields) {
+ Map<int, Error>? errorResults;
Map<String, RecordPatternField<Node, Pattern>> nameToField = {};
- for (RecordPatternField<Node, Pattern> field in fields) {
+ for (int i = 0; i < fields.length; i++) {
+ RecordPatternField<Node, Pattern> field = fields[i];
String? name = field.name;
if (name != null) {
RecordPatternField<Node, Pattern>? original = nameToField[name];
if (original != null) {
- errors?.duplicateRecordPatternField(
+ (errorResults ??= {})[i] = errors.duplicateRecordPatternField(
objectOrRecordPattern: pattern,
name: name,
original: original,
@@ -2328,6 +2478,7 @@
}
}
}
+ return errorResults;
}
bool _structurallyEqualAfterNormTypes(Type type1, Type type2) {
@@ -2345,10 +2496,11 @@
Expression extends Node,
Variable extends Object,
Type extends Object,
- Pattern extends Node> implements TypeAnalyzerErrorsBase {
+ Pattern extends Node,
+ Error> implements TypeAnalyzerErrorsBase {
/// Called if [argument] has type [argumentType], which is not assignable
/// to [parameterType].
- void argumentTypeNotAssignable({
+ Error argumentTypeNotAssignable({
required Expression argument,
required Type argumentType,
required Type parameterType,
@@ -2356,7 +2508,7 @@
/// Called if pattern support is disabled and a case constant's static type
/// doesn't properly match the scrutinee's static type.
- void caseExpressionTypeMismatch(
+ Error caseExpressionTypeMismatch(
{required Expression scrutinee,
required Expression caseExpression,
required Type scrutineeType,
@@ -2364,14 +2516,16 @@
required bool nullSafetyEnabled});
/// Called for variable that is assigned more than once.
- void duplicateAssignmentPatternVariable({
+ ///
+ /// Returns an error object that is passed on the the caller.
+ Error duplicateAssignmentPatternVariable({
required Variable variable,
required Pattern original,
required Pattern duplicate,
});
/// Called for a pair of named fields have the same name.
- void duplicateRecordPatternField({
+ Error duplicateRecordPatternField({
required Pattern objectOrRecordPattern,
required String name,
required RecordPatternField<Node, Pattern> original,
@@ -2379,7 +2533,7 @@
});
/// Called for a duplicate rest pattern found in a list or map pattern.
- void duplicateRestPattern({
+ Error duplicateRestPattern({
required Pattern mapOrListPattern,
required Node original,
required Node duplicate,
@@ -2395,7 +2549,7 @@
/// Called when a null-assert or null-check pattern is used with the matched
/// type that is strictly non-nullable, so the null check is not necessary.
- void matchedTypeIsStrictlyNonNullable({
+ Error matchedTypeIsStrictlyNonNullable({
required Pattern pattern,
required Type matchedType,
});
@@ -2409,7 +2563,7 @@
});
/// Called if the static type of a condition is not assignable to `bool`.
- void nonBooleanCondition({required Expression node});
+ Error nonBooleanCondition({required Expression node});
/// Called if [TypeAnalyzerOptions.errorOnSwitchExhaustiveness] is `true`, and
/// a switch that is required to be exhaustive cannot be proven by flow
@@ -2418,7 +2572,7 @@
/// [node] is the offending switch expression or switch statement, and
/// [scrutineeType] is the static type of the switch statement's scrutinee
/// expression.
- void nonExhaustiveSwitch({required Node node, required Type scrutineeType});
+ Error nonExhaustiveSwitch({required Node node, required Type scrutineeType});
/// Called if a pattern is illegally used in a variable declaration statement
/// that is marked `late`, and that pattern is not allowed in such a
@@ -2432,7 +2586,7 @@
/// that should be an `Iterable` (or dynamic) is actually not.
///
/// [expressionType] is the actual type of the [expression].
- void patternForInExpressionIsNotIterable({
+ Error patternForInExpressionIsNotIterable({
required Node node,
required Expression expression,
required Type expressionType,
@@ -2445,7 +2599,7 @@
/// the containing AST node that established an irrefutable context,
/// [matchedType] is the matched type, and [requiredType] is the required
/// type.
- void patternTypeMismatchInIrrefutableContext(
+ Error patternTypeMismatchInIrrefutableContext(
{required Pattern pattern,
required Node context,
required Type matchedType,
@@ -2457,12 +2611,12 @@
/// containing AST node that established an irrefutable context.
///
/// TODO(paulberry): move this error reporting to the parser.
- void refutablePatternInIrrefutableContext(
+ Error refutablePatternInIrrefutableContext(
{required Node pattern, required Node context});
/// Called if the [returnType] of the invoked relational operator is not
/// assignable to `bool`.
- void relationalPatternOperatorReturnTypeNotAssignableToBool({
+ Error relationalPatternOperatorReturnTypeNotAssignableToBool({
required Pattern pattern,
required Type returnType,
});
@@ -2484,7 +2638,7 @@
///
/// [node] is the AST node of the switch statement. [caseIndex] is the index
/// of the merged case with the erroneous case body.
- void switchCaseCompletesNormally(
+ Error switchCaseCompletesNormally(
{required Statement node, required int caseIndex});
/// Called when a wildcard pattern appears in the context where it is not
diff --git a/pkg/_fe_analyzer_shared/test/mini_ast.dart b/pkg/_fe_analyzer_shared/test/mini_ast.dart
index 1fd5a6d..c1366ce 100644
--- a/pkg/_fe_analyzer_shared/test/mini_ast.dart
+++ b/pkg/_fe_analyzer_shared/test/mini_ast.dart
@@ -2737,8 +2737,9 @@
@override
void visit(Harness h, SharedMatchContext context) {
var matchedType = h.typeAnalyzer.flow.getMatchedValueType();
- var requiredType = h.typeAnalyzer.analyzeListPattern(context, this,
+ var listPatternResult = h.typeAnalyzer.analyzeListPattern(context, this,
elementType: _elementType, elements: _elements);
+ var requiredType = listPatternResult.requiredType;
h.irBuilder.atom(matchedType.type, Kind.type, location: location);
h.irBuilder.atom(requiredType.type, Kind.type, location: location);
h.irBuilder.apply(
@@ -2929,8 +2930,9 @@
@override
void visit(Harness h, SharedMatchContext context) {
var matchedType = h.typeAnalyzer.flow.getMatchedValueType();
- var requiredType = h.typeAnalyzer.analyzeMapPattern(context, this,
+ var mapPatternResult = h.typeAnalyzer.analyzeMapPattern(context, this,
typeArguments: _typeArguments, elements: _elements);
+ var requiredType = mapPatternResult.requiredType;
h.irBuilder.atom(matchedType.type, Kind.type, location: location);
h.irBuilder.atom(requiredType.type, Kind.type, location: location);
h.irBuilder.apply(
@@ -2976,7 +2978,8 @@
class _MiniAstErrors
implements
- TypeAnalyzerErrors<Node, Statement, Expression, Var, Type, Pattern>,
+ TypeAnalyzerErrors<Node, Statement, Expression, Var, Type, Pattern,
+ void>,
VariableBinderErrors<Node, Var> {
final Set<String> _accumulatedErrors = {};
@@ -3248,7 +3251,7 @@
}
class _MiniAstTypeAnalyzer
- with TypeAnalyzer<Node, Statement, Expression, Var, Type, Pattern> {
+ with TypeAnalyzer<Node, Statement, Expression, Var, Type, Pattern, void> {
final Harness _harness;
@override
@@ -4137,8 +4140,9 @@
@override
void visit(Harness h, SharedMatchContext context) {
var matchedType = h.typeAnalyzer.flow.getMatchedValueType();
- var requiredType =
+ var objectPatternResult =
h.typeAnalyzer.analyzeObjectPattern(context, this, fields: fields);
+ var requiredType = objectPatternResult.requiredType;
h.irBuilder.atom(matchedType.type, Kind.type, location: location);
h.irBuilder.atom(requiredType.type, Kind.type, location: location);
h.irBuilder.apply(
@@ -4407,8 +4411,9 @@
@override
void visit(Harness h, SharedMatchContext context) {
var matchedType = h.typeAnalyzer.flow.getMatchedValueType();
- var requiredType =
+ var recordPatternResult =
h.typeAnalyzer.analyzeRecordPattern(context, this, fields: fields);
+ var requiredType = recordPatternResult.requiredType;
h.irBuilder.atom(matchedType.type, Kind.type, location: location);
h.irBuilder.atom(requiredType.type, Kind.type, location: location);
h.irBuilder.apply(
@@ -4922,8 +4927,10 @@
h.typeAnalyzer.handleAssignedVariablePattern(this);
} else {
var matchedType = h.typeAnalyzer.flow.getMatchedValueType();
- var staticType = h.typeAnalyzer.analyzeDeclaredVariablePattern(
- context, this, variable, variable.name, declaredType);
+ var declaredVariablePatternResult = h.typeAnalyzer
+ .analyzeDeclaredVariablePattern(
+ context, this, variable, variable.name, declaredType);
+ var staticType = declaredVariablePatternResult.staticType;
h.typeAnalyzer.handleDeclaredVariablePattern(this,
matchedType: matchedType, staticType: staticType);
}
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 9d130cb..e7fb749 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -3664,12 +3664,10 @@
ResolverVisitor resolverVisitor,
SharedMatchContext context,
) {
- declaredElement!.type = resolverVisitor.analyzeDeclaredVariablePattern(
- context,
- this,
- declaredElement!,
- declaredElement!.name,
- type?.typeOrThrow);
+ declaredElement!.type = resolverVisitor
+ .analyzeDeclaredVariablePattern(context, this, declaredElement!,
+ declaredElement!.name, type?.typeOrThrow)
+ .staticType;
}
@override
diff --git a/pkg/analyzer/lib/src/dart/resolver/list_pattern_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/list_pattern_resolver.dart
index ec5a887..4edfbdf 100644
--- a/pkg/analyzer/lib/src/dart/resolver/list_pattern_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/list_pattern_resolver.dart
@@ -30,8 +30,10 @@
}
}
- node.requiredType = resolverVisitor.analyzeListPattern(context, node,
- elementType: typeArguments?.arguments.first.typeOrThrow,
- elements: node.elements);
+ node.requiredType = resolverVisitor
+ .analyzeListPattern(context, node,
+ elementType: typeArguments?.arguments.first.typeOrThrow,
+ elements: node.elements)
+ .requiredType;
}
}
diff --git a/pkg/analyzer/lib/src/dart/resolver/shared_type_analyzer.dart b/pkg/analyzer/lib/src/dart/resolver/shared_type_analyzer.dart
index 1ceb938..7c1cbaa 100644
--- a/pkg/analyzer/lib/src/dart/resolver/shared_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/shared_type_analyzer.dart
@@ -23,7 +23,7 @@
class SharedTypeAnalyzerErrors
implements
shared.TypeAnalyzerErrors<AstNode, Statement, Expression,
- PromotableElement, DartType, DartPattern> {
+ PromotableElement, DartType, DartPattern, void> {
final ErrorReporter _errorReporter;
SharedTypeAnalyzerErrors(this._errorReporter);
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index d85d20b..e30efc1 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -154,7 +154,7 @@
with
ErrorDetectionHelpers,
TypeAnalyzer<AstNode, Statement, Expression, PromotableElement,
- DartType, DartPattern> {
+ DartType, DartPattern, void> {
/// Debug-only: if `true`, manipulations of [_rewriteStack] performed by
/// [popRewrite], [pushRewrite], and [replaceExpression] will be printed.
static const bool _debugRewriteStack = false;
@@ -1563,7 +1563,7 @@
node,
typeArguments: typeArguments,
elements: node.elements,
- );
+ ).requiredType;
}
@override
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 8d98d1a..732a7f7 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -8515,7 +8515,7 @@
}
@override
- Expression buildProblem(Message message, int charOffset, int length,
+ InvalidExpression buildProblem(Message message, int charOffset, int length,
{List<LocatedMessage>? context,
bool suppressMessage = false,
Expression? expression}) {
@@ -9282,10 +9282,13 @@
} else if (inAssignmentPattern) {
String name = variable.lexeme;
if (keyword != null || type != null) {
- pattern = new InvalidPattern(buildProblem(
- fasta.templatePatternAssignmentDeclaresVariable.withArguments(name),
- variable.charOffset,
- variable.charCount));
+ pattern = new InvalidPattern(
+ buildProblem(
+ fasta.templatePatternAssignmentDeclaresVariable
+ .withArguments(name),
+ variable.charOffset,
+ variable.charCount),
+ declaredVariables: const []);
} else {
Expression variableUse = toValue(scopeLookup(scope, name, variable));
if (variableUse is VariableGet) {
@@ -9334,10 +9337,10 @@
name = pattern.variableName;
}
if (name == null) {
- push(new InvalidPattern(buildProblem(
- fasta.messageUnspecifiedGetterNameInObjectPattern,
- colon.charOffset,
- noLength)));
+ push(new InvalidPattern(
+ buildProblem(fasta.messageUnspecifiedGetterNameInObjectPattern,
+ colon.charOffset, noLength),
+ declaredVariables: const []));
} else {
push(new NamedPattern(name, pattern, colon.charOffset));
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
index ed5e0d47..6762465 100644
--- a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
@@ -3667,8 +3667,6 @@
}
abstract class Pattern extends TreeNode with InternalTreeNode {
- Expression? error;
-
Pattern(int fileOffset) {
this.fileOffset = fileOffset;
}
@@ -4236,11 +4234,13 @@
}
class PatternAssignment extends InternalExpression {
- final Pattern pattern;
- final Expression expression;
+ Pattern pattern;
+ Expression expression;
PatternAssignment(this.pattern, this.expression, {required int fileOffset}) {
super.fileOffset = fileOffset;
+ pattern.parent = this;
+ expression.parent = this;
}
@override
@@ -4730,7 +4730,11 @@
class InvalidPattern extends Pattern {
final Expression invalidExpression;
- InvalidPattern(this.invalidExpression) : super(invalidExpression.fileOffset) {
+ @override
+ final List<VariableDeclaration> declaredVariables;
+
+ InvalidPattern(this.invalidExpression, {required this.declaredVariables})
+ : super(invalidExpression.fileOffset) {
invalidExpression.parent = this;
}
@@ -4739,9 +4743,6 @@
visitor.visitInvalidPattern(this, arg);
@override
- List<VariableDeclaration> get declaredVariables => const [];
-
- @override
void toTextInternal(AstPrinter printer) {
printer.writeExpression(invalidExpression);
}
@@ -4797,9 +4798,6 @@
/// Operator accessed on a receiver of an invalid type.
Invalid,
-
- /// Erroneous operator access.
- Error,
}
/// Kinds of lowerings of objects pattern property access.
diff --git a/pkg/front_end/lib/src/fasta/type_inference/delayed_expressions.dart b/pkg/front_end/lib/src/fasta/type_inference/delayed_expressions.dart
index c173676..56fc31e 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/delayed_expressions.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/delayed_expressions.dart
@@ -653,7 +653,13 @@
final int fileOffset;
DelayedRecordNameGet(this._receiver, this._recordType, this._name,
- {required this.fileOffset});
+ {required this.fileOffset})
+ : assert(
+ _recordType.named
+ .where((element) => element.name == _name)
+ .length ==
+ 1,
+ "Invalid record type $_recordType for named access of '$_name'.");
@override
Expression createExpression(TypeEnvironment typeEnvironment) {
diff --git a/pkg/front_end/lib/src/fasta/type_inference/inference_helper.dart b/pkg/front_end/lib/src/fasta/type_inference/inference_helper.dart
index cfe7265..20333f2 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/inference_helper.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/inference_helper.dart
@@ -9,7 +9,7 @@
abstract class InferenceHelper {
Uri get uri;
- Expression buildProblem(Message message, int charOffset, int length,
+ InvalidExpression buildProblem(Message message, int charOffset, int length,
{List<LocatedMessage>? context,
bool suppressMessage = false,
Expression? expression});
diff --git a/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart b/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart
index 8070842..4ec048d 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart
@@ -98,7 +98,7 @@
class InferenceVisitorImpl extends InferenceVisitorBase
with
TypeAnalyzer<TreeNode, Statement, Expression, VariableDeclaration,
- DartType, Pattern>,
+ DartType, Pattern, InvalidExpression>,
StackChecker
implements
ExpressionVisitor1<ExpressionInferenceResult, DartType>,
@@ -1150,7 +1150,8 @@
Expression read;
if (readTarget.isMissing) {
read = createMissingPropertyGet(
- node.readOffset, readReceiver, readType, node.propertyName);
+ node.readOffset, readType, node.propertyName,
+ receiver: readReceiver);
} else {
assert(readTarget.isExtensionMember);
read = new StaticInvocation(
@@ -1852,13 +1853,11 @@
assert(checkStackBase(node, stackBase = stackHeight));
// TODO(scheglov) Pass actual variables, not just `{}`.
- DartType scrutineeType = analyzeIfCaseStatement(
- node,
- node.expression,
- node.patternGuard.pattern,
- node.patternGuard.guard,
- node.then,
- node.otherwise, {});
+ IfCaseStatementResult<DartType, InvalidExpression> analysisResult =
+ analyzeIfCaseStatement(node, node.expression, node.patternGuard.pattern,
+ node.patternGuard.guard, node.then, node.otherwise, {});
+
+ DartType scrutineeType = analysisResult.matchedExpressionType;
assert(checkStack(node, stackBase, [
/* ifFalse = */ ValueKinds.StatementOrNull,
@@ -1879,7 +1878,10 @@
then = node.then = (rewrite as Statement)..parent = node;
}
rewrite = popRewrite(NullValues.Expression);
- if (!identical(node.patternGuard.guard, rewrite)) {
+ InvalidExpression? guardError = analysisResult.nonBooleanGuardError;
+ if (guardError != null) {
+ node.patternGuard.guard = guardError..parent = node.patternGuard;
+ } else if (!identical(node.patternGuard.guard, rewrite)) {
node.patternGuard.guard = (rewrite as Expression)
..parent = node.patternGuard;
}
@@ -2203,19 +2205,20 @@
inferredTypeArgument: inferredTypeArgument,
inferredSpreadTypes: inferredSpreadTypes,
inferredConditionTypes: inferredConditionTypes);
- analyzeIfCaseElement(
- node: element,
- expression: element.expression,
- pattern: element.patternGuard.pattern,
- variables: {
- for (VariableDeclaration variable
- in element.patternGuard.pattern.declaredVariables)
- variable.name!: variable
- },
- guard: element.patternGuard.guard,
- ifTrue: element.then,
- ifFalse: element.otherwise,
- context: context);
+ IfCaseStatementResult<DartType, InvalidExpression> analysisResult =
+ analyzeIfCaseElement(
+ node: element,
+ expression: element.expression,
+ pattern: element.patternGuard.pattern,
+ variables: {
+ for (VariableDeclaration variable
+ in element.patternGuard.pattern.declaredVariables)
+ variable.name!: variable
+ },
+ guard: element.patternGuard.guard,
+ ifTrue: element.then,
+ ifFalse: element.otherwise,
+ context: context);
assert(checkStack(element, stackBase, [
/* ifFalse = */ ValueKinds.ExpressionOrNull,
@@ -2237,7 +2240,10 @@
PatternGuard patternGuard = element.patternGuard;
rewrite = popRewrite(NullValues.Expression);
- if (!identical(patternGuard.guard, rewrite)) {
+ InvalidExpression? guardError = analysisResult.nonBooleanGuardError;
+ if (guardError != null) {
+ patternGuard.guard = guardError..parent = patternGuard;
+ } else if (!identical(patternGuard.guard, rewrite)) {
patternGuard.guard = (rewrite as Expression?)?..parent = patternGuard;
}
@@ -8088,8 +8094,9 @@
assert(checkStackBase(node, stackBase = stackHeight));
Expression expression = node.expression;
- SimpleTypeAnalysisResult<DartType> analysisResult = analyzeSwitchExpression(
- node, expression, node.cases.length, typeContext);
+ SwitchExpressionResult<DartType, InvalidExpression> analysisResult =
+ analyzeSwitchExpression(
+ node, expression, node.cases.length, typeContext);
DartType valueType = analysisResult.type;
assert(checkStack(node, stackBase, [
@@ -8140,8 +8147,15 @@
SwitchExpressionCase switchCase = node.cases[caseIndex];
Expression body = switchCase.expression;
- Pattern pattern = switchCase.patternGuard.pattern;
- Expression? guard = switchCase.patternGuard.guard;
+ PatternGuard patternGuard = switchCase.patternGuard;
+ Pattern pattern = patternGuard.pattern;
+ Expression? guard = patternGuard.guard;
+
+ InvalidExpression? guardError =
+ analysisResult.nonBooleanGuardErrors?[caseIndex];
+ if (guardError != null) {
+ guard = patternGuard.guard = guardError..parent = patternGuard;
+ }
replacementStatements.addAll(pattern.declaredVariables);
@@ -8216,7 +8230,8 @@
List<SwitchCaseInfo> previousSwitchPatternInfo = _switchCasePatternInfo;
_switchCasePatternInfo = [];
Expression expression = node.expression;
- SwitchStatementTypeAnalysisResult<DartType> analysisResult =
+ SwitchStatementTypeAnalysisResult<DartType, InvalidExpression>
+ analysisResult =
analyzeSwitchStatement(node, expression, node.cases.length);
assert(checkStack(node, stackBase, [
@@ -8319,7 +8334,8 @@
_switchCasePatternInfo = [];
Expression expression = node.expression;
- SwitchStatementTypeAnalysisResult<DartType> analysisResult =
+ SwitchStatementTypeAnalysisResult<DartType, InvalidExpression>
+ analysisResult =
analyzeSwitchStatement(node, expression, node.cases.length);
assert(checkStack(node, stackBase, [
@@ -8413,8 +8429,15 @@
for (int headIndex = 0;
headIndex < switchCase.patternGuards.length;
headIndex++) {
- Pattern pattern = switchCase.patternGuards[headIndex].pattern;
- Expression? guard = switchCase.patternGuards[headIndex].guard;
+ PatternGuard patternGuard = switchCase.patternGuards[headIndex];
+ Pattern pattern = patternGuard.pattern;
+ Expression? guard = patternGuard.guard;
+
+ InvalidExpression? guardError =
+ analysisResult.nonBooleanGuardErrors?[caseIndex]?[headIndex];
+ if (guardError != null) {
+ guard = patternGuard.guard = guardError..parent = patternGuard;
+ }
replacementStatements.addAll(pattern.declaredVariables);
@@ -9003,11 +9026,8 @@
int? stackBase;
assert(checkStackBase(node, stackBase = stackHeight));
- Pattern pattern = node.pattern;
- Expression initializer = node.initializer;
-
// TODO(cstefantsova): Support late variables.
- analyzePatternVariableDeclaration(node, pattern, initializer,
+ analyzePatternVariableDeclaration(node, node.pattern, node.initializer,
isFinal: node.isFinal, isLate: false);
assert(checkStack(node, stackBase, [
@@ -9016,13 +9036,17 @@
]));
Object? rewrite = popRewrite();
- if (!identical(rewrite, pattern)) {
- pattern = rewrite as Pattern;
+ if (!identical(rewrite, node.pattern)) {
+ node.pattern = rewrite as Pattern..parent = node;
}
+ assert(checkStack(node, stackBase, [
+ /* initializer = */ ValueKinds.Expression,
+ ]));
+
rewrite = popRewrite();
- if (!identical(initializer, rewrite)) {
- initializer = rewrite as Expression;
+ if (!identical(node.initializer, rewrite)) {
+ node.initializer = rewrite as Expression;
}
MatchingCache matchingCache = createMatchingCache();
@@ -9031,7 +9055,7 @@
// TODO(cstefantsova): Do we need a more precise type for the variable?
DartType matchedType = const DynamicType();
CacheableExpression matchedExpression =
- matchingCache.createRootExpression(initializer, matchedType);
+ matchingCache.createRootExpression(node.initializer, matchedType);
DelayedExpression matchingExpression =
matchingExpressionVisitor.visitPattern(node.pattern, matchedExpression);
@@ -10073,15 +10097,27 @@
node.matchedType = flow.getMatchedValueType();
- DartType inferredType = analyzeDeclaredVariablePattern(
- context, node, node.variable, node.variable.name!, node.type);
+ DeclaredVariablePatternResult<DartType, InvalidExpression> analysisResult =
+ analyzeDeclaredVariablePattern(
+ context, node, node.variable, node.variable.name!, node.type);
+
+ Pattern? replacement;
+
+ InvalidExpression? error =
+ analysisResult.patternTypeMismatchInIrrefutableContextError;
+ if (error != null) {
+ replacement =
+ new InvalidPattern(error, declaredVariables: node.declaredVariables);
+ }
+
+ DartType inferredType = analysisResult.staticType;
instrumentation?.record(uriForInstrumentation, node.variable.fileOffset,
'type', new InstrumentationValueForType(inferredType));
if (node.type == null) {
node.variable.type = inferredType;
}
- pushRewrite(node);
+ pushRewrite(replacement ?? node);
assert(checkStack(node, stackBase, [
/* pattern = */ ValueKinds.Pattern,
@@ -10093,10 +10129,20 @@
int? stackBase;
assert(checkStackBase(node, stackBase = stackHeight));
- analyzeWildcardPattern(
- context: context, node: node, declaredType: node.type);
+ WildcardPatternResult<InvalidExpression> analysisResult =
+ analyzeWildcardPattern(
+ context: context, node: node, declaredType: node.type);
- pushRewrite(node);
+ Pattern? replacement;
+
+ InvalidExpression? error =
+ analysisResult.patternTypeMismatchInIrrefutableContextError;
+ if (error != null) {
+ replacement =
+ new InvalidPattern(error, declaredVariables: node.declaredVariables);
+ }
+
+ pushRewrite(replacement ?? node);
assert(checkStack(node, stackBase, [
/* pattern = */ ValueKinds.Pattern,
@@ -10108,9 +10154,20 @@
int? stackBase;
assert(checkStackBase(node, stackBase = stackHeight));
- node.expressionType =
+ ConstantPatternResult<DartType, InvalidExpression> analysisResult =
analyzeConstantPattern(context, node, node.expression);
+ Pattern? replacement;
+
+ InvalidExpression? error =
+ analysisResult.refutablePatternInIrrefutableContextError;
+ if (error != null) {
+ replacement =
+ new InvalidPattern(error, declaredVariables: node.declaredVariables);
+ }
+
+ node.expressionType = analysisResult.expressionType;
+
ObjectAccessTarget equalsInvokeTarget = findInterfaceMember(
node.expressionType, equalsName, node.fileOffset,
includeExtensionMethods: true,
@@ -10131,7 +10188,7 @@
node.expression = (rewrite as Expression)..parent = node;
}
- pushRewrite(node);
+ pushRewrite(replacement ?? node);
assert(checkStack(node, stackBase, [
/* pattern = */ ValueKinds.Pattern,
@@ -10172,13 +10229,23 @@
int? stackBase;
assert(checkStackBase(node, stackBase = stackHeight));
- analyzeLogicalOrPattern(context, node, node.left, node.right);
+ LogicalOrPatternResult<InvalidExpression> analysisResult =
+ analyzeLogicalOrPattern(context, node, node.left, node.right);
assert(checkStack(node, stackBase, [
/* right = */ ValueKinds.Pattern,
/* left = */ ValueKinds.Pattern,
]));
+ Pattern? replacement;
+
+ InvalidExpression? error =
+ analysisResult.refutablePatternInIrrefutableContextError;
+ if (error != null) {
+ replacement =
+ new InvalidPattern(error, declaredVariables: node.declaredVariables);
+ }
+
Object? rewrite = popRewrite();
if (!identical(rewrite, node.right)) {
node.right = (rewrite as Pattern)..parent = node;
@@ -10189,7 +10256,7 @@
node.left = (rewrite as Pattern)..parent = node;
}
- pushRewrite(node);
+ pushRewrite(replacement ?? node);
assert(checkStack(node, stackBase, [
/* pattern = */ ValueKinds.Pattern,
@@ -10230,19 +10297,29 @@
int? stackBase;
assert(checkStackBase(node, stackBase = stackHeight));
- analyzeNullCheckOrAssertPattern(context, node, node.pattern,
- isAssert: true);
+ NullCheckOrAssertPatternResult<InvalidExpression> analysisResult =
+ analyzeNullCheckOrAssertPattern(context, node, node.pattern,
+ isAssert: true);
assert(checkStack(node, stackBase, [
/* subpattern = */ ValueKinds.Pattern,
]));
+ Pattern? replacement;
+
+ InvalidExpression? error =
+ analysisResult.refutablePatternInIrrefutableContextError;
+ if (error != null) {
+ replacement =
+ new InvalidPattern(error, declaredVariables: node.declaredVariables);
+ }
+
Object? rewrite = popRewrite();
if (!identical(rewrite, node.pattern)) {
node.pattern = (rewrite as Pattern)..parent = node;
}
- pushRewrite(node);
+ pushRewrite(replacement ?? node);
assert(checkStack(node, stackBase, [
/* pattern = */ ValueKinds.Pattern,
@@ -10363,22 +10440,37 @@
node.lengthCheckType = equalsInvokeTarget.getFunctionType(this);
}
- analyzeListPattern(context, node,
- elements: node.patterns, elementType: node.typeArgument);
+ ListPatternResult<DartType, InvalidExpression> analysisResult =
+ analyzeListPattern(context, node,
+ elements: node.patterns, elementType: node.typeArgument);
assert(checkStack(node, stackBase, [
/* subpatterns = */ ...repeatedKind(
ValueKinds.Pattern, node.patterns.length)
]));
+ Pattern? replacement;
+
+ InvalidExpression? error =
+ analysisResult.patternTypeMismatchInIrrefutableContextError;
+ if (error != null) {
+ replacement =
+ new InvalidPattern(error, declaredVariables: node.declaredVariables);
+ }
+
for (int i = node.patterns.length - 1; i >= 0; i--) {
Object? rewrite = popRewrite();
- if (!identical(rewrite, node.patterns[i])) {
+ InvalidExpression? error = analysisResult.duplicateRestPatternErrors?[i];
+ if (error != null) {
+ node.patterns[i] = new InvalidPattern(error,
+ declaredVariables: node.patterns[i].declaredVariables)
+ ..parent = node;
+ } else if (!identical(rewrite, node.patterns[i])) {
node.patterns[i] = (rewrite as Pattern)..parent = node;
}
}
- pushRewrite(node);
+ pushRewrite(replacement ?? node);
assert(checkStack(node, stackBase, [
/* pattern = */ ValueKinds.Pattern,
@@ -10398,8 +10490,9 @@
node.matchedType = flow.getMatchedValueType();
- analyzeObjectPattern(context, node,
- fields: <RecordPatternField<TreeNode, Pattern>>[
+ ObjectPatternResult<DartType, InvalidExpression> analysisResult =
+ analyzeObjectPattern(context, node,
+ fields: <RecordPatternField<TreeNode, Pattern>>[
for (NamedPattern field in node.fields)
new RecordPatternField(
node: field, name: field.name, pattern: field.pattern)
@@ -10410,10 +10503,25 @@
ValueKinds.Pattern, node.fields.length)
]));
+ Pattern? replacement;
+
+ InvalidExpression? error =
+ analysisResult.patternTypeMismatchInIrrefutableContextError;
+ if (error != null) {
+ replacement =
+ new InvalidPattern(error, declaredVariables: node.declaredVariables);
+ }
+
for (int i = node.fields.length - 1; i >= 0; i--) {
NamedPattern field = node.fields[i];
Object? rewrite = popRewrite();
- if (!identical(rewrite, field.pattern)) {
+ InvalidExpression? error =
+ analysisResult.duplicateRecordPatternFieldErrors?[i];
+ if (error != null) {
+ field.pattern = new InvalidPattern(error,
+ declaredVariables: field.pattern.declaredVariables)
+ ..parent = field;
+ } else if (!identical(rewrite, field.pattern)) {
field.pattern = (rewrite as Pattern)..parent = field;
}
}
@@ -10477,9 +10585,11 @@
case ObjectAccessTargetKind.nullableCallFunction:
case ObjectAccessTargetKind.missing:
case ObjectAccessTargetKind.ambiguous:
- // TODO(johnniwinther): Provide the right receiver.
- field.error = createMissingPropertyGet(field.fileOffset,
- new NullLiteral(), node.objectType, field.fieldName);
+ field.pattern = new InvalidPattern(
+ createMissingPropertyGet(
+ field.fileOffset, node.objectType, field.fieldName),
+ declaredVariables: field.pattern.declaredVariables)
+ ..parent = field;
field.accessKind = ObjectAccessKind.Error;
break;
case ObjectAccessTargetKind.invalid:
@@ -10509,14 +10619,15 @@
}
} else {
field.accessKind = ObjectAccessKind.Error;
- field.error = helper.buildProblem(
- messageUnspecifiedGetterNameInObjectPattern,
- node.fileOffset,
- noLength);
+ field.pattern = new InvalidPattern(
+ helper.buildProblem(messageUnspecifiedGetterNameInObjectPattern,
+ node.fileOffset, noLength),
+ declaredVariables: field.pattern.declaredVariables)
+ ..parent = field;
}
}
- pushRewrite(node);
+ pushRewrite(replacement ?? node);
assert(checkStack(node, stackBase, [
/* pattern = */ ValueKinds.Pattern,
@@ -10555,18 +10666,30 @@
node.matchedType = flow.getMatchedValueType();
- DartType expressionType =
+ RelationalPatternResult<DartType, InvalidExpression> analysisResult =
analyzeRelationalPattern(context, node, node.expression);
assert(checkStack(node, stackBase, [
/* expression = */ ValueKinds.Expression,
]));
+ Pattern? replacement;
+
+ InvalidExpression? error =
+ analysisResult.refutablePatternInIrrefutableContextError ??
+ analysisResult.operatorReturnTypeNotAssignableToBoolError ??
+ analysisResult.argumentTypeNotAssignableError;
+ if (error != null) {
+ replacement =
+ new InvalidPattern(error, declaredVariables: node.declaredVariables);
+ }
+
Object? rewrite = popRewrite();
if (!identical(rewrite, node.expression)) {
node.expression = (rewrite as Expression)..parent = node;
}
+ DartType expressionType = analysisResult.operandType;
node.expressionType = expressionType;
switch (node.kind) {
@@ -10627,15 +10750,11 @@
case ObjectAccessTargetKind.nullableInlineClassMember:
case ObjectAccessTargetKind.missing:
case ObjectAccessTargetKind.ambiguous:
- // TODO(johnniwinther): Provide the right receiver and argument.
- node.error = createMissingMethodInvocation(
- node.fileOffset,
- new NullLiteral(),
- node.matchedType,
- node.name,
- new Arguments([])..fileOffset = node.fileOffset,
- isExpressionInvocation: false);
- node.accessKind = RelationAccessKind.Error;
+ replacement ??= new InvalidPattern(
+ createMissingMethodInvocation(
+ node.fileOffset, node.matchedType, node.name,
+ isExpressionInvocation: false),
+ declaredVariables: node.declaredVariables);
break;
case ObjectAccessTargetKind.objectMember:
case ObjectAccessTargetKind.superMember:
@@ -10669,7 +10788,7 @@
break;
}
- pushRewrite(node);
+ pushRewrite(replacement ?? node);
assert(checkStack(node, stackBase, [
/* pattern = */ ValueKinds.Pattern,
@@ -10689,8 +10808,20 @@
: new MapPatternTypeArguments<DartType>(
keyType: node.keyType ?? const DynamicType(),
valueType: node.valueType ?? const DynamicType());
- DartType mapType = analyzeMapPattern(context, node,
- typeArguments: typeArguments, elements: node.entries);
+ MapPatternResult<DartType, InvalidExpression> analysisResult =
+ analyzeMapPattern(context, node,
+ typeArguments: typeArguments, elements: node.entries);
+
+ Pattern? replacement;
+
+ InvalidExpression? error =
+ analysisResult.patternTypeMismatchInIrrefutableContextError;
+ if (error != null) {
+ replacement =
+ new InvalidPattern(error, declaredVariables: node.declaredVariables);
+ }
+
+ DartType mapType = analysisResult.requiredType;
// TODO(johnniwinther): How does `mapType` relate to `node.mapType`?
DartType keyType = node.keyType ?? const DynamicType();
@@ -10766,6 +10897,15 @@
for (int i = node.entries.length - 1; i >= 0; i--) {
Object? rewrite = popRewrite();
+ InvalidExpression? error = analysisResult.duplicateRestPatternErrors?[i];
+ if (error != null) {
+ node.entries[i] = new MapPatternEntry(
+ new ConstantPattern(new NullLiteral()),
+ new InvalidPattern(error,
+ declaredVariables: node.entries[i].value.declaredVariables),
+ node.entries[i].fileOffset)
+ ..parent = node;
+ }
if (!identical(node.entries[i], rewrite)) {
node.entries[i] = (rewrite as MapPatternEntry)..parent = node;
}
@@ -10779,7 +10919,7 @@
}
}
- pushRewrite(node);
+ pushRewrite(replacement ?? node);
assert(checkStack(node, stackBase, [
/* pattern = */ ValueKinds.Pattern,
@@ -10815,12 +10955,24 @@
: fieldPattern,
name: fieldPattern is NamedPattern ? fieldPattern.name : null)
];
- DartType recordType = analyzeRecordPattern(context, node, fields: fields);
+ RecordPatternResult<DartType, InvalidExpression> analysisResult =
+ analyzeRecordPattern(context, node, fields: fields);
assert(checkStack(node, stackBase, [
/* fields = */ ...repeatedKind(ValueKinds.Pattern, node.patterns.length)
]));
+ Pattern? replacement;
+
+ InvalidExpression? error =
+ analysisResult.patternTypeMismatchInIrrefutableContextError ??
+ analysisResult.duplicateRecordPatternFieldErrors?.values.first;
+ if (error != null) {
+ replacement =
+ new InvalidPattern(error, declaredVariables: node.declaredVariables);
+ }
+
+ DartType recordType = analysisResult.requiredType;
node.type = recordType as RecordType;
// TODO(johnniwinther): How does `recordType` relate to `node.recordType`?
@@ -10853,7 +11005,7 @@
}
}
- pushRewrite(node);
+ pushRewrite(replacement ?? node);
assert(checkStack(node, stackBase, [
/* pattern = */ ValueKinds.Pattern,
@@ -10865,10 +11017,8 @@
int? stackBase;
assert(checkStackBase(node, stackBase = stackHeight));
- Expression expression = node.expression;
- Pattern pattern = node.pattern;
ExpressionTypeAnalysisResult<DartType> analysisResult =
- analyzePatternAssignment(node, pattern, expression);
+ analyzePatternAssignment(node, node.pattern, node.expression);
assert(checkStack(node, stackBase, [
/* pattern = */ ValueKinds.Pattern,
@@ -10876,8 +11026,8 @@
]));
Object? rewrite = popRewrite();
- if (!identical(pattern, rewrite)) {
- pattern = rewrite as Pattern;
+ if (!identical(node.pattern, rewrite)) {
+ node.pattern = rewrite as Pattern..parent = node;
}
assert(checkStack(node, stackBase, [
@@ -10885,8 +11035,8 @@
]));
rewrite = popRewrite();
- if (!identical(expression, rewrite)) {
- expression = rewrite as Expression;
+ if (!identical(node.expression, rewrite)) {
+ node.expression = rewrite as Expression..parent = node;
}
assert(checkStack(node, stackBase, [/*empty*/]));
@@ -10897,7 +11047,7 @@
// TODO(cstefantsova): Do we need a more precise type for the variable?
DartType matchedType = const DynamicType();
CacheableExpression matchedExpression =
- matchingCache.createRootExpression(expression, matchedType);
+ matchingCache.createRootExpression(node.expression, matchedType);
DelayedExpression matchingExpression =
matchingExpressionVisitor.visitPattern(node.pattern, matchedExpression);
@@ -10942,6 +11092,7 @@
matchedType: node.matchedType, requiredType: node.variable.type);
// TODO(johnniwinther): Share this through the type analyzer.
+ Pattern? replacement;
VariableDeclarationImpl variable = node.variable as VariableDeclarationImpl;
if (isNonNullableByDefault) {
bool isDefinitelyAssigned = flowAnalysis.isAssigned(variable);
@@ -10949,32 +11100,47 @@
if ((variable.isLate && variable.isFinal) ||
variable.isLateFinalWithoutInitializer) {
if (isDefinitelyAssigned) {
- node.error = helper.buildProblem(
- templateLateDefinitelyAssignedError
- .withArguments(node.variable.name!),
- node.fileOffset,
- node.variable.name!.length);
+ replacement = new InvalidPattern(
+ helper.buildProblem(
+ templateLateDefinitelyAssignedError
+ .withArguments(node.variable.name!),
+ node.fileOffset,
+ node.variable.name!.length),
+ declaredVariables: node.declaredVariables);
}
} else if (variable.isStaticLate) {
if (!isDefinitelyUnassigned) {
- node.error = helper.buildProblem(
- templateFinalPossiblyAssignedError
- .withArguments(node.variable.name!),
- node.fileOffset,
- node.variable.name!.length);
+ replacement = new InvalidPattern(
+ helper.buildProblem(
+ templateFinalPossiblyAssignedError
+ .withArguments(node.variable.name!),
+ node.fileOffset,
+ node.variable.name!.length),
+ declaredVariables: node.declaredVariables);
}
} else if (variable.isFinal && variable.hasDeclaredInitializer) {
- node.error = helper.buildProblem(
- templateCannotAssignToFinalVariable
- .withArguments(node.variable.name!),
- node.fileOffset,
- node.variable.name!.length);
+ replacement = new InvalidPattern(
+ helper.buildProblem(
+ templateCannotAssignToFinalVariable
+ .withArguments(node.variable.name!),
+ node.fileOffset,
+ node.variable.name!.length),
+ declaredVariables: node.declaredVariables);
}
}
- analyzeAssignedVariablePattern(context, node, node.variable);
+ AssignedVariablePatternResult<InvalidExpression> analysisResult =
+ analyzeAssignedVariablePattern(context, node, node.variable);
- pushRewrite(node);
+ InvalidExpression? error =
+ analysisResult.duplicateAssignmentPatternVariableError ??
+ analysisResult.patternTypeMismatchInIrrefutableContextError;
+ if (error != null) {
+ replacement ??=
+ new InvalidPattern(error, declaredVariables: node.declaredVariables);
+ }
+
+ pushRewrite(replacement ?? node);
assert(checkStack(node, stackBase, [
/* pattern = */ ValueKinds.Pattern,
diff --git a/pkg/front_end/lib/src/fasta/type_inference/inference_visitor_base.dart b/pkg/front_end/lib/src/fasta/type_inference/inference_visitor_base.dart
index 276552d..65cd26f 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/inference_visitor_base.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/inference_visitor_base.dart
@@ -2410,7 +2410,9 @@
// ignore: unnecessary_null_comparison
assert(isImplicitCall != null);
Expression error = createMissingMethodInvocation(
- fileOffset, receiver, receiverType, name, arguments,
+ fileOffset, receiverType, name,
+ receiver: receiver,
+ arguments: arguments,
isExpressionInvocation: isExpressionInvocation,
implicitInvocationPropertyName: implicitInvocationPropertyName,
extensionAccessCandidates:
@@ -3945,7 +3947,7 @@
int length,
DartType receiverType,
Name name,
- Expression wrappedExpression,
+ Expression? wrappedExpression,
List<ExtensionAccessCandidate>? extensionAccessCandidates,
Template<Message Function(String, DartType, bool)> missingTemplate,
Template<Message Function(String, DartType, bool)> ambiguousTemplate) {
@@ -3962,37 +3964,60 @@
.toList();
template = ambiguousTemplate;
}
- return helper.wrapInProblem(
- wrappedExpression,
- template.withArguments(name.text, resolveTypeParameter(receiverType),
- isNonNullableByDefault),
- fileOffset,
- length,
- context: context);
+ if (wrappedExpression != null) {
+ return helper.wrapInProblem(
+ wrappedExpression,
+ template.withArguments(name.text, resolveTypeParameter(receiverType),
+ isNonNullableByDefault),
+ fileOffset,
+ length,
+ context: context);
+ } else {
+ return helper.buildProblem(
+ template.withArguments(name.text, resolveTypeParameter(receiverType),
+ isNonNullableByDefault),
+ fileOffset,
+ length,
+ context: context);
+ }
}
- Expression createMissingMethodInvocation(int fileOffset, Expression receiver,
- DartType receiverType, Name name, Arguments arguments,
- {required bool isExpressionInvocation,
+ Expression createMissingMethodInvocation(
+ int fileOffset, DartType receiverType, Name name,
+ {Expression? receiver,
+ Arguments? arguments,
+ required bool isExpressionInvocation,
Name? implicitInvocationPropertyName,
List<ExtensionAccessCandidate>? extensionAccessCandidates}) {
// ignore: unnecessary_null_comparison
assert(isExpressionInvocation != null);
+ assert((receiver == null) == (arguments == null),
+ "Receiver and arguments must be supplied together.");
if (implicitInvocationPropertyName != null) {
assert(extensionAccessCandidates == null);
- return helper.wrapInProblem(
- _createInvalidInvocation(fileOffset, receiver, name, arguments),
- templateInvokeNonFunction
- .withArguments(implicitInvocationPropertyName.text),
- fileOffset,
- implicitInvocationPropertyName.text.length);
+ if (receiver != null) {
+ return helper.wrapInProblem(
+ _createInvalidInvocation(fileOffset, receiver, name, arguments!),
+ templateInvokeNonFunction
+ .withArguments(implicitInvocationPropertyName.text),
+ fileOffset,
+ implicitInvocationPropertyName.text.length);
+ } else {
+ return helper.buildProblem(
+ templateInvokeNonFunction
+ .withArguments(implicitInvocationPropertyName.text),
+ fileOffset,
+ implicitInvocationPropertyName.text.length);
+ }
} else {
return _reportMissingOrAmbiguousMember(
fileOffset,
isExpressionInvocation ? noLength : name.text.length,
receiverType,
name,
- _createInvalidInvocation(fileOffset, receiver, name, arguments),
+ receiver != null
+ ? _createInvalidInvocation(fileOffset, receiver, name, arguments!)
+ : null,
extensionAccessCandidates,
receiverType is ExtensionType
? templateUndefinedExtensionMethod
@@ -4021,12 +4046,12 @@
switch (readTarget.kind) {
case ObjectAccessTargetKind.missing:
- read = createMissingPropertyGet(
- fileOffset, receiver, receiverType, propertyName);
+ read = createMissingPropertyGet(fileOffset, receiverType, propertyName,
+ receiver: receiver);
break;
case ObjectAccessTargetKind.ambiguous:
- read = createMissingPropertyGet(
- fileOffset, receiver, receiverType, propertyName,
+ read = createMissingPropertyGet(fileOffset, receiverType, propertyName,
+ receiver: receiver,
extensionAccessCandidates: readTarget.candidates);
break;
case ObjectAccessTargetKind.extensionMember:
@@ -4184,9 +4209,10 @@
return new PropertyGetInferenceResult(readResult, readTarget.member);
}
- Expression createMissingPropertyGet(int fileOffset, Expression receiver,
- DartType receiverType, Name propertyName,
- {List<ExtensionAccessCandidate>? extensionAccessCandidates}) {
+ Expression createMissingPropertyGet(
+ int fileOffset, DartType receiverType, Name propertyName,
+ {Expression? receiver,
+ List<ExtensionAccessCandidate>? extensionAccessCandidates}) {
Template<Message Function(String, DartType, bool)> templateMissing;
if (receiverType is ExtensionType) {
templateMissing = templateUndefinedExtensionGetter;
@@ -4198,7 +4224,9 @@
propertyName.text.length,
receiverType,
propertyName,
- _createInvalidGet(fileOffset, receiver, propertyName),
+ receiver != null
+ ? _createInvalidGet(fileOffset, receiver, propertyName)
+ : null,
extensionAccessCandidates,
templateMissing,
templateAmbiguousExtensionProperty);
diff --git a/pkg/front_end/lib/src/fasta/type_inference/matching_expressions.dart b/pkg/front_end/lib/src/fasta/type_inference/matching_expressions.dart
index 86aa205..be89351 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/matching_expressions.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/matching_expressions.dart
@@ -19,9 +19,6 @@
DelayedExpression visitPattern(
Pattern node, CacheableExpression matchedExpression) {
- if (node.error != null) {
- return new FixedExpression(node.error!, const InvalidType());
- }
return node.acceptPattern1(this, matchedExpression);
}
@@ -459,7 +456,9 @@
fileOffset: field.fileOffset);
break;
case ObjectAccessKind.Error:
- expression = new FixedExpression(field.error!, const InvalidType());
+ expression = new FixedExpression(
+ (field.pattern as InvalidPattern).invalidExpression,
+ const InvalidType());
break;
}
CacheableExpression objectExpression =
@@ -622,9 +621,6 @@
const InvalidType(),
fileOffset: node.fileOffset);
break;
- case RelationAccessKind.Error:
- expression = new FixedExpression(node.error!, const InvalidType());
- break;
}
return matchingCache.createComparisonExpression(
matchedExpression, node.name.text, constant, expression,
diff --git a/pkg/front_end/lib/src/fasta/type_inference/shared_type_analyzer.dart b/pkg/front_end/lib/src/fasta/type_inference/shared_type_analyzer.dart
index e86f8ce..c6a523f 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/shared_type_analyzer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/shared_type_analyzer.dart
@@ -19,7 +19,7 @@
class SharedTypeAnalyzerErrors
implements
TypeAnalyzerErrors<TreeNode, Statement, Expression, VariableDeclaration,
- DartType, Pattern> {
+ DartType, Pattern, InvalidExpression> {
final InferenceVisitorImpl visitor;
final InferenceHelper helper;
@@ -37,12 +37,12 @@
required this.isNonNullableByDefault});
@override
- void argumentTypeNotAssignable({
+ InvalidExpression argumentTypeNotAssignable({
required Expression argument,
required DartType argumentType,
required DartType parameterType,
}) {
- helper.addProblem(
+ return helper.buildProblem(
templateArgumentTypeNotAssignable.withArguments(
argumentType, parameterType, isNonNullableByDefault),
argument.fileOffset,
@@ -55,13 +55,13 @@
}
@override
- void caseExpressionTypeMismatch(
+ InvalidExpression caseExpressionTypeMismatch(
{required Expression scrutinee,
required Expression caseExpression,
required DartType caseExpressionType,
required DartType scrutineeType,
required bool nullSafetyEnabled}) {
- helper.addProblem(
+ return helper.buildProblem(
nullSafetyEnabled
? templateSwitchExpressionNotSubtype.withArguments(
caseExpressionType, scrutineeType, nullSafetyEnabled)
@@ -76,12 +76,12 @@
}
@override
- void duplicateAssignmentPatternVariable({
+ InvalidExpression duplicateAssignmentPatternVariable({
required VariableDeclaration variable,
required Pattern original,
required Pattern duplicate,
}) {
- duplicate.error = helper.buildProblem(
+ return helper.buildProblem(
templateDuplicatePatternAssignmentVariable
.withArguments(variable.name!),
duplicate.fileOffset,
@@ -93,13 +93,13 @@
}
@override
- void duplicateRecordPatternField({
+ InvalidExpression duplicateRecordPatternField({
required Pattern objectOrRecordPattern,
required String name,
required RecordPatternField<TreeNode, Pattern> original,
required RecordPatternField<TreeNode, Pattern> duplicate,
}) {
- objectOrRecordPattern.error = helper.buildProblem(
+ return helper.buildProblem(
templateDuplicateRecordPatternField.withArguments(name),
duplicate.pattern.fileOffset,
noLength,
@@ -110,12 +110,12 @@
}
@override
- void duplicateRestPattern({
+ InvalidExpression duplicateRestPattern({
required Pattern mapOrListPattern,
required TreeNode original,
required TreeNode duplicate,
}) {
- mapOrListPattern.error = helper.buildProblem(
+ return helper.buildProblem(
messageDuplicateRestElementInPattern, duplicate.fileOffset, noLength,
context: [
messageDuplicateRestElementInPatternContext.withLocation(
@@ -130,19 +130,21 @@
}) {
// TODO(cstefantsova): Currently this error is reported elsewhere due to
// the order the types are inferred.
+ // TODO(johnniwinther): How should we handle errors that are not report
+ // here? Should we have a sentinel error node, allow a nullable result, or ?
}
@override
- void matchedTypeIsStrictlyNonNullable({
+ InvalidExpression matchedTypeIsStrictlyNonNullable({
required Pattern pattern,
required DartType matchedType,
}) {
// These are only warnings, so we don't update `pattern.error`.
if (pattern is NullAssertPattern) {
- helper.addProblem(
+ return helper.buildProblem(
messageUnnecessaryNullAssertPattern, pattern.fileOffset, noLength);
} else {
- helper.addProblem(
+ return helper.buildProblem(
messageUnnecessaryNullCheckPattern, pattern.fileOffset, noLength);
}
}
@@ -157,10 +159,9 @@
}
@override
- void nonBooleanCondition({required Expression node}) {
- // TODO(johnniwinther): Find a way to propagate the error state to the
- // parent of the guard.
- helper.addProblem(messageNonBoolCondition, node.fileOffset, noLength);
+ InvalidExpression nonBooleanCondition({required Expression node}) {
+ return helper.buildProblem(
+ messageNonBoolCondition, node.fileOffset, noLength);
}
@override
@@ -170,7 +171,7 @@
}
@override
- void nonExhaustiveSwitch(
+ InvalidExpression nonExhaustiveSwitch(
{required TreeNode node, required DartType scrutineeType}) {
// Report the error on the scrutinee expression, to match what the full
// exhaustiveness algorithm does
@@ -180,7 +181,7 @@
} else {
fileOffset = (node as SwitchExpression).expression.fileOffset;
}
- helper.addProblem(
+ return helper.buildProblem(
templateNonExhaustiveSwitch.withArguments(scrutineeType,
scrutineeType.toText(textStrategy), isNonNullableByDefault),
fileOffset,
@@ -188,7 +189,7 @@
}
@override
- void patternForInExpressionIsNotIterable({
+ InvalidExpression patternForInExpressionIsNotIterable({
required TreeNode node,
required Expression expression,
required DartType expressionType,
@@ -197,12 +198,12 @@
}
@override
- void patternTypeMismatchInIrrefutableContext(
+ InvalidExpression patternTypeMismatchInIrrefutableContext(
{required Pattern pattern,
required TreeNode context,
required DartType matchedType,
required DartType requiredType}) {
- pattern.error = helper.buildProblem(
+ return helper.buildProblem(
templatePatternTypeMismatchInIrrefutableContext.withArguments(
matchedType, requiredType, isNonNullableByDefault),
pattern.fileOffset,
@@ -210,20 +211,18 @@
}
@override
- void refutablePatternInIrrefutableContext(
+ InvalidExpression refutablePatternInIrrefutableContext(
{required covariant Pattern pattern, required TreeNode context}) {
- pattern.error = helper.buildProblem(
- messageRefutablePatternInIrrefutableContext,
- pattern.fileOffset,
- noLength);
+ return helper.buildProblem(messageRefutablePatternInIrrefutableContext,
+ pattern.fileOffset, noLength);
}
@override
- void relationalPatternOperatorReturnTypeNotAssignableToBool({
+ InvalidExpression relationalPatternOperatorReturnTypeNotAssignableToBool({
required Pattern pattern,
required DartType returnType,
}) {
- pattern.error = helper.buildProblem(
+ return helper.buildProblem(
templateInvalidAssignmentError.withArguments(returnType,
coreTypes.boolNonNullableRawType, isNonNullableByDefault),
pattern.fileOffset,
@@ -243,9 +242,9 @@
}
@override
- void switchCaseCompletesNormally(
+ InvalidExpression switchCaseCompletesNormally(
{required covariant SwitchStatement node, required int caseIndex}) {
- helper.addProblem(messageSwitchCaseFallThrough,
+ return helper.buildProblem(messageSwitchCaseFallThrough,
node.cases[caseIndex].fileOffset, noLength);
}
diff --git a/pkg/front_end/testcases/class_modifiers/subtype_function.dart.strong.expect b/pkg/front_end/testcases/class_modifiers/subtype_function.dart.strong.expect
index c7953d7..6cfad95 100644
--- a/pkg/front_end/testcases/class_modifiers/subtype_function.dart.strong.expect
+++ b/pkg/front_end/testcases/class_modifiers/subtype_function.dart.strong.expect
@@ -2,10 +2,37 @@
//
// Problems in library:
//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:5:7: Error: The type 'A' must be 'base', 'final' or 'sealed' because the supertype 'Function' is 'final'.
+// Try adding 'base', 'final', or 'sealed' to the type.
+// class A extends Function {}
+// ^
+//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:5:17: Error: The class 'Function' can't be extended outside of its library because it's a final class.
+// class A extends Function {}
+// ^
+//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:7:7: Error: The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'Function' is 'final'.
+// Try adding 'base', 'final', or 'sealed' to the type.
+// class B implements Function {}
+// ^
+//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:7:20: Error: The class 'Function' can't be implemented outside of its library because it's a final class.
+// class B implements Function {}
+// ^
+//
// pkg/front_end/testcases/class_modifiers/subtype_function.dart:9:14: Error: The class 'Function' can't be used as a mixin because it isn't a mixin class nor a mixin.
// class C with Function {}
// ^
//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:9:14: Error: The mixin 'Function' can't be mixed-in outside of its library because it's a final mixin.
+// class C with Function {}
+// ^
+//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:9:7: Error: The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'Function' is 'final'.
+// Try adding 'base', 'final', or 'sealed' to the type.
+// class C with Function {}
+// ^
+//
// pkg/front_end/testcases/class_modifiers/subtype_function.dart:5:7: Error: Extending 'Function' is deprecated because 'Function' is final class.
// Try removing 'Function' from the 'extends' clause.
// class A extends Function {}
diff --git a/pkg/front_end/testcases/class_modifiers/subtype_function.dart.strong.transformed.expect b/pkg/front_end/testcases/class_modifiers/subtype_function.dart.strong.transformed.expect
index c7953d7..6cfad95 100644
--- a/pkg/front_end/testcases/class_modifiers/subtype_function.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/class_modifiers/subtype_function.dart.strong.transformed.expect
@@ -2,10 +2,37 @@
//
// Problems in library:
//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:5:7: Error: The type 'A' must be 'base', 'final' or 'sealed' because the supertype 'Function' is 'final'.
+// Try adding 'base', 'final', or 'sealed' to the type.
+// class A extends Function {}
+// ^
+//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:5:17: Error: The class 'Function' can't be extended outside of its library because it's a final class.
+// class A extends Function {}
+// ^
+//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:7:7: Error: The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'Function' is 'final'.
+// Try adding 'base', 'final', or 'sealed' to the type.
+// class B implements Function {}
+// ^
+//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:7:20: Error: The class 'Function' can't be implemented outside of its library because it's a final class.
+// class B implements Function {}
+// ^
+//
// pkg/front_end/testcases/class_modifiers/subtype_function.dart:9:14: Error: The class 'Function' can't be used as a mixin because it isn't a mixin class nor a mixin.
// class C with Function {}
// ^
//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:9:14: Error: The mixin 'Function' can't be mixed-in outside of its library because it's a final mixin.
+// class C with Function {}
+// ^
+//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:9:7: Error: The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'Function' is 'final'.
+// Try adding 'base', 'final', or 'sealed' to the type.
+// class C with Function {}
+// ^
+//
// pkg/front_end/testcases/class_modifiers/subtype_function.dart:5:7: Error: Extending 'Function' is deprecated because 'Function' is final class.
// Try removing 'Function' from the 'extends' clause.
// class A extends Function {}
diff --git a/pkg/front_end/testcases/class_modifiers/subtype_function.dart.weak.expect b/pkg/front_end/testcases/class_modifiers/subtype_function.dart.weak.expect
index c7953d7..6cfad95 100644
--- a/pkg/front_end/testcases/class_modifiers/subtype_function.dart.weak.expect
+++ b/pkg/front_end/testcases/class_modifiers/subtype_function.dart.weak.expect
@@ -2,10 +2,37 @@
//
// Problems in library:
//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:5:7: Error: The type 'A' must be 'base', 'final' or 'sealed' because the supertype 'Function' is 'final'.
+// Try adding 'base', 'final', or 'sealed' to the type.
+// class A extends Function {}
+// ^
+//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:5:17: Error: The class 'Function' can't be extended outside of its library because it's a final class.
+// class A extends Function {}
+// ^
+//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:7:7: Error: The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'Function' is 'final'.
+// Try adding 'base', 'final', or 'sealed' to the type.
+// class B implements Function {}
+// ^
+//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:7:20: Error: The class 'Function' can't be implemented outside of its library because it's a final class.
+// class B implements Function {}
+// ^
+//
// pkg/front_end/testcases/class_modifiers/subtype_function.dart:9:14: Error: The class 'Function' can't be used as a mixin because it isn't a mixin class nor a mixin.
// class C with Function {}
// ^
//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:9:14: Error: The mixin 'Function' can't be mixed-in outside of its library because it's a final mixin.
+// class C with Function {}
+// ^
+//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:9:7: Error: The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'Function' is 'final'.
+// Try adding 'base', 'final', or 'sealed' to the type.
+// class C with Function {}
+// ^
+//
// pkg/front_end/testcases/class_modifiers/subtype_function.dart:5:7: Error: Extending 'Function' is deprecated because 'Function' is final class.
// Try removing 'Function' from the 'extends' clause.
// class A extends Function {}
diff --git a/pkg/front_end/testcases/class_modifiers/subtype_function.dart.weak.modular.expect b/pkg/front_end/testcases/class_modifiers/subtype_function.dart.weak.modular.expect
index c7953d7..6cfad95 100644
--- a/pkg/front_end/testcases/class_modifiers/subtype_function.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/class_modifiers/subtype_function.dart.weak.modular.expect
@@ -2,10 +2,37 @@
//
// Problems in library:
//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:5:7: Error: The type 'A' must be 'base', 'final' or 'sealed' because the supertype 'Function' is 'final'.
+// Try adding 'base', 'final', or 'sealed' to the type.
+// class A extends Function {}
+// ^
+//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:5:17: Error: The class 'Function' can't be extended outside of its library because it's a final class.
+// class A extends Function {}
+// ^
+//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:7:7: Error: The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'Function' is 'final'.
+// Try adding 'base', 'final', or 'sealed' to the type.
+// class B implements Function {}
+// ^
+//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:7:20: Error: The class 'Function' can't be implemented outside of its library because it's a final class.
+// class B implements Function {}
+// ^
+//
// pkg/front_end/testcases/class_modifiers/subtype_function.dart:9:14: Error: The class 'Function' can't be used as a mixin because it isn't a mixin class nor a mixin.
// class C with Function {}
// ^
//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:9:14: Error: The mixin 'Function' can't be mixed-in outside of its library because it's a final mixin.
+// class C with Function {}
+// ^
+//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:9:7: Error: The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'Function' is 'final'.
+// Try adding 'base', 'final', or 'sealed' to the type.
+// class C with Function {}
+// ^
+//
// pkg/front_end/testcases/class_modifiers/subtype_function.dart:5:7: Error: Extending 'Function' is deprecated because 'Function' is final class.
// Try removing 'Function' from the 'extends' clause.
// class A extends Function {}
diff --git a/pkg/front_end/testcases/class_modifiers/subtype_function.dart.weak.outline.expect b/pkg/front_end/testcases/class_modifiers/subtype_function.dart.weak.outline.expect
index e4913a1..94939a4 100644
--- a/pkg/front_end/testcases/class_modifiers/subtype_function.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/class_modifiers/subtype_function.dart.weak.outline.expect
@@ -2,10 +2,37 @@
//
// Problems in library:
//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:5:7: Error: The type 'A' must be 'base', 'final' or 'sealed' because the supertype 'Function' is 'final'.
+// Try adding 'base', 'final', or 'sealed' to the type.
+// class A extends Function {}
+// ^
+//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:5:17: Error: The class 'Function' can't be extended outside of its library because it's a final class.
+// class A extends Function {}
+// ^
+//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:7:7: Error: The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'Function' is 'final'.
+// Try adding 'base', 'final', or 'sealed' to the type.
+// class B implements Function {}
+// ^
+//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:7:20: Error: The class 'Function' can't be implemented outside of its library because it's a final class.
+// class B implements Function {}
+// ^
+//
// pkg/front_end/testcases/class_modifiers/subtype_function.dart:9:14: Error: The class 'Function' can't be used as a mixin because it isn't a mixin class nor a mixin.
// class C with Function {}
// ^
//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:9:14: Error: The mixin 'Function' can't be mixed-in outside of its library because it's a final mixin.
+// class C with Function {}
+// ^
+//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:9:7: Error: The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'Function' is 'final'.
+// Try adding 'base', 'final', or 'sealed' to the type.
+// class C with Function {}
+// ^
+//
// pkg/front_end/testcases/class_modifiers/subtype_function.dart:5:7: Error: Extending 'Function' is deprecated because 'Function' is final class.
// Try removing 'Function' from the 'extends' clause.
// class A extends Function {}
diff --git a/pkg/front_end/testcases/class_modifiers/subtype_function.dart.weak.transformed.expect b/pkg/front_end/testcases/class_modifiers/subtype_function.dart.weak.transformed.expect
index c7953d7..6cfad95 100644
--- a/pkg/front_end/testcases/class_modifiers/subtype_function.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/class_modifiers/subtype_function.dart.weak.transformed.expect
@@ -2,10 +2,37 @@
//
// Problems in library:
//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:5:7: Error: The type 'A' must be 'base', 'final' or 'sealed' because the supertype 'Function' is 'final'.
+// Try adding 'base', 'final', or 'sealed' to the type.
+// class A extends Function {}
+// ^
+//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:5:17: Error: The class 'Function' can't be extended outside of its library because it's a final class.
+// class A extends Function {}
+// ^
+//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:7:7: Error: The type 'B' must be 'base', 'final' or 'sealed' because the supertype 'Function' is 'final'.
+// Try adding 'base', 'final', or 'sealed' to the type.
+// class B implements Function {}
+// ^
+//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:7:20: Error: The class 'Function' can't be implemented outside of its library because it's a final class.
+// class B implements Function {}
+// ^
+//
// pkg/front_end/testcases/class_modifiers/subtype_function.dart:9:14: Error: The class 'Function' can't be used as a mixin because it isn't a mixin class nor a mixin.
// class C with Function {}
// ^
//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:9:14: Error: The mixin 'Function' can't be mixed-in outside of its library because it's a final mixin.
+// class C with Function {}
+// ^
+//
+// pkg/front_end/testcases/class_modifiers/subtype_function.dart:9:7: Error: The type 'C' must be 'base', 'final' or 'sealed' because the supertype 'Function' is 'final'.
+// Try adding 'base', 'final', or 'sealed' to the type.
+// class C with Function {}
+// ^
+//
// pkg/front_end/testcases/class_modifiers/subtype_function.dart:5:7: Error: Extending 'Function' is deprecated because 'Function' is final class.
// Try removing 'Function' from the 'extends' clause.
// class A extends Function {}
diff --git a/pkg/front_end/testcases/modular.status b/pkg/front_end/testcases/modular.status
index 4211ebc..36480fe 100644
--- a/pkg/front_end/testcases/modular.status
+++ b/pkg/front_end/testcases/modular.status
@@ -85,5 +85,4 @@
nnbd_mixed/messages_with_types_opt_out: TypeCheckError
no_such_method_forwarders/mixin_nsm: TypeCheckError
patterns/pattern_types: TypeCheckError
-patterns/shared_errors: TypeCheckError
runtime_checks_new/mixin_forwarding_stub_getter: TypeCheckError
diff --git a/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart b/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart
new file mode 100644
index 0000000..3d6741b
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2023, 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.
+
+method() {
+ var ([double v1] && [num v2]) = [42];
+ print(v1);
+ print(v2);
+}
diff --git a/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart.strong.expect b/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart.strong.expect
new file mode 100644
index 0000000..22c9007
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart.strong.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static method method() → dynamic {
+ core::double v1;
+ core::num v2;
+ {
+ final dynamic #0#0 = <core::double>[42.0];
+ late final core::bool #0#3 = #0#0{core::List<core::double>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1;
+ late final core::double #0#4 = #0#0{core::List<core::double>}.{core::List::[]}(0){(core::int) → core::double};
+ if(!(#0#3 && (#0#4 is{ForNonNullableByDefault} core::double && (let final dynamic #t1 = v1 = #0#4 in true)) && (#0#3 && (#0#4 is{ForNonNullableByDefault} core::num && (let final dynamic #t2 = v2 = #0#4 in true)))))
+ throw new _in::ReachabilityError::•();
+ }
+ core::print(v1);
+ core::print(v2);
+}
+
+constants {
+ #C1 = 1
+}
diff --git a/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart.strong.transformed.expect b/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart.strong.transformed.expect
new file mode 100644
index 0000000..05d0615
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart.strong.transformed.expect
@@ -0,0 +1,26 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static method method() → dynamic {
+ core::double v1;
+ core::num v2;
+ {
+ final dynamic #0#0 = core::_GrowableList::_literal1<core::double>(42.0);
+ function ##0#3#initializer() → core::bool
+ return #0#0{core::List<core::double>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1;
+ late final core::bool #0#3 = ##0#3#initializer(){() → core::bool};
+ function ##0#4#initializer() → core::double
+ return #0#0{core::List<core::double>}.{core::List::[]}(0){(core::int) → core::double};
+ late final core::double #0#4 = ##0#4#initializer(){() → core::double};
+ if(!(#0#3 && (#0#4 is{ForNonNullableByDefault} core::double && (let final core::double #t1 = v1 = #0#4 in true)) && (#0#3 && (#0#4 is{ForNonNullableByDefault} core::num && (let final core::double #t2 = v2 = #0#4 in true)))))
+ throw new _in::ReachabilityError::•();
+ }
+ core::print(v1);
+ core::print(v2);
+}
+
+constants {
+ #C1 = 1
+}
diff --git a/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart.textual_outline.expect b/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart.textual_outline.expect
new file mode 100644
index 0000000..83d2302
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart.textual_outline.expect
@@ -0,0 +1 @@
+method() {}
diff --git a/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..83d2302
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart.textual_outline_modelled.expect
@@ -0,0 +1 @@
+method() {}
diff --git a/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart.weak.expect b/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart.weak.expect
new file mode 100644
index 0000000..22c9007
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart.weak.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static method method() → dynamic {
+ core::double v1;
+ core::num v2;
+ {
+ final dynamic #0#0 = <core::double>[42.0];
+ late final core::bool #0#3 = #0#0{core::List<core::double>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1;
+ late final core::double #0#4 = #0#0{core::List<core::double>}.{core::List::[]}(0){(core::int) → core::double};
+ if(!(#0#3 && (#0#4 is{ForNonNullableByDefault} core::double && (let final dynamic #t1 = v1 = #0#4 in true)) && (#0#3 && (#0#4 is{ForNonNullableByDefault} core::num && (let final dynamic #t2 = v2 = #0#4 in true)))))
+ throw new _in::ReachabilityError::•();
+ }
+ core::print(v1);
+ core::print(v2);
+}
+
+constants {
+ #C1 = 1
+}
diff --git a/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart.weak.modular.expect b/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart.weak.modular.expect
new file mode 100644
index 0000000..22c9007
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart.weak.modular.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static method method() → dynamic {
+ core::double v1;
+ core::num v2;
+ {
+ final dynamic #0#0 = <core::double>[42.0];
+ late final core::bool #0#3 = #0#0{core::List<core::double>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1;
+ late final core::double #0#4 = #0#0{core::List<core::double>}.{core::List::[]}(0){(core::int) → core::double};
+ if(!(#0#3 && (#0#4 is{ForNonNullableByDefault} core::double && (let final dynamic #t1 = v1 = #0#4 in true)) && (#0#3 && (#0#4 is{ForNonNullableByDefault} core::num && (let final dynamic #t2 = v2 = #0#4 in true)))))
+ throw new _in::ReachabilityError::•();
+ }
+ core::print(v1);
+ core::print(v2);
+}
+
+constants {
+ #C1 = 1
+}
diff --git a/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart.weak.outline.expect b/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart.weak.outline.expect
new file mode 100644
index 0000000..befb402
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart.weak.outline.expect
@@ -0,0 +1,5 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+static method method() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart.weak.transformed.expect b/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart.weak.transformed.expect
new file mode 100644
index 0000000..05d0615
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/invalid_pattern_declares_variables.dart.weak.transformed.expect
@@ -0,0 +1,26 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static method method() → dynamic {
+ core::double v1;
+ core::num v2;
+ {
+ final dynamic #0#0 = core::_GrowableList::_literal1<core::double>(42.0);
+ function ##0#3#initializer() → core::bool
+ return #0#0{core::List<core::double>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1;
+ late final core::bool #0#3 = ##0#3#initializer(){() → core::bool};
+ function ##0#4#initializer() → core::double
+ return #0#0{core::List<core::double>}.{core::List::[]}(0){(core::int) → core::double};
+ late final core::double #0#4 = ##0#4#initializer(){() → core::double};
+ if(!(#0#3 && (#0#4 is{ForNonNullableByDefault} core::double && (let final core::double #t1 = v1 = #0#4 in true)) && (#0#3 && (#0#4 is{ForNonNullableByDefault} core::num && (let final core::double #t2 = v2 = #0#4 in true)))))
+ throw new _in::ReachabilityError::•();
+ }
+ core::print(v1);
+ core::print(v2);
+}
+
+constants {
+ #C1 = 1
+}
diff --git a/pkg/front_end/testcases/patterns/non_bool_guard.dart b/pkg/front_end/testcases/patterns/non_bool_guard.dart
new file mode 100644
index 0000000..a1edb72
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/non_bool_guard.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2023, 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.
+
+String test1(List<int> v) {
+ switch (v) {
+ case [var a, _] when a - 1:
+ return "match";
+ default:
+ return "no match";
+ }
+}
+
+String test2(List<int> v) {
+ if (v case [var a, _] when a - 1) {
+ return "match";
+ }
+ return "no match";
+}
+
+String test3(List<int> v) =>
+ switch (v) {
+ [var a, _] when a - 1 => "match",
+ _ => "no match"
+ };
diff --git a/pkg/front_end/testcases/patterns/non_bool_guard.dart.strong.expect b/pkg/front_end/testcases/patterns/non_bool_guard.dart.strong.expect
new file mode 100644
index 0000000..c6f1884
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/non_bool_guard.dart.strong.expect
@@ -0,0 +1,73 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/patterns/non_bool_guard.dart:7:28: Error: Conditions must have a static type of 'bool'.
+// Try changing the condition.
+// case [var a, _] when a - 1:
+// ^
+//
+// pkg/front_end/testcases/patterns/non_bool_guard.dart:15:32: Error: Conditions must have a static type of 'bool'.
+// Try changing the condition.
+// if (v case [var a, _] when a - 1) {
+// ^
+//
+// pkg/front_end/testcases/patterns/non_bool_guard.dart:23:23: Error: Conditions must have a static type of 'bool'.
+// Try changing the condition.
+// [var a, _] when a - 1 => "match",
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+static method test1(core::List<core::int> v) → core::String {
+ #L1:
+ {
+ core::int a;
+ final core::List<core::int> #0#0 = v;
+ if(#0#0.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final dynamic #t1 = a = #0#0.{core::List::[]}(0){(core::int) → core::int} in true) && (let final dynamic #t2 = #0#0.{core::List::[]}(1){(core::int) → core::int} in true) && invalid-expression "pkg/front_end/testcases/patterns/non_bool_guard.dart:7:28: Error: Conditions must have a static type of 'bool'.
+Try changing the condition.
+ case [var a, _] when a - 1:
+ ^") {
+ {
+ return "match";
+ }
+ }
+ else {
+ {
+ return "no match";
+ }
+ }
+ }
+}
+static method test2(core::List<core::int> v) → core::String {
+ {
+ core::int a;
+ final core::List<core::int> #0#0 = v;
+ if(#0#0.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final dynamic #t3 = a = #0#0.{core::List::[]}(0){(core::int) → core::int} in true) && (let final dynamic #t4 = #0#0.{core::List::[]}(1){(core::int) → core::int} in true) && invalid-expression "pkg/front_end/testcases/patterns/non_bool_guard.dart:15:32: Error: Conditions must have a static type of 'bool'.
+Try changing the condition.
+ if (v case [var a, _] when a - 1) {
+ ^") {
+ return "match";
+ }
+ }
+ return "no match";
+}
+static method test3(core::List<core::int> v) → core::String
+ return block {
+ core::String #t5;
+ core::int a;
+ final core::List<core::int> #0#0 = v;
+ if(#0#0.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final dynamic #t6 = a = #0#0.{core::List::[]}(0){(core::int) → core::int} in true) && (let final dynamic #t7 = #0#0.{core::List::[]}(1){(core::int) → core::int} in true) && invalid-expression "pkg/front_end/testcases/patterns/non_bool_guard.dart:23:23: Error: Conditions must have a static type of 'bool'.
+Try changing the condition.
+ [var a, _] when a - 1 => \"match\",
+ ^")
+ #t5 = "match";
+ else
+ if(true)
+ #t5 = "no match";
+ } =>#t5;
+
+constants {
+ #C1 = 2
+}
diff --git a/pkg/front_end/testcases/patterns/non_bool_guard.dart.strong.transformed.expect b/pkg/front_end/testcases/patterns/non_bool_guard.dart.strong.transformed.expect
new file mode 100644
index 0000000..3b921f5
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/non_bool_guard.dart.strong.transformed.expect
@@ -0,0 +1,73 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/patterns/non_bool_guard.dart:7:28: Error: Conditions must have a static type of 'bool'.
+// Try changing the condition.
+// case [var a, _] when a - 1:
+// ^
+//
+// pkg/front_end/testcases/patterns/non_bool_guard.dart:15:32: Error: Conditions must have a static type of 'bool'.
+// Try changing the condition.
+// if (v case [var a, _] when a - 1) {
+// ^
+//
+// pkg/front_end/testcases/patterns/non_bool_guard.dart:23:23: Error: Conditions must have a static type of 'bool'.
+// Try changing the condition.
+// [var a, _] when a - 1 => "match",
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+static method test1(core::List<core::int> v) → core::String {
+ #L1:
+ {
+ core::int a;
+ final core::List<core::int> #0#0 = v;
+ if(#0#0.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final core::int #t1 = a = #0#0.{core::List::[]}(0){(core::int) → core::int} in true) && (let final core::int #t2 = #0#0.{core::List::[]}(1){(core::int) → core::int} in true) && invalid-expression "pkg/front_end/testcases/patterns/non_bool_guard.dart:7:28: Error: Conditions must have a static type of 'bool'.
+Try changing the condition.
+ case [var a, _] when a - 1:
+ ^") {
+ {
+ return "match";
+ }
+ }
+ else {
+ {
+ return "no match";
+ }
+ }
+ }
+}
+static method test2(core::List<core::int> v) → core::String {
+ {
+ core::int a;
+ final core::List<core::int> #0#0 = v;
+ if(#0#0.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final core::int #t3 = a = #0#0.{core::List::[]}(0){(core::int) → core::int} in true) && (let final core::int #t4 = #0#0.{core::List::[]}(1){(core::int) → core::int} in true) && invalid-expression "pkg/front_end/testcases/patterns/non_bool_guard.dart:15:32: Error: Conditions must have a static type of 'bool'.
+Try changing the condition.
+ if (v case [var a, _] when a - 1) {
+ ^") {
+ return "match";
+ }
+ }
+ return "no match";
+}
+static method test3(core::List<core::int> v) → core::String
+ return block {
+ core::String #t5;
+ core::int a;
+ final core::List<core::int> #0#0 = v;
+ if(#0#0.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final core::int #t6 = a = #0#0.{core::List::[]}(0){(core::int) → core::int} in true) && (let final core::int #t7 = #0#0.{core::List::[]}(1){(core::int) → core::int} in true) && invalid-expression "pkg/front_end/testcases/patterns/non_bool_guard.dart:23:23: Error: Conditions must have a static type of 'bool'.
+Try changing the condition.
+ [var a, _] when a - 1 => \"match\",
+ ^")
+ #t5 = "match";
+ else
+ if(true)
+ #t5 = "no match";
+ } =>#t5;
+
+constants {
+ #C1 = 2
+}
diff --git a/pkg/front_end/testcases/patterns/non_bool_guard.dart.textual_outline.expect b/pkg/front_end/testcases/patterns/non_bool_guard.dart.textual_outline.expect
new file mode 100644
index 0000000..e4559d3
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/non_bool_guard.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+String test1(List<int> v) {}
+String test2(List<int> v) {}
+String test3(List<int> v) => switch (v) { };
diff --git a/pkg/front_end/testcases/patterns/non_bool_guard.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/patterns/non_bool_guard.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..c4d75c0
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/non_bool_guard.dart.textual_outline_modelled.expect
@@ -0,0 +1,7 @@
+String test1(List<int> v) {}
+String test2(List<int> v) {}
+String test3(List<int> v) =>
+switch (v) {}
+---- unknown chunk starts ----
+;
+---- unknown chunk ends ----
diff --git a/pkg/front_end/testcases/patterns/non_bool_guard.dart.weak.expect b/pkg/front_end/testcases/patterns/non_bool_guard.dart.weak.expect
new file mode 100644
index 0000000..c6f1884
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/non_bool_guard.dart.weak.expect
@@ -0,0 +1,73 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/patterns/non_bool_guard.dart:7:28: Error: Conditions must have a static type of 'bool'.
+// Try changing the condition.
+// case [var a, _] when a - 1:
+// ^
+//
+// pkg/front_end/testcases/patterns/non_bool_guard.dart:15:32: Error: Conditions must have a static type of 'bool'.
+// Try changing the condition.
+// if (v case [var a, _] when a - 1) {
+// ^
+//
+// pkg/front_end/testcases/patterns/non_bool_guard.dart:23:23: Error: Conditions must have a static type of 'bool'.
+// Try changing the condition.
+// [var a, _] when a - 1 => "match",
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+static method test1(core::List<core::int> v) → core::String {
+ #L1:
+ {
+ core::int a;
+ final core::List<core::int> #0#0 = v;
+ if(#0#0.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final dynamic #t1 = a = #0#0.{core::List::[]}(0){(core::int) → core::int} in true) && (let final dynamic #t2 = #0#0.{core::List::[]}(1){(core::int) → core::int} in true) && invalid-expression "pkg/front_end/testcases/patterns/non_bool_guard.dart:7:28: Error: Conditions must have a static type of 'bool'.
+Try changing the condition.
+ case [var a, _] when a - 1:
+ ^") {
+ {
+ return "match";
+ }
+ }
+ else {
+ {
+ return "no match";
+ }
+ }
+ }
+}
+static method test2(core::List<core::int> v) → core::String {
+ {
+ core::int a;
+ final core::List<core::int> #0#0 = v;
+ if(#0#0.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final dynamic #t3 = a = #0#0.{core::List::[]}(0){(core::int) → core::int} in true) && (let final dynamic #t4 = #0#0.{core::List::[]}(1){(core::int) → core::int} in true) && invalid-expression "pkg/front_end/testcases/patterns/non_bool_guard.dart:15:32: Error: Conditions must have a static type of 'bool'.
+Try changing the condition.
+ if (v case [var a, _] when a - 1) {
+ ^") {
+ return "match";
+ }
+ }
+ return "no match";
+}
+static method test3(core::List<core::int> v) → core::String
+ return block {
+ core::String #t5;
+ core::int a;
+ final core::List<core::int> #0#0 = v;
+ if(#0#0.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final dynamic #t6 = a = #0#0.{core::List::[]}(0){(core::int) → core::int} in true) && (let final dynamic #t7 = #0#0.{core::List::[]}(1){(core::int) → core::int} in true) && invalid-expression "pkg/front_end/testcases/patterns/non_bool_guard.dart:23:23: Error: Conditions must have a static type of 'bool'.
+Try changing the condition.
+ [var a, _] when a - 1 => \"match\",
+ ^")
+ #t5 = "match";
+ else
+ if(true)
+ #t5 = "no match";
+ } =>#t5;
+
+constants {
+ #C1 = 2
+}
diff --git a/pkg/front_end/testcases/patterns/non_bool_guard.dart.weak.modular.expect b/pkg/front_end/testcases/patterns/non_bool_guard.dart.weak.modular.expect
new file mode 100644
index 0000000..c6f1884
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/non_bool_guard.dart.weak.modular.expect
@@ -0,0 +1,73 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/patterns/non_bool_guard.dart:7:28: Error: Conditions must have a static type of 'bool'.
+// Try changing the condition.
+// case [var a, _] when a - 1:
+// ^
+//
+// pkg/front_end/testcases/patterns/non_bool_guard.dart:15:32: Error: Conditions must have a static type of 'bool'.
+// Try changing the condition.
+// if (v case [var a, _] when a - 1) {
+// ^
+//
+// pkg/front_end/testcases/patterns/non_bool_guard.dart:23:23: Error: Conditions must have a static type of 'bool'.
+// Try changing the condition.
+// [var a, _] when a - 1 => "match",
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+static method test1(core::List<core::int> v) → core::String {
+ #L1:
+ {
+ core::int a;
+ final core::List<core::int> #0#0 = v;
+ if(#0#0.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final dynamic #t1 = a = #0#0.{core::List::[]}(0){(core::int) → core::int} in true) && (let final dynamic #t2 = #0#0.{core::List::[]}(1){(core::int) → core::int} in true) && invalid-expression "pkg/front_end/testcases/patterns/non_bool_guard.dart:7:28: Error: Conditions must have a static type of 'bool'.
+Try changing the condition.
+ case [var a, _] when a - 1:
+ ^") {
+ {
+ return "match";
+ }
+ }
+ else {
+ {
+ return "no match";
+ }
+ }
+ }
+}
+static method test2(core::List<core::int> v) → core::String {
+ {
+ core::int a;
+ final core::List<core::int> #0#0 = v;
+ if(#0#0.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final dynamic #t3 = a = #0#0.{core::List::[]}(0){(core::int) → core::int} in true) && (let final dynamic #t4 = #0#0.{core::List::[]}(1){(core::int) → core::int} in true) && invalid-expression "pkg/front_end/testcases/patterns/non_bool_guard.dart:15:32: Error: Conditions must have a static type of 'bool'.
+Try changing the condition.
+ if (v case [var a, _] when a - 1) {
+ ^") {
+ return "match";
+ }
+ }
+ return "no match";
+}
+static method test3(core::List<core::int> v) → core::String
+ return block {
+ core::String #t5;
+ core::int a;
+ final core::List<core::int> #0#0 = v;
+ if(#0#0.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final dynamic #t6 = a = #0#0.{core::List::[]}(0){(core::int) → core::int} in true) && (let final dynamic #t7 = #0#0.{core::List::[]}(1){(core::int) → core::int} in true) && invalid-expression "pkg/front_end/testcases/patterns/non_bool_guard.dart:23:23: Error: Conditions must have a static type of 'bool'.
+Try changing the condition.
+ [var a, _] when a - 1 => \"match\",
+ ^")
+ #t5 = "match";
+ else
+ if(true)
+ #t5 = "no match";
+ } =>#t5;
+
+constants {
+ #C1 = 2
+}
diff --git a/pkg/front_end/testcases/patterns/non_bool_guard.dart.weak.outline.expect b/pkg/front_end/testcases/patterns/non_bool_guard.dart.weak.outline.expect
new file mode 100644
index 0000000..46f1fb3
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/non_bool_guard.dart.weak.outline.expect
@@ -0,0 +1,10 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static method test1(core::List<core::int> v) → core::String
+ ;
+static method test2(core::List<core::int> v) → core::String
+ ;
+static method test3(core::List<core::int> v) → core::String
+ ;
diff --git a/pkg/front_end/testcases/patterns/non_bool_guard.dart.weak.transformed.expect b/pkg/front_end/testcases/patterns/non_bool_guard.dart.weak.transformed.expect
new file mode 100644
index 0000000..3b921f5
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/non_bool_guard.dart.weak.transformed.expect
@@ -0,0 +1,73 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/patterns/non_bool_guard.dart:7:28: Error: Conditions must have a static type of 'bool'.
+// Try changing the condition.
+// case [var a, _] when a - 1:
+// ^
+//
+// pkg/front_end/testcases/patterns/non_bool_guard.dart:15:32: Error: Conditions must have a static type of 'bool'.
+// Try changing the condition.
+// if (v case [var a, _] when a - 1) {
+// ^
+//
+// pkg/front_end/testcases/patterns/non_bool_guard.dart:23:23: Error: Conditions must have a static type of 'bool'.
+// Try changing the condition.
+// [var a, _] when a - 1 => "match",
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+static method test1(core::List<core::int> v) → core::String {
+ #L1:
+ {
+ core::int a;
+ final core::List<core::int> #0#0 = v;
+ if(#0#0.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final core::int #t1 = a = #0#0.{core::List::[]}(0){(core::int) → core::int} in true) && (let final core::int #t2 = #0#0.{core::List::[]}(1){(core::int) → core::int} in true) && invalid-expression "pkg/front_end/testcases/patterns/non_bool_guard.dart:7:28: Error: Conditions must have a static type of 'bool'.
+Try changing the condition.
+ case [var a, _] when a - 1:
+ ^") {
+ {
+ return "match";
+ }
+ }
+ else {
+ {
+ return "no match";
+ }
+ }
+ }
+}
+static method test2(core::List<core::int> v) → core::String {
+ {
+ core::int a;
+ final core::List<core::int> #0#0 = v;
+ if(#0#0.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final core::int #t3 = a = #0#0.{core::List::[]}(0){(core::int) → core::int} in true) && (let final core::int #t4 = #0#0.{core::List::[]}(1){(core::int) → core::int} in true) && invalid-expression "pkg/front_end/testcases/patterns/non_bool_guard.dart:15:32: Error: Conditions must have a static type of 'bool'.
+Try changing the condition.
+ if (v case [var a, _] when a - 1) {
+ ^") {
+ return "match";
+ }
+ }
+ return "no match";
+}
+static method test3(core::List<core::int> v) → core::String
+ return block {
+ core::String #t5;
+ core::int a;
+ final core::List<core::int> #0#0 = v;
+ if(#0#0.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final core::int #t6 = a = #0#0.{core::List::[]}(0){(core::int) → core::int} in true) && (let final core::int #t7 = #0#0.{core::List::[]}(1){(core::int) → core::int} in true) && invalid-expression "pkg/front_end/testcases/patterns/non_bool_guard.dart:23:23: Error: Conditions must have a static type of 'bool'.
+Try changing the condition.
+ [var a, _] when a - 1 => \"match\",
+ ^")
+ #t5 = "match";
+ else
+ if(true)
+ #t5 = "no match";
+ } =>#t5;
+
+constants {
+ #C1 = 2
+}
diff --git a/pkg/front_end/testcases/patterns/pattern_types.dart.strong.expect b/pkg/front_end/testcases/patterns/pattern_types.dart.strong.expect
index 2b00c98..b25d765 100644
--- a/pkg/front_end/testcases/patterns/pattern_types.dart.strong.expect
+++ b/pkg/front_end/testcases/patterns/pattern_types.dart.strong.expect
@@ -226,40 +226,73 @@
core::bool #0#14#isSet = false;
dynamic #0#15;
core::bool #0#15#isSet = false;
- if(#0#0 is{ForNonNullableByDefault} Null && (let final dynamic #t1 = hashCode = #0#0{Null}.{core::Object::hashCode}{core::int} in true) || #0#0 is{ForNonNullableByDefault} Null && (let final dynamic #t2 = toString = #0#0{Null}.{core::Object::toString}{() → core::String} in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t3 = field = #0#5#isSet ?{dynamic} #0#5{dynamic} : let final dynamic #t4 = #0#5#isSet = true in #0#5 = #0#0{self::Class}.{self::Class::field}{dynamic} in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t5 = method = #0#6#isSet ?{() → void} #0#6{() → void} : let final dynamic #t6 = #0#6#isSet = true in #0#6 = #0#0{self::Class}.{self::Class::method}{() → void} in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t7 = extensionGetter = self::_extension#0|get#extensionGetter(#0#0{self::Class}) in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t8 = extensionMethod = self::_extension#0|extensionMethod(#0#0{self::Class}) in true) || #0#0 is{ForNonNullableByDefault} dynamic && (let final dynamic #t9 = dynamicAccess = #0#0{dynamic}.dynamicAccess in true) || #0#0 is{ForNonNullableByDefault} () → void && (let final dynamic #t10 = call = #0#12#isSet ?{() → void} #0#12{() → void} : let final dynamic #t11 = #0#12#isSet = true in #0#12 = #0#0{() → void}.call in true) || #0#0 is{ForNonNullableByDefault} (core::int, {required named: core::String}) && (let final dynamic #t12 = $1 = #0#14#isSet ?{core::int} #0#14{core::int} : let final dynamic #t13 = #0#14#isSet = true in #0#14 = #0#0{(core::int, {required named: core::String})}.$1{core::int} in true) || #0#0 is{ForNonNullableByDefault} (core::int, {required named: core::String}) && (let final dynamic #t14 = named = #0#15#isSet ?{core::String} #0#15{core::String} : let final dynamic #t15 = #0#15#isSet = true in #0#15 = #0#0{(core::int, {required named: core::String})}.named{core::String} in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t16 = missing = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:75:16: Error: The getter 'missing' isn't defined for the class 'Class'.
+ if(#0#0 is{ForNonNullableByDefault} Null && (let final dynamic #t1 = hashCode = #0#0{Null}.{core::Object::hashCode}{core::int} in true) || #0#0 is{ForNonNullableByDefault} Null && (let final dynamic #t2 = toString = #0#0{Null}.{core::Object::toString}{() → core::String} in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t3 = field = #0#5#isSet ?{dynamic} #0#5{dynamic} : let final dynamic #t4 = #0#5#isSet = true in #0#5 = #0#0{self::Class}.{self::Class::field}{dynamic} in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t5 = method = #0#6#isSet ?{() → void} #0#6{() → void} : let final dynamic #t6 = #0#6#isSet = true in #0#6 = #0#0{self::Class}.{self::Class::method}{() → void} in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t7 = extensionGetter = self::_extension#0|get#extensionGetter(#0#0{self::Class}) in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t8 = extensionMethod = self::_extension#0|extensionMethod(#0#0{self::Class}) in true) || #0#0 is{ForNonNullableByDefault} dynamic && (let final dynamic #t9 = dynamicAccess = #0#0{dynamic}.dynamicAccess in true) || #0#0 is{ForNonNullableByDefault} () → void && (let final dynamic #t10 = call = #0#12#isSet ?{() → void} #0#12{() → void} : let final dynamic #t11 = #0#12#isSet = true in #0#12 = #0#0{() → void}.call in true) || #0#0 is{ForNonNullableByDefault} (core::int, {required named: core::String}) && (let final dynamic #t12 = $1 = #0#14#isSet ?{core::int} #0#14{core::int} : let final dynamic #t13 = #0#14#isSet = true in #0#14 = #0#0{(core::int, {required named: core::String})}.$1{core::int} in true) || #0#0 is{ForNonNullableByDefault} (core::int, {required named: core::String}) && (let final dynamic #t14 = named = #0#15#isSet ?{core::String} #0#15{core::String} : let final dynamic #t15 = #0#15#isSet = true in #0#15 = #0#0{(core::int, {required named: core::String})}.named{core::String} in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t16 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:75:16: Error: The getter 'missing' isn't defined for the class 'Class'.
- 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'missing'.
case Class(: var missing): // Error: missing getter
- ^^^^^^^" in null{<unresolved>}.missing in true) || #0#0 is{ForNonNullableByDefault} self::Class? && (let final dynamic #t17 = field#1 = #0#5#isSet ?{invalid-type} #0#5{invalid-type} : let final dynamic #t18 = #0#5#isSet = true in #0#5 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:76:17: Error: The getter 'field' isn't defined for the class 'Class?'.
+ ^^^^^^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:75:16: Error: The getter 'missing' isn't defined for the class 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'missing'.
+ case Class(: var missing): // Error: missing getter
+ ^^^^^^^") || #0#0 is{ForNonNullableByDefault} self::Class? && (let final dynamic #t17 = #0#5#isSet ?{invalid-type} #0#5{invalid-type} : let final dynamic #t18 = #0#5#isSet = true in #0#5 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:76:17: Error: The getter 'field' isn't defined for the class 'Class?'.
- 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'field'.
case Class_(: var field): // Error: nullable member get
- ^^^^^" in null{<unresolved>}.field in true) || #0#0 is{ForNonNullableByDefault} self::Class? && (let final dynamic #t19 = method#1 = #0#6#isSet ?{invalid-type} #0#6{invalid-type} : let final dynamic #t20 = #0#6#isSet = true in #0#6 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:77:17: Error: The getter 'method' isn't defined for the class 'Class?'.
+ ^^^^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:76:17: Error: The getter 'field' isn't defined for the class 'Class?'.
+ - 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'field'.
+ case Class_(: var field): // Error: nullable member get
+ ^^^^^") || #0#0 is{ForNonNullableByDefault} self::Class? && (let final dynamic #t19 = #0#6#isSet ?{invalid-type} #0#6{invalid-type} : let final dynamic #t20 = #0#6#isSet = true in #0#6 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:77:17: Error: The getter 'method' isn't defined for the class 'Class?'.
- 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'method'.
case Class_(: var method): // Error: nullable member tear-off
- ^^^^^^" in null{<unresolved>}.method in true) || #0#0 is{ForNonNullableByDefault} self::Class? && (let final dynamic #t21 = extensionGetter#1 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:78:17: Error: The getter 'extensionGetter' isn't defined for the class 'Class?'.
+ ^^^^^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:77:17: Error: The getter 'method' isn't defined for the class 'Class?'.
+ - 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'method'.
+ case Class_(: var method): // Error: nullable member tear-off
+ ^^^^^^") || #0#0 is{ForNonNullableByDefault} self::Class? && (let final dynamic #t21 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:78:17: Error: The getter 'extensionGetter' isn't defined for the class 'Class?'.
- 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'extensionGetter'.
case Class_(: var extensionGetter): // Error: nullable extension member get
- ^^^^^^^^^^^^^^^" in null{<unresolved>}.extensionGetter in true) || #0#0 is{ForNonNullableByDefault} self::Class? && (let final dynamic #t22 = extensionMethod#1 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:79:17: Error: The getter 'extensionMethod' isn't defined for the class 'Class?'.
+ ^^^^^^^^^^^^^^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:78:17: Error: The getter 'extensionGetter' isn't defined for the class 'Class?'.
+ - 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'extensionGetter'.
+ case Class_(: var extensionGetter): // Error: nullable extension member get
+ ^^^^^^^^^^^^^^^") || #0#0 is{ForNonNullableByDefault} self::Class? && (let final dynamic #t22 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:79:17: Error: The getter 'extensionMethod' isn't defined for the class 'Class?'.
- 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'extensionMethod'.
case Class_(: var extensionMethod): // Error: nullable extension tear-off
- ^^^^^^^^^^^^^^^" in null{<unresolved>}.extensionMethod in true) || #0#0 is{ForNonNullableByDefault} () →? void && (let final dynamic #t23 = call#1 = #0#12#isSet ?{invalid-type} #0#12{invalid-type} : let final dynamic #t24 = #0#12#isSet = true in #0#12 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:80:21: Error: The getter 'call' isn't defined for the class 'void Function()?'.
+ ^^^^^^^^^^^^^^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:79:17: Error: The getter 'extensionMethod' isn't defined for the class 'Class?'.
+ - 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'extensionMethod'.
+ case Class_(: var extensionMethod): // Error: nullable extension tear-off
+ ^^^^^^^^^^^^^^^") || #0#0 is{ForNonNullableByDefault} () →? void && (let final dynamic #t23 = #0#12#isSet ?{invalid-type} #0#12{invalid-type} : let final dynamic #t24 = #0#12#isSet = true in #0#12 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:80:21: Error: The getter 'call' isn't defined for the class 'void Function()?'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'call'.
case Function1_(: var call): // Error: nullable function tear-off
- ^^^^" in null{<unresolved>}.call in true) || #0#0 is{ForNonNullableByDefault} (core::int, {required named: core::String})? && (let final dynamic #t25 = $1#1 = #0#14#isSet ?{invalid-type} #0#14{invalid-type} : let final dynamic #t26 = #0#14#isSet = true in #0#14 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:81:19: Error: The getter '\$1' isn't defined for the class '(int, {String named})?'.
+ ^^^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:80:21: Error: The getter 'call' isn't defined for the class 'void Function()?'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'call'.
+ case Function1_(: var call): // Error: nullable function tear-off
+ ^^^^") || #0#0 is{ForNonNullableByDefault} (core::int, {required named: core::String})? && (let final dynamic #t25 = #0#14#isSet ?{invalid-type} #0#14{invalid-type} : let final dynamic #t26 = #0#14#isSet = true in #0#14 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:81:19: Error: The getter '\$1' isn't defined for the class '(int, {String named})?'.
Try correcting the name to the name of an existing getter, or defining a getter or field named '\$1'.
case Record1_(: var \$1): // Error: nullable record index get
- ^^" in null{<unresolved>}.$1 in true) || #0#0 is{ForNonNullableByDefault} (core::int, {required named: core::String})? && (let final dynamic #t27 = named#1 = #0#15#isSet ?{invalid-type} #0#15{invalid-type} : let final dynamic #t28 = #0#15#isSet = true in #0#15 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:82:19: Error: The getter 'named' isn't defined for the class '(int, {String named})?'.
+ ^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:81:19: Error: The getter '\$1' isn't defined for the class '(int, {String named})?'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$1'.
+ case Record1_(: var \$1): // Error: nullable record index get
+ ^^") || #0#0 is{ForNonNullableByDefault} (core::int, {required named: core::String})? && (let final dynamic #t27 = #0#15#isSet ?{invalid-type} #0#15{invalid-type} : let final dynamic #t28 = #0#15#isSet = true in #0#15 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:82:19: Error: The getter 'named' isn't defined for the class '(int, {String named})?'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'named'.
case Record1_(: var named): // Error: nullable record named get
- ^^^^^" in null{<unresolved>}.named in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t29 = ambiguousField = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:83:16: Error: The getter 'ambiguousField' isn't defined for the class 'Class'.
+ ^^^^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:82:19: Error: The getter 'named' isn't defined for the class '(int, {String named})?'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'named'.
+ case Record1_(: var named): // Error: nullable record named get
+ ^^^^^") || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t29 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:83:16: Error: The getter 'ambiguousField' isn't defined for the class 'Class'.
- 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'ambiguousField'.
case Class(: var ambiguousField): // Error: ambiguous get
- ^^^^^^^^^^^^^^" in null{<unresolved>}.ambiguousField in true) || #0#0 is{ForNonNullableByDefault} invalid-type) {
+ ^^^^^^^^^^^^^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:83:16: Error: The getter 'ambiguousField' isn't defined for the class 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'ambiguousField'.
+ case Class(: var ambiguousField): // Error: ambiguous get
+ ^^^^^^^^^^^^^^") || #0#0 is{ForNonNullableByDefault} invalid-type) {
}
}
}
@@ -344,10 +377,9 @@
if(self::_extension#0|<=(#15#0, #C1)) {
}
}
- {
- final self::Class #16#0 = cls;
- if(#16#0.{self::Class::<}(#C2){(core::int) → core::bool}) {
- }
+ if(invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:113:18: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+ if (cls case < '0') {} // Error: invalid instance < argument
+ ^") {
}
{
final self::Class #17#0 = cls;
@@ -377,23 +409,23 @@
- 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
Try correcting the name to the name of an existing method, or defining a method named '<'.
if (cls_ case < 0) {} // Error: nullable instance <
- ^" in null{<unresolved>}.<()) {
+ ^") {
}
if(invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:120:17: Error: The method '<=' isn't defined for the class 'Class?'.
- 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
Try correcting the name to the name of an existing method, or defining a method named '<='.
if (cls_ case <= 0) {} // Error: nullable extension <=
- ^^" in null{<unresolved>}.<=()) {
+ ^^") {
}
if(invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:121:19: Error: The method '<' isn't defined for the class 'String'.
Try correcting the name to the name of an existing method, or defining a method named '<'.
if (string case < 0) {} // Error: missing <
- ^" in null{<unresolved>}.<()) {
+ ^") {
}
if(invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:122:19: Error: The method '<=' isn't defined for the class 'String'.
Try correcting the name to the name of an existing method, or defining a method named '<='.
if (string case <= 0) {} // Error: ambiguous <=
- ^^" in null{<unresolved>}.<=()) {
+ ^^") {
}
{
final invalid-type #26#0 = invalid;
@@ -417,10 +449,10 @@
^^^^^^") {
}
}
- {
- final self::Class2 #29#0 = cls2;
- if(#29#0 =={self::Class2::==}{(self::Class2) → core::bool} #C1) {
- }
+ if(invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:126:20: Error: The argument type 'int' can't be assigned to the parameter type 'Class2'.
+ - 'Class2' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+ if (cls2 case == 0) {} // Error: invalid instance == argument
+ ^") {
}
{
final self::Class2 #30#0 = cls2;
@@ -434,10 +466,10 @@
^^^^^^")) {
}
}
- {
- final self::Class2 #31#0 = cls2;
- if(!(#31#0 =={self::Class2::==}{(self::Class2) → core::bool} #C1)) {
- }
+ if(invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:128:20: Error: The argument type 'int' can't be assigned to the parameter type 'Class2'.
+ - 'Class2' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+ if (cls2 case != 0) {} // Error: invalid instance == argument negated
+ ^") {
}
{
final self::Class2 #32#0 = cls2;
@@ -451,10 +483,10 @@
^^^^^^"){(self::Class2) → core::bool}) {
}
}
- {
- final self::Class2 #33#0 = cls2;
- if(#33#0.{self::Class2::<}(#C1){(self::Class2) → core::bool}) {
- }
+ if(invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:130:19: Error: The argument type 'int' can't be assigned to the parameter type 'Class2'.
+ - 'Class2' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+ if (cls2 case < 0) {} // Error: invalid instance < argument
+ ^") {
}
{
final self::Class2? #34#0 = cls2_;
diff --git a/pkg/front_end/testcases/patterns/pattern_types.dart.weak.expect b/pkg/front_end/testcases/patterns/pattern_types.dart.weak.expect
index 8def158..3f707d2 100644
--- a/pkg/front_end/testcases/patterns/pattern_types.dart.weak.expect
+++ b/pkg/front_end/testcases/patterns/pattern_types.dart.weak.expect
@@ -227,40 +227,73 @@
core::bool #0#14#isSet = false;
dynamic #0#15;
core::bool #0#15#isSet = false;
- if(#0#0 is{ForNonNullableByDefault} Null && (let final dynamic #t1 = hashCode = #0#0{Null}.{core::Object::hashCode}{core::int} in true) || #0#0 is{ForNonNullableByDefault} Null && (let final dynamic #t2 = toString = #0#0{Null}.{core::Object::toString}{() → core::String} in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t3 = field = #0#5#isSet ?{dynamic} #0#5{dynamic} : let final dynamic #t4 = #0#5#isSet = true in #0#5 = #0#0{self::Class}.{self::Class::field}{dynamic} in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t5 = method = #0#6#isSet ?{() → void} #0#6{() → void} : let final dynamic #t6 = #0#6#isSet = true in #0#6 = #0#0{self::Class}.{self::Class::method}{() → void} in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t7 = extensionGetter = self::_extension#0|get#extensionGetter(#0#0{self::Class}) in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t8 = extensionMethod = self::_extension#0|extensionMethod(#0#0{self::Class}) in true) || #0#0 is{ForNonNullableByDefault} dynamic && (let final dynamic #t9 = dynamicAccess = #0#0{dynamic}.dynamicAccess in true) || #0#0 is{ForNonNullableByDefault} () → void && (let final dynamic #t10 = call = #0#12#isSet ?{() → void} #0#12{() → void} : let final dynamic #t11 = #0#12#isSet = true in #0#12 = #0#0{() → void}.call in true) || #0#0 is{ForNonNullableByDefault} (core::int, {required named: core::String}) && (let final dynamic #t12 = $1 = #0#14#isSet ?{core::int} #0#14{core::int} : let final dynamic #t13 = #0#14#isSet = true in #0#14 = #0#0{(core::int, {required named: core::String})}.$1{core::int} in true) || #0#0 is{ForNonNullableByDefault} (core::int, {required named: core::String}) && (let final dynamic #t14 = named = #0#15#isSet ?{core::String} #0#15{core::String} : let final dynamic #t15 = #0#15#isSet = true in #0#15 = #0#0{(core::int, {required named: core::String})}.named{core::String} in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t16 = missing = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:75:16: Error: The getter 'missing' isn't defined for the class 'Class'.
+ if(#0#0 is{ForNonNullableByDefault} Null && (let final dynamic #t1 = hashCode = #0#0{Null}.{core::Object::hashCode}{core::int} in true) || #0#0 is{ForNonNullableByDefault} Null && (let final dynamic #t2 = toString = #0#0{Null}.{core::Object::toString}{() → core::String} in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t3 = field = #0#5#isSet ?{dynamic} #0#5{dynamic} : let final dynamic #t4 = #0#5#isSet = true in #0#5 = #0#0{self::Class}.{self::Class::field}{dynamic} in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t5 = method = #0#6#isSet ?{() → void} #0#6{() → void} : let final dynamic #t6 = #0#6#isSet = true in #0#6 = #0#0{self::Class}.{self::Class::method}{() → void} in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t7 = extensionGetter = self::_extension#0|get#extensionGetter(#0#0{self::Class}) in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t8 = extensionMethod = self::_extension#0|extensionMethod(#0#0{self::Class}) in true) || #0#0 is{ForNonNullableByDefault} dynamic && (let final dynamic #t9 = dynamicAccess = #0#0{dynamic}.dynamicAccess in true) || #0#0 is{ForNonNullableByDefault} () → void && (let final dynamic #t10 = call = #0#12#isSet ?{() → void} #0#12{() → void} : let final dynamic #t11 = #0#12#isSet = true in #0#12 = #0#0{() → void}.call in true) || #0#0 is{ForNonNullableByDefault} (core::int, {required named: core::String}) && (let final dynamic #t12 = $1 = #0#14#isSet ?{core::int} #0#14{core::int} : let final dynamic #t13 = #0#14#isSet = true in #0#14 = #0#0{(core::int, {required named: core::String})}.$1{core::int} in true) || #0#0 is{ForNonNullableByDefault} (core::int, {required named: core::String}) && (let final dynamic #t14 = named = #0#15#isSet ?{core::String} #0#15{core::String} : let final dynamic #t15 = #0#15#isSet = true in #0#15 = #0#0{(core::int, {required named: core::String})}.named{core::String} in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t16 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:75:16: Error: The getter 'missing' isn't defined for the class 'Class'.
- 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'missing'.
case Class(: var missing): // Error: missing getter
- ^^^^^^^" in null{<unresolved>}.missing in true) || #0#0 is{ForNonNullableByDefault} self::Class? && (let final dynamic #t17 = field#1 = #0#5#isSet ?{invalid-type} #0#5{invalid-type} : let final dynamic #t18 = #0#5#isSet = true in #0#5 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:76:17: Error: The getter 'field' isn't defined for the class 'Class?'.
+ ^^^^^^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:75:16: Error: The getter 'missing' isn't defined for the class 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'missing'.
+ case Class(: var missing): // Error: missing getter
+ ^^^^^^^") || #0#0 is{ForNonNullableByDefault} self::Class? && (let final dynamic #t17 = #0#5#isSet ?{invalid-type} #0#5{invalid-type} : let final dynamic #t18 = #0#5#isSet = true in #0#5 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:76:17: Error: The getter 'field' isn't defined for the class 'Class?'.
- 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'field'.
case Class_(: var field): // Error: nullable member get
- ^^^^^" in null{<unresolved>}.field in true) || #0#0 is{ForNonNullableByDefault} self::Class? && (let final dynamic #t19 = method#1 = #0#6#isSet ?{invalid-type} #0#6{invalid-type} : let final dynamic #t20 = #0#6#isSet = true in #0#6 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:77:17: Error: The getter 'method' isn't defined for the class 'Class?'.
+ ^^^^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:76:17: Error: The getter 'field' isn't defined for the class 'Class?'.
+ - 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'field'.
+ case Class_(: var field): // Error: nullable member get
+ ^^^^^") || #0#0 is{ForNonNullableByDefault} self::Class? && (let final dynamic #t19 = #0#6#isSet ?{invalid-type} #0#6{invalid-type} : let final dynamic #t20 = #0#6#isSet = true in #0#6 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:77:17: Error: The getter 'method' isn't defined for the class 'Class?'.
- 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'method'.
case Class_(: var method): // Error: nullable member tear-off
- ^^^^^^" in null{<unresolved>}.method in true) || #0#0 is{ForNonNullableByDefault} self::Class? && (let final dynamic #t21 = extensionGetter#1 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:78:17: Error: The getter 'extensionGetter' isn't defined for the class 'Class?'.
+ ^^^^^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:77:17: Error: The getter 'method' isn't defined for the class 'Class?'.
+ - 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'method'.
+ case Class_(: var method): // Error: nullable member tear-off
+ ^^^^^^") || #0#0 is{ForNonNullableByDefault} self::Class? && (let final dynamic #t21 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:78:17: Error: The getter 'extensionGetter' isn't defined for the class 'Class?'.
- 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'extensionGetter'.
case Class_(: var extensionGetter): // Error: nullable extension member get
- ^^^^^^^^^^^^^^^" in null{<unresolved>}.extensionGetter in true) || #0#0 is{ForNonNullableByDefault} self::Class? && (let final dynamic #t22 = extensionMethod#1 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:79:17: Error: The getter 'extensionMethod' isn't defined for the class 'Class?'.
+ ^^^^^^^^^^^^^^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:78:17: Error: The getter 'extensionGetter' isn't defined for the class 'Class?'.
+ - 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'extensionGetter'.
+ case Class_(: var extensionGetter): // Error: nullable extension member get
+ ^^^^^^^^^^^^^^^") || #0#0 is{ForNonNullableByDefault} self::Class? && (let final dynamic #t22 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:79:17: Error: The getter 'extensionMethod' isn't defined for the class 'Class?'.
- 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'extensionMethod'.
case Class_(: var extensionMethod): // Error: nullable extension tear-off
- ^^^^^^^^^^^^^^^" in null{<unresolved>}.extensionMethod in true) || #0#0 is{ForNonNullableByDefault} () →? void && (let final dynamic #t23 = call#1 = #0#12#isSet ?{invalid-type} #0#12{invalid-type} : let final dynamic #t24 = #0#12#isSet = true in #0#12 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:80:21: Error: The getter 'call' isn't defined for the class 'void Function()?'.
+ ^^^^^^^^^^^^^^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:79:17: Error: The getter 'extensionMethod' isn't defined for the class 'Class?'.
+ - 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'extensionMethod'.
+ case Class_(: var extensionMethod): // Error: nullable extension tear-off
+ ^^^^^^^^^^^^^^^") || #0#0 is{ForNonNullableByDefault} () →? void && (let final dynamic #t23 = #0#12#isSet ?{invalid-type} #0#12{invalid-type} : let final dynamic #t24 = #0#12#isSet = true in #0#12 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:80:21: Error: The getter 'call' isn't defined for the class 'void Function()?'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'call'.
case Function1_(: var call): // Error: nullable function tear-off
- ^^^^" in null{<unresolved>}.call in true) || #0#0 is{ForNonNullableByDefault} (core::int, {required named: core::String})? && (let final dynamic #t25 = $1#1 = #0#14#isSet ?{invalid-type} #0#14{invalid-type} : let final dynamic #t26 = #0#14#isSet = true in #0#14 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:81:19: Error: The getter '\$1' isn't defined for the class '(int, {String named})?'.
+ ^^^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:80:21: Error: The getter 'call' isn't defined for the class 'void Function()?'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'call'.
+ case Function1_(: var call): // Error: nullable function tear-off
+ ^^^^") || #0#0 is{ForNonNullableByDefault} (core::int, {required named: core::String})? && (let final dynamic #t25 = #0#14#isSet ?{invalid-type} #0#14{invalid-type} : let final dynamic #t26 = #0#14#isSet = true in #0#14 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:81:19: Error: The getter '\$1' isn't defined for the class '(int, {String named})?'.
Try correcting the name to the name of an existing getter, or defining a getter or field named '\$1'.
case Record1_(: var \$1): // Error: nullable record index get
- ^^" in null{<unresolved>}.$1 in true) || #0#0 is{ForNonNullableByDefault} (core::int, {required named: core::String})? && (let final dynamic #t27 = named#1 = #0#15#isSet ?{invalid-type} #0#15{invalid-type} : let final dynamic #t28 = #0#15#isSet = true in #0#15 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:82:19: Error: The getter 'named' isn't defined for the class '(int, {String named})?'.
+ ^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:81:19: Error: The getter '\$1' isn't defined for the class '(int, {String named})?'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$1'.
+ case Record1_(: var \$1): // Error: nullable record index get
+ ^^") || #0#0 is{ForNonNullableByDefault} (core::int, {required named: core::String})? && (let final dynamic #t27 = #0#15#isSet ?{invalid-type} #0#15{invalid-type} : let final dynamic #t28 = #0#15#isSet = true in #0#15 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:82:19: Error: The getter 'named' isn't defined for the class '(int, {String named})?'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'named'.
case Record1_(: var named): // Error: nullable record named get
- ^^^^^" in null{<unresolved>}.named in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t29 = ambiguousField = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:83:16: Error: The getter 'ambiguousField' isn't defined for the class 'Class'.
+ ^^^^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:82:19: Error: The getter 'named' isn't defined for the class '(int, {String named})?'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'named'.
+ case Record1_(: var named): // Error: nullable record named get
+ ^^^^^") || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t29 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:83:16: Error: The getter 'ambiguousField' isn't defined for the class 'Class'.
- 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'ambiguousField'.
case Class(: var ambiguousField): // Error: ambiguous get
- ^^^^^^^^^^^^^^" in null{<unresolved>}.ambiguousField in true) || #0#0 is{ForNonNullableByDefault} invalid-type) {
+ ^^^^^^^^^^^^^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:83:16: Error: The getter 'ambiguousField' isn't defined for the class 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'ambiguousField'.
+ case Class(: var ambiguousField): // Error: ambiguous get
+ ^^^^^^^^^^^^^^") || #0#0 is{ForNonNullableByDefault} invalid-type) {
}
}
}
@@ -345,10 +378,9 @@
if(self::_extension#0|<=(#15#0, #C1)) {
}
}
- {
- final self::Class #16#0 = cls;
- if(#16#0.{self::Class::<}(#C2){(core::int) → core::bool}) {
- }
+ if(invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:113:18: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+ if (cls case < '0') {} // Error: invalid instance < argument
+ ^") {
}
{
final self::Class #17#0 = cls;
@@ -378,23 +410,23 @@
- 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
Try correcting the name to the name of an existing method, or defining a method named '<'.
if (cls_ case < 0) {} // Error: nullable instance <
- ^" in null{<unresolved>}.<()) {
+ ^") {
}
if(invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:120:17: Error: The method '<=' isn't defined for the class 'Class?'.
- 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
Try correcting the name to the name of an existing method, or defining a method named '<='.
if (cls_ case <= 0) {} // Error: nullable extension <=
- ^^" in null{<unresolved>}.<=()) {
+ ^^") {
}
if(invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:121:19: Error: The method '<' isn't defined for the class 'String'.
Try correcting the name to the name of an existing method, or defining a method named '<'.
if (string case < 0) {} // Error: missing <
- ^" in null{<unresolved>}.<()) {
+ ^") {
}
if(invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:122:19: Error: The method '<=' isn't defined for the class 'String'.
Try correcting the name to the name of an existing method, or defining a method named '<='.
if (string case <= 0) {} // Error: ambiguous <=
- ^^" in null{<unresolved>}.<=()) {
+ ^^") {
}
{
final invalid-type #26#0 = invalid;
@@ -418,10 +450,10 @@
^^^^^^") {
}
}
- {
- final self::Class2 #29#0 = cls2;
- if(#29#0 =={self::Class2::==}{(self::Class2) → core::bool} #C1) {
- }
+ if(invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:126:20: Error: The argument type 'int' can't be assigned to the parameter type 'Class2'.
+ - 'Class2' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+ if (cls2 case == 0) {} // Error: invalid instance == argument
+ ^") {
}
{
final self::Class2 #30#0 = cls2;
@@ -435,10 +467,10 @@
^^^^^^")) {
}
}
- {
- final self::Class2 #31#0 = cls2;
- if(!(#31#0 =={self::Class2::==}{(self::Class2) → core::bool} #C1)) {
- }
+ if(invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:128:20: Error: The argument type 'int' can't be assigned to the parameter type 'Class2'.
+ - 'Class2' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+ if (cls2 case != 0) {} // Error: invalid instance == argument negated
+ ^") {
}
{
final self::Class2 #32#0 = cls2;
@@ -452,10 +484,10 @@
^^^^^^"){(self::Class2) → core::bool}) {
}
}
- {
- final self::Class2 #33#0 = cls2;
- if(#33#0.{self::Class2::<}(#C1){(self::Class2) → core::bool}) {
- }
+ if(invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:130:19: Error: The argument type 'int' can't be assigned to the parameter type 'Class2'.
+ - 'Class2' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+ if (cls2 case < 0) {} // Error: invalid instance < argument
+ ^") {
}
{
final self::Class2? #34#0 = cls2_;
diff --git a/pkg/front_end/testcases/patterns/pattern_types.dart.weak.modular.expect b/pkg/front_end/testcases/patterns/pattern_types.dart.weak.modular.expect
index 8def158..3f707d2 100644
--- a/pkg/front_end/testcases/patterns/pattern_types.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/patterns/pattern_types.dart.weak.modular.expect
@@ -227,40 +227,73 @@
core::bool #0#14#isSet = false;
dynamic #0#15;
core::bool #0#15#isSet = false;
- if(#0#0 is{ForNonNullableByDefault} Null && (let final dynamic #t1 = hashCode = #0#0{Null}.{core::Object::hashCode}{core::int} in true) || #0#0 is{ForNonNullableByDefault} Null && (let final dynamic #t2 = toString = #0#0{Null}.{core::Object::toString}{() → core::String} in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t3 = field = #0#5#isSet ?{dynamic} #0#5{dynamic} : let final dynamic #t4 = #0#5#isSet = true in #0#5 = #0#0{self::Class}.{self::Class::field}{dynamic} in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t5 = method = #0#6#isSet ?{() → void} #0#6{() → void} : let final dynamic #t6 = #0#6#isSet = true in #0#6 = #0#0{self::Class}.{self::Class::method}{() → void} in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t7 = extensionGetter = self::_extension#0|get#extensionGetter(#0#0{self::Class}) in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t8 = extensionMethod = self::_extension#0|extensionMethod(#0#0{self::Class}) in true) || #0#0 is{ForNonNullableByDefault} dynamic && (let final dynamic #t9 = dynamicAccess = #0#0{dynamic}.dynamicAccess in true) || #0#0 is{ForNonNullableByDefault} () → void && (let final dynamic #t10 = call = #0#12#isSet ?{() → void} #0#12{() → void} : let final dynamic #t11 = #0#12#isSet = true in #0#12 = #0#0{() → void}.call in true) || #0#0 is{ForNonNullableByDefault} (core::int, {required named: core::String}) && (let final dynamic #t12 = $1 = #0#14#isSet ?{core::int} #0#14{core::int} : let final dynamic #t13 = #0#14#isSet = true in #0#14 = #0#0{(core::int, {required named: core::String})}.$1{core::int} in true) || #0#0 is{ForNonNullableByDefault} (core::int, {required named: core::String}) && (let final dynamic #t14 = named = #0#15#isSet ?{core::String} #0#15{core::String} : let final dynamic #t15 = #0#15#isSet = true in #0#15 = #0#0{(core::int, {required named: core::String})}.named{core::String} in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t16 = missing = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:75:16: Error: The getter 'missing' isn't defined for the class 'Class'.
+ if(#0#0 is{ForNonNullableByDefault} Null && (let final dynamic #t1 = hashCode = #0#0{Null}.{core::Object::hashCode}{core::int} in true) || #0#0 is{ForNonNullableByDefault} Null && (let final dynamic #t2 = toString = #0#0{Null}.{core::Object::toString}{() → core::String} in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t3 = field = #0#5#isSet ?{dynamic} #0#5{dynamic} : let final dynamic #t4 = #0#5#isSet = true in #0#5 = #0#0{self::Class}.{self::Class::field}{dynamic} in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t5 = method = #0#6#isSet ?{() → void} #0#6{() → void} : let final dynamic #t6 = #0#6#isSet = true in #0#6 = #0#0{self::Class}.{self::Class::method}{() → void} in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t7 = extensionGetter = self::_extension#0|get#extensionGetter(#0#0{self::Class}) in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t8 = extensionMethod = self::_extension#0|extensionMethod(#0#0{self::Class}) in true) || #0#0 is{ForNonNullableByDefault} dynamic && (let final dynamic #t9 = dynamicAccess = #0#0{dynamic}.dynamicAccess in true) || #0#0 is{ForNonNullableByDefault} () → void && (let final dynamic #t10 = call = #0#12#isSet ?{() → void} #0#12{() → void} : let final dynamic #t11 = #0#12#isSet = true in #0#12 = #0#0{() → void}.call in true) || #0#0 is{ForNonNullableByDefault} (core::int, {required named: core::String}) && (let final dynamic #t12 = $1 = #0#14#isSet ?{core::int} #0#14{core::int} : let final dynamic #t13 = #0#14#isSet = true in #0#14 = #0#0{(core::int, {required named: core::String})}.$1{core::int} in true) || #0#0 is{ForNonNullableByDefault} (core::int, {required named: core::String}) && (let final dynamic #t14 = named = #0#15#isSet ?{core::String} #0#15{core::String} : let final dynamic #t15 = #0#15#isSet = true in #0#15 = #0#0{(core::int, {required named: core::String})}.named{core::String} in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t16 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:75:16: Error: The getter 'missing' isn't defined for the class 'Class'.
- 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'missing'.
case Class(: var missing): // Error: missing getter
- ^^^^^^^" in null{<unresolved>}.missing in true) || #0#0 is{ForNonNullableByDefault} self::Class? && (let final dynamic #t17 = field#1 = #0#5#isSet ?{invalid-type} #0#5{invalid-type} : let final dynamic #t18 = #0#5#isSet = true in #0#5 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:76:17: Error: The getter 'field' isn't defined for the class 'Class?'.
+ ^^^^^^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:75:16: Error: The getter 'missing' isn't defined for the class 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'missing'.
+ case Class(: var missing): // Error: missing getter
+ ^^^^^^^") || #0#0 is{ForNonNullableByDefault} self::Class? && (let final dynamic #t17 = #0#5#isSet ?{invalid-type} #0#5{invalid-type} : let final dynamic #t18 = #0#5#isSet = true in #0#5 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:76:17: Error: The getter 'field' isn't defined for the class 'Class?'.
- 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'field'.
case Class_(: var field): // Error: nullable member get
- ^^^^^" in null{<unresolved>}.field in true) || #0#0 is{ForNonNullableByDefault} self::Class? && (let final dynamic #t19 = method#1 = #0#6#isSet ?{invalid-type} #0#6{invalid-type} : let final dynamic #t20 = #0#6#isSet = true in #0#6 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:77:17: Error: The getter 'method' isn't defined for the class 'Class?'.
+ ^^^^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:76:17: Error: The getter 'field' isn't defined for the class 'Class?'.
+ - 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'field'.
+ case Class_(: var field): // Error: nullable member get
+ ^^^^^") || #0#0 is{ForNonNullableByDefault} self::Class? && (let final dynamic #t19 = #0#6#isSet ?{invalid-type} #0#6{invalid-type} : let final dynamic #t20 = #0#6#isSet = true in #0#6 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:77:17: Error: The getter 'method' isn't defined for the class 'Class?'.
- 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'method'.
case Class_(: var method): // Error: nullable member tear-off
- ^^^^^^" in null{<unresolved>}.method in true) || #0#0 is{ForNonNullableByDefault} self::Class? && (let final dynamic #t21 = extensionGetter#1 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:78:17: Error: The getter 'extensionGetter' isn't defined for the class 'Class?'.
+ ^^^^^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:77:17: Error: The getter 'method' isn't defined for the class 'Class?'.
+ - 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'method'.
+ case Class_(: var method): // Error: nullable member tear-off
+ ^^^^^^") || #0#0 is{ForNonNullableByDefault} self::Class? && (let final dynamic #t21 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:78:17: Error: The getter 'extensionGetter' isn't defined for the class 'Class?'.
- 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'extensionGetter'.
case Class_(: var extensionGetter): // Error: nullable extension member get
- ^^^^^^^^^^^^^^^" in null{<unresolved>}.extensionGetter in true) || #0#0 is{ForNonNullableByDefault} self::Class? && (let final dynamic #t22 = extensionMethod#1 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:79:17: Error: The getter 'extensionMethod' isn't defined for the class 'Class?'.
+ ^^^^^^^^^^^^^^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:78:17: Error: The getter 'extensionGetter' isn't defined for the class 'Class?'.
+ - 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'extensionGetter'.
+ case Class_(: var extensionGetter): // Error: nullable extension member get
+ ^^^^^^^^^^^^^^^") || #0#0 is{ForNonNullableByDefault} self::Class? && (let final dynamic #t22 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:79:17: Error: The getter 'extensionMethod' isn't defined for the class 'Class?'.
- 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'extensionMethod'.
case Class_(: var extensionMethod): // Error: nullable extension tear-off
- ^^^^^^^^^^^^^^^" in null{<unresolved>}.extensionMethod in true) || #0#0 is{ForNonNullableByDefault} () →? void && (let final dynamic #t23 = call#1 = #0#12#isSet ?{invalid-type} #0#12{invalid-type} : let final dynamic #t24 = #0#12#isSet = true in #0#12 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:80:21: Error: The getter 'call' isn't defined for the class 'void Function()?'.
+ ^^^^^^^^^^^^^^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:79:17: Error: The getter 'extensionMethod' isn't defined for the class 'Class?'.
+ - 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'extensionMethod'.
+ case Class_(: var extensionMethod): // Error: nullable extension tear-off
+ ^^^^^^^^^^^^^^^") || #0#0 is{ForNonNullableByDefault} () →? void && (let final dynamic #t23 = #0#12#isSet ?{invalid-type} #0#12{invalid-type} : let final dynamic #t24 = #0#12#isSet = true in #0#12 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:80:21: Error: The getter 'call' isn't defined for the class 'void Function()?'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'call'.
case Function1_(: var call): // Error: nullable function tear-off
- ^^^^" in null{<unresolved>}.call in true) || #0#0 is{ForNonNullableByDefault} (core::int, {required named: core::String})? && (let final dynamic #t25 = $1#1 = #0#14#isSet ?{invalid-type} #0#14{invalid-type} : let final dynamic #t26 = #0#14#isSet = true in #0#14 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:81:19: Error: The getter '\$1' isn't defined for the class '(int, {String named})?'.
+ ^^^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:80:21: Error: The getter 'call' isn't defined for the class 'void Function()?'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'call'.
+ case Function1_(: var call): // Error: nullable function tear-off
+ ^^^^") || #0#0 is{ForNonNullableByDefault} (core::int, {required named: core::String})? && (let final dynamic #t25 = #0#14#isSet ?{invalid-type} #0#14{invalid-type} : let final dynamic #t26 = #0#14#isSet = true in #0#14 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:81:19: Error: The getter '\$1' isn't defined for the class '(int, {String named})?'.
Try correcting the name to the name of an existing getter, or defining a getter or field named '\$1'.
case Record1_(: var \$1): // Error: nullable record index get
- ^^" in null{<unresolved>}.$1 in true) || #0#0 is{ForNonNullableByDefault} (core::int, {required named: core::String})? && (let final dynamic #t27 = named#1 = #0#15#isSet ?{invalid-type} #0#15{invalid-type} : let final dynamic #t28 = #0#15#isSet = true in #0#15 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:82:19: Error: The getter 'named' isn't defined for the class '(int, {String named})?'.
+ ^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:81:19: Error: The getter '\$1' isn't defined for the class '(int, {String named})?'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named '\$1'.
+ case Record1_(: var \$1): // Error: nullable record index get
+ ^^") || #0#0 is{ForNonNullableByDefault} (core::int, {required named: core::String})? && (let final dynamic #t27 = #0#15#isSet ?{invalid-type} #0#15{invalid-type} : let final dynamic #t28 = #0#15#isSet = true in #0#15 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:82:19: Error: The getter 'named' isn't defined for the class '(int, {String named})?'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'named'.
case Record1_(: var named): // Error: nullable record named get
- ^^^^^" in null{<unresolved>}.named in true) || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t29 = ambiguousField = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:83:16: Error: The getter 'ambiguousField' isn't defined for the class 'Class'.
+ ^^^^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:82:19: Error: The getter 'named' isn't defined for the class '(int, {String named})?'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'named'.
+ case Record1_(: var named): // Error: nullable record named get
+ ^^^^^") || #0#0 is{ForNonNullableByDefault} self::Class && (let final dynamic #t29 = invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:83:16: Error: The getter 'ambiguousField' isn't defined for the class 'Class'.
- 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'ambiguousField'.
case Class(: var ambiguousField): // Error: ambiguous get
- ^^^^^^^^^^^^^^" in null{<unresolved>}.ambiguousField in true) || #0#0 is{ForNonNullableByDefault} invalid-type) {
+ ^^^^^^^^^^^^^^" in invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:83:16: Error: The getter 'ambiguousField' isn't defined for the class 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'ambiguousField'.
+ case Class(: var ambiguousField): // Error: ambiguous get
+ ^^^^^^^^^^^^^^") || #0#0 is{ForNonNullableByDefault} invalid-type) {
}
}
}
@@ -345,10 +378,9 @@
if(self::_extension#0|<=(#15#0, #C1)) {
}
}
- {
- final self::Class #16#0 = cls;
- if(#16#0.{self::Class::<}(#C2){(core::int) → core::bool}) {
- }
+ if(invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:113:18: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+ if (cls case < '0') {} // Error: invalid instance < argument
+ ^") {
}
{
final self::Class #17#0 = cls;
@@ -378,23 +410,23 @@
- 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
Try correcting the name to the name of an existing method, or defining a method named '<'.
if (cls_ case < 0) {} // Error: nullable instance <
- ^" in null{<unresolved>}.<()) {
+ ^") {
}
if(invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:120:17: Error: The method '<=' isn't defined for the class 'Class?'.
- 'Class' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
Try correcting the name to the name of an existing method, or defining a method named '<='.
if (cls_ case <= 0) {} // Error: nullable extension <=
- ^^" in null{<unresolved>}.<=()) {
+ ^^") {
}
if(invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:121:19: Error: The method '<' isn't defined for the class 'String'.
Try correcting the name to the name of an existing method, or defining a method named '<'.
if (string case < 0) {} // Error: missing <
- ^" in null{<unresolved>}.<()) {
+ ^") {
}
if(invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:122:19: Error: The method '<=' isn't defined for the class 'String'.
Try correcting the name to the name of an existing method, or defining a method named '<='.
if (string case <= 0) {} // Error: ambiguous <=
- ^^" in null{<unresolved>}.<=()) {
+ ^^") {
}
{
final invalid-type #26#0 = invalid;
@@ -418,10 +450,10 @@
^^^^^^") {
}
}
- {
- final self::Class2 #29#0 = cls2;
- if(#29#0 =={self::Class2::==}{(self::Class2) → core::bool} #C1) {
- }
+ if(invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:126:20: Error: The argument type 'int' can't be assigned to the parameter type 'Class2'.
+ - 'Class2' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+ if (cls2 case == 0) {} // Error: invalid instance == argument
+ ^") {
}
{
final self::Class2 #30#0 = cls2;
@@ -435,10 +467,10 @@
^^^^^^")) {
}
}
- {
- final self::Class2 #31#0 = cls2;
- if(!(#31#0 =={self::Class2::==}{(self::Class2) → core::bool} #C1)) {
- }
+ if(invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:128:20: Error: The argument type 'int' can't be assigned to the parameter type 'Class2'.
+ - 'Class2' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+ if (cls2 case != 0) {} // Error: invalid instance == argument negated
+ ^") {
}
{
final self::Class2 #32#0 = cls2;
@@ -452,10 +484,10 @@
^^^^^^"){(self::Class2) → core::bool}) {
}
}
- {
- final self::Class2 #33#0 = cls2;
- if(#33#0.{self::Class2::<}(#C1){(self::Class2) → core::bool}) {
- }
+ if(invalid-expression "pkg/front_end/testcases/patterns/pattern_types.dart:130:19: Error: The argument type 'int' can't be assigned to the parameter type 'Class2'.
+ - 'Class2' is from 'pkg/front_end/testcases/patterns/pattern_types.dart'.
+ if (cls2 case < 0) {} // Error: invalid instance < argument
+ ^") {
}
{
final self::Class2? #34#0 = cls2_;
diff --git a/pkg/front_end/testcases/patterns/shared_errors.dart.strong.expect b/pkg/front_end/testcases/patterns/shared_errors.dart.strong.expect
index 3ae32de..29b1a29 100644
--- a/pkg/front_end/testcases/patterns/shared_errors.dart.strong.expect
+++ b/pkg/front_end/testcases/patterns/shared_errors.dart.strong.expect
@@ -104,12 +104,12 @@
}
static method argumentTypeNotAssignable(self::Class cls) → dynamic {
#L1:
- {
- final self::Class #0#0 = cls;
- if(#0#0.{self::Class::>=}(#C1){(self::Class) → core::bool}) {
- {
- core::print(0);
- }
+ if(invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:13:13: Error: The argument type 'int' can't be assigned to the parameter type 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/patterns/shared_errors.dart'.
+ case >= 0: // Error
+ ^") {
+ {
+ core::print(0);
}
}
}
@@ -137,7 +137,7 @@
core::String a = "";
block {
final dynamic #0#0 = list;
- if(!(#0#0{core::List<core::String>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C2 && (let final dynamic #t1 = a = #0#0{core::List<core::String>}.{core::List::[]}(0){(core::int) → core::String} in true) && (let final dynamic #t2 = #0#0{core::List<core::String>}.{core::List::[]}(1){(core::int) → core::String} in invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:31:7: Error: The variable 'a' is already assigned in this pattern.
+ if(!(#0#0{core::List<core::String>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final dynamic #t1 = a = #0#0{core::List<core::String>}.{core::List::[]}(0){(core::int) → core::String} in true) && (let final dynamic #t2 = #0#0{core::List<core::String>}.{core::List::[]}(1){(core::int) → core::String} in invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:31:7: Error: The variable 'a' is already assigned in this pattern.
Try renaming the variable.
[a, a] = list; // Error
^")))
@@ -146,15 +146,19 @@
}
static method duplicateRecordPatternField(dynamic o) → dynamic {
#L3:
- if(invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:36:28: Error: The field 'field' is already matched in this pattern.
+ {
+ final dynamic #0#0 = o;
+ late final core::int #0#2 = #0#0{self::Class}.{self::Class::field}{core::int};
+ if(invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:36:28: Error: The field 'field' is already matched in this pattern.
Try removing the duplicate field.
case (field: 1, field: 2): // Error
- ^" || invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:37:33: Error: The field 'field' is already matched in this pattern.
+ ^" || #0#0 is{ForNonNullableByDefault} self::Class && #C2 =={core::num::==}{(core::Object) → core::bool} #0#2 && (let final dynamic #t3 = #0#2 in invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:37:33: Error: The field 'field' is already matched in this pattern.
Try removing the duplicate field.
case Class(field: 1, field: 2): // Error
- ^") {
- {
- core::print(0);
+ ^")) {
+ {
+ core::print(0);
+ }
}
}
}
@@ -162,10 +166,12 @@
#L4:
{
final dynamic #0#0 = o;
- if(invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:44:16: Error: At most one rest element is allowed in a list or map pattern.
+ core::int #0#2;
+ core::bool #0#2#isSet = false;
+ if(#0#0 is{ForNonNullableByDefault} core::List<dynamic> && (#0#2#isSet ?{core::int} #0#2{core::int} : let final dynamic #t4 = #0#2#isSet = true in #0#2 = #0#0{core::List<dynamic>}.{core::List::length}{core::int}).{core::num::>=}(#C2){(core::num) → core::bool} && (let final dynamic #t5 = #0#0{core::List<dynamic>}.{core::List::[]}((#0#2#isSet ?{core::int} #0#2{core::int} : let final dynamic #t6 = #0#2#isSet = true in #0#2 = #0#0{core::List<dynamic>}.{core::List::length}{core::int}).{core::num::-}(1){(core::num) → core::int}){(core::int) → dynamic} in invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:44:16: Error: At most one rest element is allowed in a list or map pattern.
Try removing the duplicate rest element.
case [..., ...]: // Error
- ^" || #0#0 is{ForNonNullableByDefault} core::Map<dynamic, dynamic> && #0#0{core::Map<dynamic, dynamic>}.{core::Map::length}{core::int}.{core::num::>=}(#C1){(core::num) → core::bool}) {
+ ^") || #0#0 is{ForNonNullableByDefault} core::Map<dynamic, dynamic> && (#0#2#isSet ?{core::int} #0#2{core::int} : let final dynamic #t7 = #0#2#isSet = true in #0#2 = #0#0{core::Map<dynamic, dynamic>}.{core::Map::length}{core::int}).{core::num::>=}(#C3){(core::num) → core::bool}) {
}
}
}
@@ -176,7 +182,7 @@
final core::List<core::int> #0#0 = list;
late final core::int #0#4 = #0#0.{core::List::[]}(0){(core::int) → core::int};
late final core::int #0#6 = #0#0.{core::List::[]}(1){(core::int) → core::int};
- if(#0#0.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C2 && (let final dynamic #t3 = #0#4! in let final dynamic #t4 = a = #0#4! in true) && (!(#0#6 == null) ?{core::bool} let final dynamic #t5 = b = #0#6 in true : false)) {
+ if(#0#0.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final dynamic #t8 = #0#4! in let final dynamic #t9 = a = #0#4! in true) && (!(#0#6 == null) ?{core::bool} let final dynamic #t10 = b = #0#6 in true : false)) {
core::print(0);
}
}
@@ -184,23 +190,26 @@
static method nonBooleanCondition(core::int i) → dynamic {
{
final core::int #0#0 = i;
- if(#C1 =={core::num::==}{(core::Object) → core::bool} #0#0 && i) {
+ if(#C3 =={core::num::==}{(core::Object) → core::bool} #0#0 && invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:56:21: Error: Conditions must have a static type of 'bool'.
+Try changing the condition.
+ if (i case 0 when i) { // Error
+ ^") {
core::print(0);
}
}
}
static method refutablePatternInIrrefutableContext(core::int? x) → dynamic {
core::int a;
- if(!invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:62:9: Error: Refutable patterns can't be used in an irrefutable context.
-Try using an if-case, a 'switch' statement, or a 'switch' expression instead.
- var (a?) = x; // Error
- ^")
- throw new _in::ReachabilityError::•();
+ {
+ final dynamic #0#0 = x;
+ if(!(!(#0#0 == null) ?{core::bool} let final dynamic #t11 = a = #0#0{core::int} in true : false))
+ throw new _in::ReachabilityError::•();
+ }
}
static method restPatternNotLastInMap(dynamic o) → dynamic {
{
final dynamic #0#0 = o;
- if(#0#0 is{ForNonNullableByDefault} core::Map<dynamic, dynamic> && #0#0{core::Map<dynamic, dynamic>}.{core::Map::length}{core::int}.{core::num::>=}(#C3){(core::num) → core::bool} && #0#0{core::Map<dynamic, dynamic>}.{core::Map::containsKey}(#C4){(core::Object?) → core::bool} && #C5 =={core::num::==}{(core::Object) → core::bool} #0#0{core::Map<dynamic, dynamic>}.{core::Map::[]}(#C4){(core::Object?) → dynamic}) {
+ if(#0#0 is{ForNonNullableByDefault} core::Map<dynamic, dynamic> && #0#0{core::Map<dynamic, dynamic>}.{core::Map::length}{core::int}.{core::num::>=}(#C2){(core::num) → core::bool} && #0#0{core::Map<dynamic, dynamic>}.{core::Map::containsKey}(#C4){(core::Object?) → core::bool} && #C5 =={core::num::==}{(core::Object) → core::bool} #0#0{core::Map<dynamic, dynamic>}.{core::Map::[]}(#C4){(core::Object?) → dynamic}) {
core::print(0);
}
}
@@ -208,16 +217,16 @@
static method restPatternWithSubPatternInMap(dynamic o) → dynamic {
{
final dynamic #0#0 = o;
- if(#0#0 is{ForNonNullableByDefault} core::Map<dynamic, dynamic> && #0#0{core::Map<dynamic, dynamic>}.{core::Map::length}{core::int}.{core::num::>=}(#C3){(core::num) → core::bool} && #0#0{core::Map<dynamic, dynamic>}.{core::Map::containsKey}(#C4){(core::Object?) → core::bool} && #C5 =={core::num::==}{(core::Object) → core::bool} #0#0{core::Map<dynamic, dynamic>}.{core::Map::[]}(#C4){(core::Object?) → dynamic}) {
+ if(#0#0 is{ForNonNullableByDefault} core::Map<dynamic, dynamic> && #0#0{core::Map<dynamic, dynamic>}.{core::Map::length}{core::int}.{core::num::>=}(#C2){(core::num) → core::bool} && #0#0{core::Map<dynamic, dynamic>}.{core::Map::containsKey}(#C4){(core::Object?) → core::bool} && #C5 =={core::num::==}{(core::Object) → core::bool} #0#0{core::Map<dynamic, dynamic>}.{core::Map::[]}(#C4){(core::Object?) → dynamic}) {
core::print(0);
}
}
}
constants {
- #C1 = 0
- #C2 = 2
- #C3 = 1
+ #C1 = 2
+ #C2 = 1
+ #C3 = 0
#C4 = 5
#C5 = 3
}
diff --git a/pkg/front_end/testcases/patterns/shared_errors.dart.strong.transformed.expect b/pkg/front_end/testcases/patterns/shared_errors.dart.strong.transformed.expect
new file mode 100644
index 0000000..e53cba4
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/shared_errors.dart.strong.transformed.expect
@@ -0,0 +1,238 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:13:13: Error: The argument type 'int' can't be assigned to the parameter type 'Class'.
+// - 'Class' is from 'pkg/front_end/testcases/patterns/shared_errors.dart'.
+// case >= 0: // Error
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:20:10: Error: A value of type 'Class' can't be assigned to a variable of type 'bool'.
+// - 'Class' is from 'pkg/front_end/testcases/patterns/shared_errors.dart'.
+// case > 0: // Error
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:26:12: Error: The matched value of type 'List<String>' isn't assignable to the required type 'List<int>'.
+// - 'List' is from 'dart:core'.
+// Try changing the required type of the pattern, or the matched value type.
+// var <int>[a] = list; // Error
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:31:7: Error: The variable 'a' is already assigned in this pattern.
+// Try renaming the variable.
+// [a, a] = list; // Error
+// ^
+// pkg/front_end/testcases/patterns/shared_errors.dart:31:4: Context: The first assigned variable pattern.
+// [a, a] = list; // Error
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:36:28: Error: The field 'field' is already matched in this pattern.
+// Try removing the duplicate field.
+// case (field: 1, field: 2): // Error
+// ^
+// pkg/front_end/testcases/patterns/shared_errors.dart:36:18: Context: The first field.
+// case (field: 1, field: 2): // Error
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:37:33: Error: The field 'field' is already matched in this pattern.
+// Try removing the duplicate field.
+// case Class(field: 1, field: 2): // Error
+// ^
+// pkg/front_end/testcases/patterns/shared_errors.dart:37:23: Context: The first field.
+// case Class(field: 1, field: 2): // Error
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:45:11: Error: At most one rest element is allowed in a list or map pattern.
+// Try removing the duplicate rest element.
+// case {..., ...}: // Error
+// ^
+// pkg/front_end/testcases/patterns/shared_errors.dart:45:16: Context: The first rest element.
+// case {..., ...}: // Error
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:44:16: Error: At most one rest element is allowed in a list or map pattern.
+// Try removing the duplicate rest element.
+// case [..., ...]: // Error
+// ^
+// pkg/front_end/testcases/patterns/shared_errors.dart:44:11: Context: The first rest element.
+// case [..., ...]: // Error
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:50:23: Warning: The null-assert pattern will have no effect because the matched type isn't nullable.
+// Try replacing the null-assert pattern with its nested pattern.
+// if (list case [var a!, var b?]) { // Warnings
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:50:31: Warning: The null-check pattern will have no effect because the matched type isn't nullable.
+// Try replacing the null-check pattern with its nested pattern.
+// if (list case [var a!, var b?]) { // Warnings
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:56:21: Error: Conditions must have a static type of 'bool'.
+// Try changing the condition.
+// if (i case 0 when i) { // Error
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:62:9: Error: Refutable patterns can't be used in an irrefutable context.
+// Try using an if-case, a 'switch' statement, or a 'switch' expression instead.
+// var (a?) = x; // Error
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:66:15: Error: The '...' pattern can appear only at the end in map patterns.
+// if (o case {..., 5: 3}) { // Error
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:72:21: Error: A rest element in a map pattern can't have a subpattern.
+// Try removing the subpattern.
+// if (o case {5: 3, ...var a}) { // Error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class Class extends core::Object {
+ synthetic constructor •() → self::Class
+ : super core::Object::•()
+ ;
+ get field() → core::int
+ return 42;
+ operator >=(self::Class cls) → core::bool
+ return true;
+ operator >(core::int i) → self::Class
+ return new self::Class::•();
+}
+static method argumentTypeNotAssignable(self::Class cls) → dynamic {
+ #L1:
+ if(invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:13:13: Error: The argument type 'int' can't be assigned to the parameter type 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/patterns/shared_errors.dart'.
+ case >= 0: // Error
+ ^") {
+ {
+ core::print(0);
+ }
+ }
+}
+static method relationalPatternOperatorReturnTypeNotAssignableToBool(self::Class cls) → dynamic {
+ #L2:
+ if(invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:20:10: Error: A value of type 'Class' can't be assigned to a variable of type 'bool'.
+ - 'Class' is from 'pkg/front_end/testcases/patterns/shared_errors.dart'.
+ case > 0: // Error
+ ^") {
+ {
+ core::print(0);
+ }
+ }
+}
+static method patternTypeMismatchInIrrefutableContext(core::List<core::String> list) → dynamic {
+ core::int a;
+ if(!invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:26:12: Error: The matched value of type 'List<String>' isn't assignable to the required type 'List<int>'.
+ - 'List' is from 'dart:core'.
+Try changing the required type of the pattern, or the matched value type.
+ var <int>[a] = list; // Error
+ ^")
+ throw new _in::ReachabilityError::•();
+}
+static method duplicateAssignmentPatternVariable(core::List<core::String> list) → dynamic {
+ core::String a = "";
+ block {
+ final dynamic #0#0 = list;
+ if(!(#0#0{core::List<core::String>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final core::String #t1 = a = #0#0{core::List<core::String>}.{core::List::[]}(0){(core::int) → core::String} in true) && (let final core::String #t2 = #0#0{core::List<core::String>}.{core::List::[]}(1){(core::int) → core::String} in invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:31:7: Error: The variable 'a' is already assigned in this pattern.
+Try renaming the variable.
+ [a, a] = list; // Error
+ ^")))
+ throw new _in::ReachabilityError::•();
+ } =>#0#0;
+}
+static method duplicateRecordPatternField(dynamic o) → dynamic {
+ #L3:
+ {
+ final dynamic #0#0 = o;
+ function ##0#2#initializer() → core::int
+ return #0#0{self::Class}.{self::Class::field}{core::int};
+ late final core::int #0#2 = ##0#2#initializer(){() → core::int};
+ if(invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:36:28: Error: The field 'field' is already matched in this pattern.
+Try removing the duplicate field.
+ case (field: 1, field: 2): // Error
+ ^" || #0#0 is{ForNonNullableByDefault} self::Class && #C2 =={core::num::==}{(core::Object) → core::bool} #0#2 && (let final core::int #t3 = #0#2 in invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:37:33: Error: The field 'field' is already matched in this pattern.
+Try removing the duplicate field.
+ case Class(field: 1, field: 2): // Error
+ ^")) {
+ {
+ core::print(0);
+ }
+ }
+ }
+}
+static method duplicateRestPattern(dynamic o) → dynamic {
+ #L4:
+ {
+ final dynamic #0#0 = o;
+ core::int #0#2;
+ core::bool #0#2#isSet = false;
+ if(#0#0 is{ForNonNullableByDefault} core::List<dynamic> && (#0#2#isSet ?{core::int} #0#2{core::int} : let final core::bool* #t4 = #0#2#isSet = true in #0#2 = #0#0{core::List<dynamic>}.{core::List::length}{core::int}).{core::num::>=}(#C2){(core::num) → core::bool} && (let final dynamic #t5 = #0#0{core::List<dynamic>}.{core::List::[]}((#0#2#isSet ?{core::int} #0#2{core::int} : let final core::bool* #t6 = #0#2#isSet = true in #0#2 = #0#0{core::List<dynamic>}.{core::List::length}{core::int}).{core::num::-}(1){(core::num) → core::int}){(core::int) → dynamic} in invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:44:16: Error: At most one rest element is allowed in a list or map pattern.
+Try removing the duplicate rest element.
+ case [..., ...]: // Error
+ ^") || #0#0 is{ForNonNullableByDefault} core::Map<dynamic, dynamic> && (#0#2#isSet ?{core::int} #0#2{core::int} : let final core::bool* #t7 = #0#2#isSet = true in #0#2 = #0#0{core::Map<dynamic, dynamic>}.{core::Map::length}{core::int}).{core::num::>=}(#C3){(core::num) → core::bool}) {
+ }
+ }
+}
+static method matchedTypeIsStrictlyNonNullable(core::List<core::int> list) → dynamic {
+ {
+ core::int a;
+ core::int b;
+ final core::List<core::int> #0#0 = list;
+ function ##0#4#initializer() → core::int
+ return #0#0.{core::List::[]}(0){(core::int) → core::int};
+ late final core::int #0#4 = ##0#4#initializer(){() → core::int};
+ function ##0#6#initializer() → core::int
+ return #0#0.{core::List::[]}(1){(core::int) → core::int};
+ late final core::int #0#6 = ##0#6#initializer(){() → core::int};
+ if(#0#0.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final core::int #t8 = #0#4! in let final core::int #t9 = a = #0#4! in true) && (!(#0#6 == null) ?{core::bool} let final core::int #t10 = b = #0#6 in true : false)) {
+ core::print(0);
+ }
+ }
+}
+static method nonBooleanCondition(core::int i) → dynamic {
+ {
+ final core::int #0#0 = i;
+ if(#C3 =={core::num::==}{(core::Object) → core::bool} #0#0 && invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:56:21: Error: Conditions must have a static type of 'bool'.
+Try changing the condition.
+ if (i case 0 when i) { // Error
+ ^") {
+ core::print(0);
+ }
+ }
+}
+static method refutablePatternInIrrefutableContext(core::int? x) → dynamic {
+ core::int a;
+ {
+ final dynamic #0#0 = x;
+ if(!(!(#0#0 == null) ?{core::bool} let final core::int #t11 = a = #0#0{core::int} in true : false))
+ throw new _in::ReachabilityError::•();
+ }
+}
+static method restPatternNotLastInMap(dynamic o) → dynamic {
+ {
+ final dynamic #0#0 = o;
+ if(#0#0 is{ForNonNullableByDefault} core::Map<dynamic, dynamic> && #0#0{core::Map<dynamic, dynamic>}.{core::Map::length}{core::int}.{core::num::>=}(#C2){(core::num) → core::bool} && #0#0{core::Map<dynamic, dynamic>}.{core::Map::containsKey}(#C4){(core::Object?) → core::bool} && #C5 =={core::num::==}{(core::Object) → core::bool} #0#0{core::Map<dynamic, dynamic>}.{core::Map::[]}(#C4){(core::Object?) → dynamic}) {
+ core::print(0);
+ }
+ }
+}
+static method restPatternWithSubPatternInMap(dynamic o) → dynamic {
+ {
+ final dynamic #0#0 = o;
+ if(#0#0 is{ForNonNullableByDefault} core::Map<dynamic, dynamic> && #0#0{core::Map<dynamic, dynamic>}.{core::Map::length}{core::int}.{core::num::>=}(#C2){(core::num) → core::bool} && #0#0{core::Map<dynamic, dynamic>}.{core::Map::containsKey}(#C4){(core::Object?) → core::bool} && #C5 =={core::num::==}{(core::Object) → core::bool} #0#0{core::Map<dynamic, dynamic>}.{core::Map::[]}(#C4){(core::Object?) → dynamic}) {
+ core::print(0);
+ }
+ }
+}
+
+constants {
+ #C1 = 2
+ #C2 = 1
+ #C3 = 0
+ #C4 = 5
+ #C5 = 3
+}
diff --git a/pkg/front_end/testcases/patterns/shared_errors.dart.weak.expect b/pkg/front_end/testcases/patterns/shared_errors.dart.weak.expect
index 3ae32de..29b1a29 100644
--- a/pkg/front_end/testcases/patterns/shared_errors.dart.weak.expect
+++ b/pkg/front_end/testcases/patterns/shared_errors.dart.weak.expect
@@ -104,12 +104,12 @@
}
static method argumentTypeNotAssignable(self::Class cls) → dynamic {
#L1:
- {
- final self::Class #0#0 = cls;
- if(#0#0.{self::Class::>=}(#C1){(self::Class) → core::bool}) {
- {
- core::print(0);
- }
+ if(invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:13:13: Error: The argument type 'int' can't be assigned to the parameter type 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/patterns/shared_errors.dart'.
+ case >= 0: // Error
+ ^") {
+ {
+ core::print(0);
}
}
}
@@ -137,7 +137,7 @@
core::String a = "";
block {
final dynamic #0#0 = list;
- if(!(#0#0{core::List<core::String>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C2 && (let final dynamic #t1 = a = #0#0{core::List<core::String>}.{core::List::[]}(0){(core::int) → core::String} in true) && (let final dynamic #t2 = #0#0{core::List<core::String>}.{core::List::[]}(1){(core::int) → core::String} in invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:31:7: Error: The variable 'a' is already assigned in this pattern.
+ if(!(#0#0{core::List<core::String>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final dynamic #t1 = a = #0#0{core::List<core::String>}.{core::List::[]}(0){(core::int) → core::String} in true) && (let final dynamic #t2 = #0#0{core::List<core::String>}.{core::List::[]}(1){(core::int) → core::String} in invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:31:7: Error: The variable 'a' is already assigned in this pattern.
Try renaming the variable.
[a, a] = list; // Error
^")))
@@ -146,15 +146,19 @@
}
static method duplicateRecordPatternField(dynamic o) → dynamic {
#L3:
- if(invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:36:28: Error: The field 'field' is already matched in this pattern.
+ {
+ final dynamic #0#0 = o;
+ late final core::int #0#2 = #0#0{self::Class}.{self::Class::field}{core::int};
+ if(invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:36:28: Error: The field 'field' is already matched in this pattern.
Try removing the duplicate field.
case (field: 1, field: 2): // Error
- ^" || invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:37:33: Error: The field 'field' is already matched in this pattern.
+ ^" || #0#0 is{ForNonNullableByDefault} self::Class && #C2 =={core::num::==}{(core::Object) → core::bool} #0#2 && (let final dynamic #t3 = #0#2 in invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:37:33: Error: The field 'field' is already matched in this pattern.
Try removing the duplicate field.
case Class(field: 1, field: 2): // Error
- ^") {
- {
- core::print(0);
+ ^")) {
+ {
+ core::print(0);
+ }
}
}
}
@@ -162,10 +166,12 @@
#L4:
{
final dynamic #0#0 = o;
- if(invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:44:16: Error: At most one rest element is allowed in a list or map pattern.
+ core::int #0#2;
+ core::bool #0#2#isSet = false;
+ if(#0#0 is{ForNonNullableByDefault} core::List<dynamic> && (#0#2#isSet ?{core::int} #0#2{core::int} : let final dynamic #t4 = #0#2#isSet = true in #0#2 = #0#0{core::List<dynamic>}.{core::List::length}{core::int}).{core::num::>=}(#C2){(core::num) → core::bool} && (let final dynamic #t5 = #0#0{core::List<dynamic>}.{core::List::[]}((#0#2#isSet ?{core::int} #0#2{core::int} : let final dynamic #t6 = #0#2#isSet = true in #0#2 = #0#0{core::List<dynamic>}.{core::List::length}{core::int}).{core::num::-}(1){(core::num) → core::int}){(core::int) → dynamic} in invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:44:16: Error: At most one rest element is allowed in a list or map pattern.
Try removing the duplicate rest element.
case [..., ...]: // Error
- ^" || #0#0 is{ForNonNullableByDefault} core::Map<dynamic, dynamic> && #0#0{core::Map<dynamic, dynamic>}.{core::Map::length}{core::int}.{core::num::>=}(#C1){(core::num) → core::bool}) {
+ ^") || #0#0 is{ForNonNullableByDefault} core::Map<dynamic, dynamic> && (#0#2#isSet ?{core::int} #0#2{core::int} : let final dynamic #t7 = #0#2#isSet = true in #0#2 = #0#0{core::Map<dynamic, dynamic>}.{core::Map::length}{core::int}).{core::num::>=}(#C3){(core::num) → core::bool}) {
}
}
}
@@ -176,7 +182,7 @@
final core::List<core::int> #0#0 = list;
late final core::int #0#4 = #0#0.{core::List::[]}(0){(core::int) → core::int};
late final core::int #0#6 = #0#0.{core::List::[]}(1){(core::int) → core::int};
- if(#0#0.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C2 && (let final dynamic #t3 = #0#4! in let final dynamic #t4 = a = #0#4! in true) && (!(#0#6 == null) ?{core::bool} let final dynamic #t5 = b = #0#6 in true : false)) {
+ if(#0#0.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final dynamic #t8 = #0#4! in let final dynamic #t9 = a = #0#4! in true) && (!(#0#6 == null) ?{core::bool} let final dynamic #t10 = b = #0#6 in true : false)) {
core::print(0);
}
}
@@ -184,23 +190,26 @@
static method nonBooleanCondition(core::int i) → dynamic {
{
final core::int #0#0 = i;
- if(#C1 =={core::num::==}{(core::Object) → core::bool} #0#0 && i) {
+ if(#C3 =={core::num::==}{(core::Object) → core::bool} #0#0 && invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:56:21: Error: Conditions must have a static type of 'bool'.
+Try changing the condition.
+ if (i case 0 when i) { // Error
+ ^") {
core::print(0);
}
}
}
static method refutablePatternInIrrefutableContext(core::int? x) → dynamic {
core::int a;
- if(!invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:62:9: Error: Refutable patterns can't be used in an irrefutable context.
-Try using an if-case, a 'switch' statement, or a 'switch' expression instead.
- var (a?) = x; // Error
- ^")
- throw new _in::ReachabilityError::•();
+ {
+ final dynamic #0#0 = x;
+ if(!(!(#0#0 == null) ?{core::bool} let final dynamic #t11 = a = #0#0{core::int} in true : false))
+ throw new _in::ReachabilityError::•();
+ }
}
static method restPatternNotLastInMap(dynamic o) → dynamic {
{
final dynamic #0#0 = o;
- if(#0#0 is{ForNonNullableByDefault} core::Map<dynamic, dynamic> && #0#0{core::Map<dynamic, dynamic>}.{core::Map::length}{core::int}.{core::num::>=}(#C3){(core::num) → core::bool} && #0#0{core::Map<dynamic, dynamic>}.{core::Map::containsKey}(#C4){(core::Object?) → core::bool} && #C5 =={core::num::==}{(core::Object) → core::bool} #0#0{core::Map<dynamic, dynamic>}.{core::Map::[]}(#C4){(core::Object?) → dynamic}) {
+ if(#0#0 is{ForNonNullableByDefault} core::Map<dynamic, dynamic> && #0#0{core::Map<dynamic, dynamic>}.{core::Map::length}{core::int}.{core::num::>=}(#C2){(core::num) → core::bool} && #0#0{core::Map<dynamic, dynamic>}.{core::Map::containsKey}(#C4){(core::Object?) → core::bool} && #C5 =={core::num::==}{(core::Object) → core::bool} #0#0{core::Map<dynamic, dynamic>}.{core::Map::[]}(#C4){(core::Object?) → dynamic}) {
core::print(0);
}
}
@@ -208,16 +217,16 @@
static method restPatternWithSubPatternInMap(dynamic o) → dynamic {
{
final dynamic #0#0 = o;
- if(#0#0 is{ForNonNullableByDefault} core::Map<dynamic, dynamic> && #0#0{core::Map<dynamic, dynamic>}.{core::Map::length}{core::int}.{core::num::>=}(#C3){(core::num) → core::bool} && #0#0{core::Map<dynamic, dynamic>}.{core::Map::containsKey}(#C4){(core::Object?) → core::bool} && #C5 =={core::num::==}{(core::Object) → core::bool} #0#0{core::Map<dynamic, dynamic>}.{core::Map::[]}(#C4){(core::Object?) → dynamic}) {
+ if(#0#0 is{ForNonNullableByDefault} core::Map<dynamic, dynamic> && #0#0{core::Map<dynamic, dynamic>}.{core::Map::length}{core::int}.{core::num::>=}(#C2){(core::num) → core::bool} && #0#0{core::Map<dynamic, dynamic>}.{core::Map::containsKey}(#C4){(core::Object?) → core::bool} && #C5 =={core::num::==}{(core::Object) → core::bool} #0#0{core::Map<dynamic, dynamic>}.{core::Map::[]}(#C4){(core::Object?) → dynamic}) {
core::print(0);
}
}
}
constants {
- #C1 = 0
- #C2 = 2
- #C3 = 1
+ #C1 = 2
+ #C2 = 1
+ #C3 = 0
#C4 = 5
#C5 = 3
}
diff --git a/pkg/front_end/testcases/patterns/shared_errors.dart.weak.modular.expect b/pkg/front_end/testcases/patterns/shared_errors.dart.weak.modular.expect
index 3ae32de..29b1a29 100644
--- a/pkg/front_end/testcases/patterns/shared_errors.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/patterns/shared_errors.dart.weak.modular.expect
@@ -104,12 +104,12 @@
}
static method argumentTypeNotAssignable(self::Class cls) → dynamic {
#L1:
- {
- final self::Class #0#0 = cls;
- if(#0#0.{self::Class::>=}(#C1){(self::Class) → core::bool}) {
- {
- core::print(0);
- }
+ if(invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:13:13: Error: The argument type 'int' can't be assigned to the parameter type 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/patterns/shared_errors.dart'.
+ case >= 0: // Error
+ ^") {
+ {
+ core::print(0);
}
}
}
@@ -137,7 +137,7 @@
core::String a = "";
block {
final dynamic #0#0 = list;
- if(!(#0#0{core::List<core::String>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C2 && (let final dynamic #t1 = a = #0#0{core::List<core::String>}.{core::List::[]}(0){(core::int) → core::String} in true) && (let final dynamic #t2 = #0#0{core::List<core::String>}.{core::List::[]}(1){(core::int) → core::String} in invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:31:7: Error: The variable 'a' is already assigned in this pattern.
+ if(!(#0#0{core::List<core::String>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final dynamic #t1 = a = #0#0{core::List<core::String>}.{core::List::[]}(0){(core::int) → core::String} in true) && (let final dynamic #t2 = #0#0{core::List<core::String>}.{core::List::[]}(1){(core::int) → core::String} in invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:31:7: Error: The variable 'a' is already assigned in this pattern.
Try renaming the variable.
[a, a] = list; // Error
^")))
@@ -146,15 +146,19 @@
}
static method duplicateRecordPatternField(dynamic o) → dynamic {
#L3:
- if(invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:36:28: Error: The field 'field' is already matched in this pattern.
+ {
+ final dynamic #0#0 = o;
+ late final core::int #0#2 = #0#0{self::Class}.{self::Class::field}{core::int};
+ if(invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:36:28: Error: The field 'field' is already matched in this pattern.
Try removing the duplicate field.
case (field: 1, field: 2): // Error
- ^" || invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:37:33: Error: The field 'field' is already matched in this pattern.
+ ^" || #0#0 is{ForNonNullableByDefault} self::Class && #C2 =={core::num::==}{(core::Object) → core::bool} #0#2 && (let final dynamic #t3 = #0#2 in invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:37:33: Error: The field 'field' is already matched in this pattern.
Try removing the duplicate field.
case Class(field: 1, field: 2): // Error
- ^") {
- {
- core::print(0);
+ ^")) {
+ {
+ core::print(0);
+ }
}
}
}
@@ -162,10 +166,12 @@
#L4:
{
final dynamic #0#0 = o;
- if(invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:44:16: Error: At most one rest element is allowed in a list or map pattern.
+ core::int #0#2;
+ core::bool #0#2#isSet = false;
+ if(#0#0 is{ForNonNullableByDefault} core::List<dynamic> && (#0#2#isSet ?{core::int} #0#2{core::int} : let final dynamic #t4 = #0#2#isSet = true in #0#2 = #0#0{core::List<dynamic>}.{core::List::length}{core::int}).{core::num::>=}(#C2){(core::num) → core::bool} && (let final dynamic #t5 = #0#0{core::List<dynamic>}.{core::List::[]}((#0#2#isSet ?{core::int} #0#2{core::int} : let final dynamic #t6 = #0#2#isSet = true in #0#2 = #0#0{core::List<dynamic>}.{core::List::length}{core::int}).{core::num::-}(1){(core::num) → core::int}){(core::int) → dynamic} in invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:44:16: Error: At most one rest element is allowed in a list or map pattern.
Try removing the duplicate rest element.
case [..., ...]: // Error
- ^" || #0#0 is{ForNonNullableByDefault} core::Map<dynamic, dynamic> && #0#0{core::Map<dynamic, dynamic>}.{core::Map::length}{core::int}.{core::num::>=}(#C1){(core::num) → core::bool}) {
+ ^") || #0#0 is{ForNonNullableByDefault} core::Map<dynamic, dynamic> && (#0#2#isSet ?{core::int} #0#2{core::int} : let final dynamic #t7 = #0#2#isSet = true in #0#2 = #0#0{core::Map<dynamic, dynamic>}.{core::Map::length}{core::int}).{core::num::>=}(#C3){(core::num) → core::bool}) {
}
}
}
@@ -176,7 +182,7 @@
final core::List<core::int> #0#0 = list;
late final core::int #0#4 = #0#0.{core::List::[]}(0){(core::int) → core::int};
late final core::int #0#6 = #0#0.{core::List::[]}(1){(core::int) → core::int};
- if(#0#0.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C2 && (let final dynamic #t3 = #0#4! in let final dynamic #t4 = a = #0#4! in true) && (!(#0#6 == null) ?{core::bool} let final dynamic #t5 = b = #0#6 in true : false)) {
+ if(#0#0.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final dynamic #t8 = #0#4! in let final dynamic #t9 = a = #0#4! in true) && (!(#0#6 == null) ?{core::bool} let final dynamic #t10 = b = #0#6 in true : false)) {
core::print(0);
}
}
@@ -184,23 +190,26 @@
static method nonBooleanCondition(core::int i) → dynamic {
{
final core::int #0#0 = i;
- if(#C1 =={core::num::==}{(core::Object) → core::bool} #0#0 && i) {
+ if(#C3 =={core::num::==}{(core::Object) → core::bool} #0#0 && invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:56:21: Error: Conditions must have a static type of 'bool'.
+Try changing the condition.
+ if (i case 0 when i) { // Error
+ ^") {
core::print(0);
}
}
}
static method refutablePatternInIrrefutableContext(core::int? x) → dynamic {
core::int a;
- if(!invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:62:9: Error: Refutable patterns can't be used in an irrefutable context.
-Try using an if-case, a 'switch' statement, or a 'switch' expression instead.
- var (a?) = x; // Error
- ^")
- throw new _in::ReachabilityError::•();
+ {
+ final dynamic #0#0 = x;
+ if(!(!(#0#0 == null) ?{core::bool} let final dynamic #t11 = a = #0#0{core::int} in true : false))
+ throw new _in::ReachabilityError::•();
+ }
}
static method restPatternNotLastInMap(dynamic o) → dynamic {
{
final dynamic #0#0 = o;
- if(#0#0 is{ForNonNullableByDefault} core::Map<dynamic, dynamic> && #0#0{core::Map<dynamic, dynamic>}.{core::Map::length}{core::int}.{core::num::>=}(#C3){(core::num) → core::bool} && #0#0{core::Map<dynamic, dynamic>}.{core::Map::containsKey}(#C4){(core::Object?) → core::bool} && #C5 =={core::num::==}{(core::Object) → core::bool} #0#0{core::Map<dynamic, dynamic>}.{core::Map::[]}(#C4){(core::Object?) → dynamic}) {
+ if(#0#0 is{ForNonNullableByDefault} core::Map<dynamic, dynamic> && #0#0{core::Map<dynamic, dynamic>}.{core::Map::length}{core::int}.{core::num::>=}(#C2){(core::num) → core::bool} && #0#0{core::Map<dynamic, dynamic>}.{core::Map::containsKey}(#C4){(core::Object?) → core::bool} && #C5 =={core::num::==}{(core::Object) → core::bool} #0#0{core::Map<dynamic, dynamic>}.{core::Map::[]}(#C4){(core::Object?) → dynamic}) {
core::print(0);
}
}
@@ -208,16 +217,16 @@
static method restPatternWithSubPatternInMap(dynamic o) → dynamic {
{
final dynamic #0#0 = o;
- if(#0#0 is{ForNonNullableByDefault} core::Map<dynamic, dynamic> && #0#0{core::Map<dynamic, dynamic>}.{core::Map::length}{core::int}.{core::num::>=}(#C3){(core::num) → core::bool} && #0#0{core::Map<dynamic, dynamic>}.{core::Map::containsKey}(#C4){(core::Object?) → core::bool} && #C5 =={core::num::==}{(core::Object) → core::bool} #0#0{core::Map<dynamic, dynamic>}.{core::Map::[]}(#C4){(core::Object?) → dynamic}) {
+ if(#0#0 is{ForNonNullableByDefault} core::Map<dynamic, dynamic> && #0#0{core::Map<dynamic, dynamic>}.{core::Map::length}{core::int}.{core::num::>=}(#C2){(core::num) → core::bool} && #0#0{core::Map<dynamic, dynamic>}.{core::Map::containsKey}(#C4){(core::Object?) → core::bool} && #C5 =={core::num::==}{(core::Object) → core::bool} #0#0{core::Map<dynamic, dynamic>}.{core::Map::[]}(#C4){(core::Object?) → dynamic}) {
core::print(0);
}
}
}
constants {
- #C1 = 0
- #C2 = 2
- #C3 = 1
+ #C1 = 2
+ #C2 = 1
+ #C3 = 0
#C4 = 5
#C5 = 3
}
diff --git a/pkg/front_end/testcases/patterns/shared_errors.dart.weak.transformed.expect b/pkg/front_end/testcases/patterns/shared_errors.dart.weak.transformed.expect
new file mode 100644
index 0000000..e53cba4
--- /dev/null
+++ b/pkg/front_end/testcases/patterns/shared_errors.dart.weak.transformed.expect
@@ -0,0 +1,238 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:13:13: Error: The argument type 'int' can't be assigned to the parameter type 'Class'.
+// - 'Class' is from 'pkg/front_end/testcases/patterns/shared_errors.dart'.
+// case >= 0: // Error
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:20:10: Error: A value of type 'Class' can't be assigned to a variable of type 'bool'.
+// - 'Class' is from 'pkg/front_end/testcases/patterns/shared_errors.dart'.
+// case > 0: // Error
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:26:12: Error: The matched value of type 'List<String>' isn't assignable to the required type 'List<int>'.
+// - 'List' is from 'dart:core'.
+// Try changing the required type of the pattern, or the matched value type.
+// var <int>[a] = list; // Error
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:31:7: Error: The variable 'a' is already assigned in this pattern.
+// Try renaming the variable.
+// [a, a] = list; // Error
+// ^
+// pkg/front_end/testcases/patterns/shared_errors.dart:31:4: Context: The first assigned variable pattern.
+// [a, a] = list; // Error
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:36:28: Error: The field 'field' is already matched in this pattern.
+// Try removing the duplicate field.
+// case (field: 1, field: 2): // Error
+// ^
+// pkg/front_end/testcases/patterns/shared_errors.dart:36:18: Context: The first field.
+// case (field: 1, field: 2): // Error
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:37:33: Error: The field 'field' is already matched in this pattern.
+// Try removing the duplicate field.
+// case Class(field: 1, field: 2): // Error
+// ^
+// pkg/front_end/testcases/patterns/shared_errors.dart:37:23: Context: The first field.
+// case Class(field: 1, field: 2): // Error
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:45:11: Error: At most one rest element is allowed in a list or map pattern.
+// Try removing the duplicate rest element.
+// case {..., ...}: // Error
+// ^
+// pkg/front_end/testcases/patterns/shared_errors.dart:45:16: Context: The first rest element.
+// case {..., ...}: // Error
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:44:16: Error: At most one rest element is allowed in a list or map pattern.
+// Try removing the duplicate rest element.
+// case [..., ...]: // Error
+// ^
+// pkg/front_end/testcases/patterns/shared_errors.dart:44:11: Context: The first rest element.
+// case [..., ...]: // Error
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:50:23: Warning: The null-assert pattern will have no effect because the matched type isn't nullable.
+// Try replacing the null-assert pattern with its nested pattern.
+// if (list case [var a!, var b?]) { // Warnings
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:50:31: Warning: The null-check pattern will have no effect because the matched type isn't nullable.
+// Try replacing the null-check pattern with its nested pattern.
+// if (list case [var a!, var b?]) { // Warnings
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:56:21: Error: Conditions must have a static type of 'bool'.
+// Try changing the condition.
+// if (i case 0 when i) { // Error
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:62:9: Error: Refutable patterns can't be used in an irrefutable context.
+// Try using an if-case, a 'switch' statement, or a 'switch' expression instead.
+// var (a?) = x; // Error
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:66:15: Error: The '...' pattern can appear only at the end in map patterns.
+// if (o case {..., 5: 3}) { // Error
+// ^
+//
+// pkg/front_end/testcases/patterns/shared_errors.dart:72:21: Error: A rest element in a map pattern can't have a subpattern.
+// Try removing the subpattern.
+// if (o case {5: 3, ...var a}) { // Error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class Class extends core::Object {
+ synthetic constructor •() → self::Class
+ : super core::Object::•()
+ ;
+ get field() → core::int
+ return 42;
+ operator >=(self::Class cls) → core::bool
+ return true;
+ operator >(core::int i) → self::Class
+ return new self::Class::•();
+}
+static method argumentTypeNotAssignable(self::Class cls) → dynamic {
+ #L1:
+ if(invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:13:13: Error: The argument type 'int' can't be assigned to the parameter type 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/patterns/shared_errors.dart'.
+ case >= 0: // Error
+ ^") {
+ {
+ core::print(0);
+ }
+ }
+}
+static method relationalPatternOperatorReturnTypeNotAssignableToBool(self::Class cls) → dynamic {
+ #L2:
+ if(invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:20:10: Error: A value of type 'Class' can't be assigned to a variable of type 'bool'.
+ - 'Class' is from 'pkg/front_end/testcases/patterns/shared_errors.dart'.
+ case > 0: // Error
+ ^") {
+ {
+ core::print(0);
+ }
+ }
+}
+static method patternTypeMismatchInIrrefutableContext(core::List<core::String> list) → dynamic {
+ core::int a;
+ if(!invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:26:12: Error: The matched value of type 'List<String>' isn't assignable to the required type 'List<int>'.
+ - 'List' is from 'dart:core'.
+Try changing the required type of the pattern, or the matched value type.
+ var <int>[a] = list; // Error
+ ^")
+ throw new _in::ReachabilityError::•();
+}
+static method duplicateAssignmentPatternVariable(core::List<core::String> list) → dynamic {
+ core::String a = "";
+ block {
+ final dynamic #0#0 = list;
+ if(!(#0#0{core::List<core::String>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final core::String #t1 = a = #0#0{core::List<core::String>}.{core::List::[]}(0){(core::int) → core::String} in true) && (let final core::String #t2 = #0#0{core::List<core::String>}.{core::List::[]}(1){(core::int) → core::String} in invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:31:7: Error: The variable 'a' is already assigned in this pattern.
+Try renaming the variable.
+ [a, a] = list; // Error
+ ^")))
+ throw new _in::ReachabilityError::•();
+ } =>#0#0;
+}
+static method duplicateRecordPatternField(dynamic o) → dynamic {
+ #L3:
+ {
+ final dynamic #0#0 = o;
+ function ##0#2#initializer() → core::int
+ return #0#0{self::Class}.{self::Class::field}{core::int};
+ late final core::int #0#2 = ##0#2#initializer(){() → core::int};
+ if(invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:36:28: Error: The field 'field' is already matched in this pattern.
+Try removing the duplicate field.
+ case (field: 1, field: 2): // Error
+ ^" || #0#0 is{ForNonNullableByDefault} self::Class && #C2 =={core::num::==}{(core::Object) → core::bool} #0#2 && (let final core::int #t3 = #0#2 in invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:37:33: Error: The field 'field' is already matched in this pattern.
+Try removing the duplicate field.
+ case Class(field: 1, field: 2): // Error
+ ^")) {
+ {
+ core::print(0);
+ }
+ }
+ }
+}
+static method duplicateRestPattern(dynamic o) → dynamic {
+ #L4:
+ {
+ final dynamic #0#0 = o;
+ core::int #0#2;
+ core::bool #0#2#isSet = false;
+ if(#0#0 is{ForNonNullableByDefault} core::List<dynamic> && (#0#2#isSet ?{core::int} #0#2{core::int} : let final core::bool* #t4 = #0#2#isSet = true in #0#2 = #0#0{core::List<dynamic>}.{core::List::length}{core::int}).{core::num::>=}(#C2){(core::num) → core::bool} && (let final dynamic #t5 = #0#0{core::List<dynamic>}.{core::List::[]}((#0#2#isSet ?{core::int} #0#2{core::int} : let final core::bool* #t6 = #0#2#isSet = true in #0#2 = #0#0{core::List<dynamic>}.{core::List::length}{core::int}).{core::num::-}(1){(core::num) → core::int}){(core::int) → dynamic} in invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:44:16: Error: At most one rest element is allowed in a list or map pattern.
+Try removing the duplicate rest element.
+ case [..., ...]: // Error
+ ^") || #0#0 is{ForNonNullableByDefault} core::Map<dynamic, dynamic> && (#0#2#isSet ?{core::int} #0#2{core::int} : let final core::bool* #t7 = #0#2#isSet = true in #0#2 = #0#0{core::Map<dynamic, dynamic>}.{core::Map::length}{core::int}).{core::num::>=}(#C3){(core::num) → core::bool}) {
+ }
+ }
+}
+static method matchedTypeIsStrictlyNonNullable(core::List<core::int> list) → dynamic {
+ {
+ core::int a;
+ core::int b;
+ final core::List<core::int> #0#0 = list;
+ function ##0#4#initializer() → core::int
+ return #0#0.{core::List::[]}(0){(core::int) → core::int};
+ late final core::int #0#4 = ##0#4#initializer(){() → core::int};
+ function ##0#6#initializer() → core::int
+ return #0#0.{core::List::[]}(1){(core::int) → core::int};
+ late final core::int #0#6 = ##0#6#initializer(){() → core::int};
+ if(#0#0.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final core::int #t8 = #0#4! in let final core::int #t9 = a = #0#4! in true) && (!(#0#6 == null) ?{core::bool} let final core::int #t10 = b = #0#6 in true : false)) {
+ core::print(0);
+ }
+ }
+}
+static method nonBooleanCondition(core::int i) → dynamic {
+ {
+ final core::int #0#0 = i;
+ if(#C3 =={core::num::==}{(core::Object) → core::bool} #0#0 && invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:56:21: Error: Conditions must have a static type of 'bool'.
+Try changing the condition.
+ if (i case 0 when i) { // Error
+ ^") {
+ core::print(0);
+ }
+ }
+}
+static method refutablePatternInIrrefutableContext(core::int? x) → dynamic {
+ core::int a;
+ {
+ final dynamic #0#0 = x;
+ if(!(!(#0#0 == null) ?{core::bool} let final core::int #t11 = a = #0#0{core::int} in true : false))
+ throw new _in::ReachabilityError::•();
+ }
+}
+static method restPatternNotLastInMap(dynamic o) → dynamic {
+ {
+ final dynamic #0#0 = o;
+ if(#0#0 is{ForNonNullableByDefault} core::Map<dynamic, dynamic> && #0#0{core::Map<dynamic, dynamic>}.{core::Map::length}{core::int}.{core::num::>=}(#C2){(core::num) → core::bool} && #0#0{core::Map<dynamic, dynamic>}.{core::Map::containsKey}(#C4){(core::Object?) → core::bool} && #C5 =={core::num::==}{(core::Object) → core::bool} #0#0{core::Map<dynamic, dynamic>}.{core::Map::[]}(#C4){(core::Object?) → dynamic}) {
+ core::print(0);
+ }
+ }
+}
+static method restPatternWithSubPatternInMap(dynamic o) → dynamic {
+ {
+ final dynamic #0#0 = o;
+ if(#0#0 is{ForNonNullableByDefault} core::Map<dynamic, dynamic> && #0#0{core::Map<dynamic, dynamic>}.{core::Map::length}{core::int}.{core::num::>=}(#C2){(core::num) → core::bool} && #0#0{core::Map<dynamic, dynamic>}.{core::Map::containsKey}(#C4){(core::Object?) → core::bool} && #C5 =={core::num::==}{(core::Object) → core::bool} #0#0{core::Map<dynamic, dynamic>}.{core::Map::[]}(#C4){(core::Object?) → dynamic}) {
+ core::print(0);
+ }
+ }
+}
+
+constants {
+ #C1 = 2
+ #C2 = 1
+ #C3 = 0
+ #C4 = 5
+ #C5 = 3
+}
diff --git a/pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart.strong.expect b/pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart.strong.expect
index 8e6b40b..8c6b94b 100644
--- a/pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart.strong.expect
+++ b/pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart.strong.expect
@@ -22,12 +22,15 @@
{
core::int as;
final dynamic #0#0 = x;
- late final invalid-type #0#2 = invalid-expression "pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart:10:12: Error: The getter 'as' isn't defined for the class 'C'.
+ if(#0#0 is{ForNonNullableByDefault} self::C && (let final dynamic #t1 = invalid-expression "pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart:10:12: Error: The getter 'as' isn't defined for the class 'C'.
- 'C' is from 'pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'as'.
case C(: int as):
- ^^" in null{<unresolved>}.as;
- if(#0#0 is{ForNonNullableByDefault} self::C && (#0#2 is{ForNonNullableByDefault} core::int && (let final dynamic #t1 = as = #0#2{core::int} in true))) {
+ ^^" in invalid-expression "pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart:10:12: Error: The getter 'as' isn't defined for the class 'C'.
+ - 'C' is from 'pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'as'.
+ case C(: int as):
+ ^^")) {
{
break #L1;
}
diff --git a/pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart.strong.transformed.expect b/pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart.strong.transformed.expect
index 9b45992..b3c1698 100644
--- a/pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart.strong.transformed.expect
@@ -22,14 +22,15 @@
{
core::int as;
final dynamic #0#0 = x;
- function ##0#2#initializer() → invalid-type
- return invalid-expression "pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart:10:12: Error: The getter 'as' isn't defined for the class 'C'.
+ if(#0#0 is{ForNonNullableByDefault} self::C && (let final invalid-type #t1 = invalid-expression "pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart:10:12: Error: The getter 'as' isn't defined for the class 'C'.
- 'C' is from 'pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'as'.
case C(: int as):
- ^^" in null{<unresolved>}.as;
- late final invalid-type #0#2 = ##0#2#initializer(){() → invalid-type};
- if(#0#0 is{ForNonNullableByDefault} self::C && (#0#2 is{ForNonNullableByDefault} core::int && (let final core::int #t1 = as = #0#2{core::int} in true))) {
+ ^^" in invalid-expression "pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart:10:12: Error: The getter 'as' isn't defined for the class 'C'.
+ - 'C' is from 'pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'as'.
+ case C(: int as):
+ ^^")) {
{
break #L1;
}
diff --git a/pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart.weak.expect b/pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart.weak.expect
index 8e6b40b..8c6b94b 100644
--- a/pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart.weak.expect
+++ b/pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart.weak.expect
@@ -22,12 +22,15 @@
{
core::int as;
final dynamic #0#0 = x;
- late final invalid-type #0#2 = invalid-expression "pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart:10:12: Error: The getter 'as' isn't defined for the class 'C'.
+ if(#0#0 is{ForNonNullableByDefault} self::C && (let final dynamic #t1 = invalid-expression "pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart:10:12: Error: The getter 'as' isn't defined for the class 'C'.
- 'C' is from 'pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'as'.
case C(: int as):
- ^^" in null{<unresolved>}.as;
- if(#0#0 is{ForNonNullableByDefault} self::C && (#0#2 is{ForNonNullableByDefault} core::int && (let final dynamic #t1 = as = #0#2{core::int} in true))) {
+ ^^" in invalid-expression "pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart:10:12: Error: The getter 'as' isn't defined for the class 'C'.
+ - 'C' is from 'pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'as'.
+ case C(: int as):
+ ^^")) {
{
break #L1;
}
diff --git a/pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart.weak.modular.expect b/pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart.weak.modular.expect
index 8e6b40b..8c6b94b 100644
--- a/pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart.weak.modular.expect
@@ -22,12 +22,15 @@
{
core::int as;
final dynamic #0#0 = x;
- late final invalid-type #0#2 = invalid-expression "pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart:10:12: Error: The getter 'as' isn't defined for the class 'C'.
+ if(#0#0 is{ForNonNullableByDefault} self::C && (let final dynamic #t1 = invalid-expression "pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart:10:12: Error: The getter 'as' isn't defined for the class 'C'.
- 'C' is from 'pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'as'.
case C(: int as):
- ^^" in null{<unresolved>}.as;
- if(#0#0 is{ForNonNullableByDefault} self::C && (#0#2 is{ForNonNullableByDefault} core::int && (let final dynamic #t1 = as = #0#2{core::int} in true))) {
+ ^^" in invalid-expression "pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart:10:12: Error: The getter 'as' isn't defined for the class 'C'.
+ - 'C' is from 'pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'as'.
+ case C(: int as):
+ ^^")) {
{
break #L1;
}
diff --git a/pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart.weak.transformed.expect b/pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart.weak.transformed.expect
index 9b45992..b3c1698 100644
--- a/pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart.weak.transformed.expect
@@ -22,14 +22,15 @@
{
core::int as;
final dynamic #0#0 = x;
- function ##0#2#initializer() → invalid-type
- return invalid-expression "pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart:10:12: Error: The getter 'as' isn't defined for the class 'C'.
+ if(#0#0 is{ForNonNullableByDefault} self::C && (let final invalid-type #t1 = invalid-expression "pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart:10:12: Error: The getter 'as' isn't defined for the class 'C'.
- 'C' is from 'pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'as'.
case C(: int as):
- ^^" in null{<unresolved>}.as;
- late final invalid-type #0#2 = ##0#2#initializer(){() → invalid-type};
- if(#0#0 is{ForNonNullableByDefault} self::C && (#0#2 is{ForNonNullableByDefault} core::int && (let final core::int #t1 = as = #0#2{core::int} in true))) {
+ ^^" in invalid-expression "pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart:10:12: Error: The getter 'as' isn't defined for the class 'C'.
+ - 'C' is from 'pkg/front_end/testcases/patterns/typed_variable_named_as_inside_extractor_pattern_implicitly_named.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'as'.
+ case C(: int as):
+ ^^")) {
{
break #L1;
}
diff --git a/pkg/front_end/testcases/records/type_record_as_supertype.dart.strong.expect b/pkg/front_end/testcases/records/type_record_as_supertype.dart.strong.expect
index 2c8af64..df2e448 100644
--- a/pkg/front_end/testcases/records/type_record_as_supertype.dart.strong.expect
+++ b/pkg/front_end/testcases/records/type_record_as_supertype.dart.strong.expect
@@ -38,9 +38,9 @@
// pkg/front_end/testcases/records/type_record_as_supertype.dart:22:16: Error: 'RR' is restricted and can't be extended or implemented.
// abstract class C2 with RR {} // Error.
// ^
-// sdk/lib/core/record.dart:11:16: Context: This is the type denoted by the type alias.
-// abstract class Record {}
-// ^
+// sdk/lib/core/record.dart:11:22: Context: This is the type denoted by the type alias.
+// abstract final class Record {}
+// ^
//
import self as self;
import "dart:core" as core;
@@ -92,7 +92,7 @@
: super core::Object::•()
;
}
-abstract class _C1&Object&Record = core::Object with core::Record /*isAnonymousMixin,hasConstConstructor*/ {
+abstract final class _C1&Object&Record = core::Object with core::Record /*isAnonymousMixin,hasConstConstructor*/ {
const synthetic constructor •() → self::_C1&Object&Record
: super core::Object::•()
;
@@ -102,7 +102,7 @@
: super self::_C1&Object&Record::•()
;
}
-abstract class _C2&Object&RR = core::Object with core::Record /*isAnonymousMixin,hasConstConstructor*/ {
+abstract final class _C2&Object&RR = core::Object with core::Record /*isAnonymousMixin,hasConstConstructor*/ {
const synthetic constructor •() → self::_C2&Object&RR
: super core::Object::•()
;
diff --git a/pkg/front_end/testcases/records/type_record_as_supertype.dart.strong.transformed.expect b/pkg/front_end/testcases/records/type_record_as_supertype.dart.strong.transformed.expect
index 1ace8f9..b4092d3 100644
--- a/pkg/front_end/testcases/records/type_record_as_supertype.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/records/type_record_as_supertype.dart.strong.transformed.expect
@@ -38,9 +38,9 @@
// pkg/front_end/testcases/records/type_record_as_supertype.dart:22:16: Error: 'RR' is restricted and can't be extended or implemented.
// abstract class C2 with RR {} // Error.
// ^
-// sdk/lib/core/record.dart:11:16: Context: This is the type denoted by the type alias.
-// abstract class Record {}
-// ^
+// sdk/lib/core/record.dart:11:22: Context: This is the type denoted by the type alias.
+// abstract final class Record {}
+// ^
//
import self as self;
import "dart:core" as core;
@@ -92,7 +92,7 @@
: super core::Object::•()
;
}
-abstract class _C1&Object&Record extends core::Object implements core::Record /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
+abstract final class _C1&Object&Record extends core::Object implements core::Record /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
const synthetic constructor •() → self::_C1&Object&Record
: super core::Object::•()
;
@@ -102,7 +102,7 @@
: super self::_C1&Object&Record::•()
;
}
-abstract class _C2&Object&RR extends core::Object implements core::Record /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
+abstract final class _C2&Object&RR extends core::Object implements core::Record /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
const synthetic constructor •() → self::_C2&Object&RR
: super core::Object::•()
;
diff --git a/pkg/front_end/testcases/records/type_record_as_supertype.dart.weak.expect b/pkg/front_end/testcases/records/type_record_as_supertype.dart.weak.expect
index 2c8af64..df2e448 100644
--- a/pkg/front_end/testcases/records/type_record_as_supertype.dart.weak.expect
+++ b/pkg/front_end/testcases/records/type_record_as_supertype.dart.weak.expect
@@ -38,9 +38,9 @@
// pkg/front_end/testcases/records/type_record_as_supertype.dart:22:16: Error: 'RR' is restricted and can't be extended or implemented.
// abstract class C2 with RR {} // Error.
// ^
-// sdk/lib/core/record.dart:11:16: Context: This is the type denoted by the type alias.
-// abstract class Record {}
-// ^
+// sdk/lib/core/record.dart:11:22: Context: This is the type denoted by the type alias.
+// abstract final class Record {}
+// ^
//
import self as self;
import "dart:core" as core;
@@ -92,7 +92,7 @@
: super core::Object::•()
;
}
-abstract class _C1&Object&Record = core::Object with core::Record /*isAnonymousMixin,hasConstConstructor*/ {
+abstract final class _C1&Object&Record = core::Object with core::Record /*isAnonymousMixin,hasConstConstructor*/ {
const synthetic constructor •() → self::_C1&Object&Record
: super core::Object::•()
;
@@ -102,7 +102,7 @@
: super self::_C1&Object&Record::•()
;
}
-abstract class _C2&Object&RR = core::Object with core::Record /*isAnonymousMixin,hasConstConstructor*/ {
+abstract final class _C2&Object&RR = core::Object with core::Record /*isAnonymousMixin,hasConstConstructor*/ {
const synthetic constructor •() → self::_C2&Object&RR
: super core::Object::•()
;
diff --git a/pkg/front_end/testcases/records/type_record_as_supertype.dart.weak.modular.expect b/pkg/front_end/testcases/records/type_record_as_supertype.dart.weak.modular.expect
index 2c8af64..df2e448 100644
--- a/pkg/front_end/testcases/records/type_record_as_supertype.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/records/type_record_as_supertype.dart.weak.modular.expect
@@ -38,9 +38,9 @@
// pkg/front_end/testcases/records/type_record_as_supertype.dart:22:16: Error: 'RR' is restricted and can't be extended or implemented.
// abstract class C2 with RR {} // Error.
// ^
-// sdk/lib/core/record.dart:11:16: Context: This is the type denoted by the type alias.
-// abstract class Record {}
-// ^
+// sdk/lib/core/record.dart:11:22: Context: This is the type denoted by the type alias.
+// abstract final class Record {}
+// ^
//
import self as self;
import "dart:core" as core;
@@ -92,7 +92,7 @@
: super core::Object::•()
;
}
-abstract class _C1&Object&Record = core::Object with core::Record /*isAnonymousMixin,hasConstConstructor*/ {
+abstract final class _C1&Object&Record = core::Object with core::Record /*isAnonymousMixin,hasConstConstructor*/ {
const synthetic constructor •() → self::_C1&Object&Record
: super core::Object::•()
;
@@ -102,7 +102,7 @@
: super self::_C1&Object&Record::•()
;
}
-abstract class _C2&Object&RR = core::Object with core::Record /*isAnonymousMixin,hasConstConstructor*/ {
+abstract final class _C2&Object&RR = core::Object with core::Record /*isAnonymousMixin,hasConstConstructor*/ {
const synthetic constructor •() → self::_C2&Object&RR
: super core::Object::•()
;
diff --git a/pkg/front_end/testcases/records/type_record_as_supertype.dart.weak.outline.expect b/pkg/front_end/testcases/records/type_record_as_supertype.dart.weak.outline.expect
index f960292..c89ec82 100644
--- a/pkg/front_end/testcases/records/type_record_as_supertype.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/records/type_record_as_supertype.dart.weak.outline.expect
@@ -38,9 +38,9 @@
// pkg/front_end/testcases/records/type_record_as_supertype.dart:22:16: Error: 'RR' is restricted and can't be extended or implemented.
// abstract class C2 with RR {} // Error.
// ^
-// sdk/lib/core/record.dart:11:16: Context: This is the type denoted by the type alias.
-// abstract class Record {}
-// ^
+// sdk/lib/core/record.dart:11:22: Context: This is the type denoted by the type alias.
+// abstract final class Record {}
+// ^
//
import self as self;
import "dart:core" as core;
@@ -83,7 +83,7 @@
synthetic constructor •() → self::B4
;
}
-abstract class _C1&Object&Record = core::Object with core::Record /*isAnonymousMixin,hasConstConstructor*/ {
+abstract final class _C1&Object&Record = core::Object with core::Record /*isAnonymousMixin,hasConstConstructor*/ {
const synthetic constructor •() → self::_C1&Object&Record
: super core::Object::•()
;
@@ -92,7 +92,7 @@
synthetic constructor •() → self::C1
;
}
-abstract class _C2&Object&RR = core::Object with core::Record /*isAnonymousMixin,hasConstConstructor*/ {
+abstract final class _C2&Object&RR = core::Object with core::Record /*isAnonymousMixin,hasConstConstructor*/ {
const synthetic constructor •() → self::_C2&Object&RR
: super core::Object::•()
;
diff --git a/pkg/front_end/testcases/records/type_record_as_supertype.dart.weak.transformed.expect b/pkg/front_end/testcases/records/type_record_as_supertype.dart.weak.transformed.expect
index 1ace8f9..b4092d3 100644
--- a/pkg/front_end/testcases/records/type_record_as_supertype.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/records/type_record_as_supertype.dart.weak.transformed.expect
@@ -38,9 +38,9 @@
// pkg/front_end/testcases/records/type_record_as_supertype.dart:22:16: Error: 'RR' is restricted and can't be extended or implemented.
// abstract class C2 with RR {} // Error.
// ^
-// sdk/lib/core/record.dart:11:16: Context: This is the type denoted by the type alias.
-// abstract class Record {}
-// ^
+// sdk/lib/core/record.dart:11:22: Context: This is the type denoted by the type alias.
+// abstract final class Record {}
+// ^
//
import self as self;
import "dart:core" as core;
@@ -92,7 +92,7 @@
: super core::Object::•()
;
}
-abstract class _C1&Object&Record extends core::Object implements core::Record /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
+abstract final class _C1&Object&Record extends core::Object implements core::Record /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
const synthetic constructor •() → self::_C1&Object&Record
: super core::Object::•()
;
@@ -102,7 +102,7 @@
: super self::_C1&Object&Record::•()
;
}
-abstract class _C2&Object&RR extends core::Object implements core::Record /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
+abstract final class _C2&Object&RR extends core::Object implements core::Record /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
const synthetic constructor •() → self::_C2&Object&RR
: super core::Object::•()
;
diff --git a/pkg/front_end/testcases/records/type_record_unsupported.dart.strong.expect b/pkg/front_end/testcases/records/type_record_unsupported.dart.strong.expect
index fa21425..d9c5187 100644
--- a/pkg/front_end/testcases/records/type_record_unsupported.dart.strong.expect
+++ b/pkg/front_end/testcases/records/type_record_unsupported.dart.strong.expect
@@ -58,7 +58,7 @@
: super core::Object::•()
;
}
-abstract class _A3&Object&Record = core::Object with core::Record /*isAnonymousMixin,hasConstConstructor*/ {
+abstract final class _A3&Object&Record = core::Object with core::Record /*isAnonymousMixin,hasConstConstructor*/ {
const synthetic constructor •() → self::_A3&Object&Record
: super core::Object::•()
;
diff --git a/pkg/front_end/testcases/records/type_record_unsupported.dart.strong.transformed.expect b/pkg/front_end/testcases/records/type_record_unsupported.dart.strong.transformed.expect
index 4174f02..aea7b2e 100644
--- a/pkg/front_end/testcases/records/type_record_unsupported.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/records/type_record_unsupported.dart.strong.transformed.expect
@@ -58,7 +58,7 @@
: super core::Object::•()
;
}
-abstract class _A3&Object&Record extends core::Object implements core::Record /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
+abstract final class _A3&Object&Record extends core::Object implements core::Record /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
const synthetic constructor •() → self::_A3&Object&Record
: super core::Object::•()
;
diff --git a/pkg/front_end/testcases/records/type_record_unsupported.dart.weak.expect b/pkg/front_end/testcases/records/type_record_unsupported.dart.weak.expect
index 5610029..fa3163b 100644
--- a/pkg/front_end/testcases/records/type_record_unsupported.dart.weak.expect
+++ b/pkg/front_end/testcases/records/type_record_unsupported.dart.weak.expect
@@ -58,7 +58,7 @@
: super core::Object::•()
;
}
-abstract class _A3&Object&Record = core::Object with core::Record /*isAnonymousMixin,hasConstConstructor*/ {
+abstract final class _A3&Object&Record = core::Object with core::Record /*isAnonymousMixin,hasConstConstructor*/ {
const synthetic constructor •() → self::_A3&Object&Record
: super core::Object::•()
;
diff --git a/pkg/front_end/testcases/records/type_record_unsupported.dart.weak.modular.expect b/pkg/front_end/testcases/records/type_record_unsupported.dart.weak.modular.expect
index 5610029..fa3163b 100644
--- a/pkg/front_end/testcases/records/type_record_unsupported.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/records/type_record_unsupported.dart.weak.modular.expect
@@ -58,7 +58,7 @@
: super core::Object::•()
;
}
-abstract class _A3&Object&Record = core::Object with core::Record /*isAnonymousMixin,hasConstConstructor*/ {
+abstract final class _A3&Object&Record = core::Object with core::Record /*isAnonymousMixin,hasConstConstructor*/ {
const synthetic constructor •() → self::_A3&Object&Record
: super core::Object::•()
;
diff --git a/pkg/front_end/testcases/records/type_record_unsupported.dart.weak.outline.expect b/pkg/front_end/testcases/records/type_record_unsupported.dart.weak.outline.expect
index 4dc5f91..53b2b68 100644
--- a/pkg/front_end/testcases/records/type_record_unsupported.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/records/type_record_unsupported.dart.weak.outline.expect
@@ -48,7 +48,7 @@
synthetic constructor •() → self::A2
;
}
-abstract class _A3&Object&Record = core::Object with core::Record /*isAnonymousMixin,hasConstConstructor*/ {
+abstract final class _A3&Object&Record = core::Object with core::Record /*isAnonymousMixin,hasConstConstructor*/ {
const synthetic constructor •() → self::_A3&Object&Record
: super core::Object::•()
;
diff --git a/pkg/front_end/testcases/records/type_record_unsupported.dart.weak.transformed.expect b/pkg/front_end/testcases/records/type_record_unsupported.dart.weak.transformed.expect
index 8bef6e6..fb6bddc 100644
--- a/pkg/front_end/testcases/records/type_record_unsupported.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/records/type_record_unsupported.dart.weak.transformed.expect
@@ -58,7 +58,7 @@
: super core::Object::•()
;
}
-abstract class _A3&Object&Record extends core::Object implements core::Record /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
+abstract final class _A3&Object&Record extends core::Object implements core::Record /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
const synthetic constructor •() → self::_A3&Object&Record
: super core::Object::•()
;
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index e2454e2..e987dd7 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -150,7 +150,6 @@
nnbd/no_support_for_old_null_aware_index_access_syntax: RuntimeError # Expected.
no_such_method_forwarders/mixin_nsm: TypeCheckError
patterns/pattern_types: TypeCheckError
-patterns/shared_errors: TypeCheckError
rasta/abstract_constructor: RuntimeError
rasta/bad_constructor_redirection: RuntimeError
rasta/bad_continue: RuntimeError
diff --git a/pkg/front_end/testcases/weak.status b/pkg/front_end/testcases/weak.status
index 75fe83c..3dc6e6f 100644
--- a/pkg/front_end/testcases/weak.status
+++ b/pkg/front_end/testcases/weak.status
@@ -232,7 +232,6 @@
nnbd_mixed/messages_with_types_opt_out: TypeCheckError
nnbd_mixed/mixin_from_opt_in/main: RuntimeError
patterns/pattern_types: TypeCheckError
-patterns/shared_errors: TypeCheckError
rasta/abstract_constructor: RuntimeError
rasta/bad_constructor_redirection: RuntimeError
rasta/bad_continue: RuntimeError
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index e32421c..a44c05e 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -13325,7 +13325,11 @@
final Nullability declaredNullability;
RecordType(this.positional, this.named, this.declaredNullability)
- : assert(() {
+ : /*TODO(johnniwinther): Enabled this assert:
+ assert(named.length == named.map((p) => p.name).toSet().length,
+ "Named field types must have unique names in a RecordType: "
+ "${named}"),*/
+ assert(() {
// Assert that the named field types are sorted.
for (int i = 1; i < named.length; i++) {
if (named[i].name.compareTo(named[i - 1].name) < 0) {