mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-04 10:11:06 +01:00
Fix a crash when checking a nested tuple-pattern (#7716)
Adds a virtual node to `DefaultValuePattern` to end the `ExprRegionForPattern` before checking the expression for the default value. When checking the default value expression, the context was still configured to interpret expressions as patterns, which caused some corruption of state with tuple-pattern subpatterns. Corrects an assertion failure I found while working on feedback from #7665.
This commit is contained in:
@@ -157,6 +157,14 @@ auto HandleParseNode(Context& context, Parse::DefaultValueUnspecifiedId node_id)
|
||||
return context.TODO(node_id, "pattern default values");
|
||||
}
|
||||
|
||||
auto HandleParseNode(Context& context,
|
||||
Parse::DefaultValueExprStartId /*node_id*/) -> bool {
|
||||
// We want to check the default value expression as a normal expression,
|
||||
// and not convert it into a pattern.
|
||||
EndEmptyExprRegionForPattern(context);
|
||||
return true;
|
||||
}
|
||||
|
||||
auto HandleParseNode(Context& context, Parse::DefaultValuePatternId node_id)
|
||||
-> bool {
|
||||
// On entry, the top of the node stack should have an expression for the
|
||||
@@ -205,6 +213,9 @@ auto HandleParseNode(Context& context, Parse::DefaultValuePatternId node_id)
|
||||
.default_value_id = default_value_id});
|
||||
context.node_stack().Push(node_id, default_value_inst_id);
|
||||
|
||||
// We turned off expr region for pattern checking while parsing the default
|
||||
// value expression, so turn it back on again for further pattern checking.
|
||||
BeginExprRegionForPattern(context);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -498,6 +498,7 @@ class NodeStack {
|
||||
case Parse::NodeKind::ContinueStatementStart:
|
||||
case Parse::NodeKind::CorePackageName:
|
||||
case Parse::NodeKind::CppPackageName:
|
||||
case Parse::NodeKind::DefaultValueExprStart:
|
||||
case Parse::NodeKind::ExportIntroducer:
|
||||
case Parse::NodeKind::FileEnd:
|
||||
case Parse::NodeKind::FileStart:
|
||||
|
||||
@@ -64,6 +64,13 @@ library "[[@TEST_NAME]]";
|
||||
// CHECK:STDERR:
|
||||
fn Z(v: i32, x: i32 = 3, (y: i32 = 2, z: i32), w: i32 = 4, k: i32);
|
||||
|
||||
// --- nested.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
//@dump-sem-ir-begin
|
||||
fn F(a: i32, (b: i32, (c: i32, (d: i32, e: i32))) = (1, (2, (3, 4))));
|
||||
//@dump-sem-ir-end
|
||||
|
||||
// --- basic.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
@@ -72,6 +79,96 @@ library "[[@TEST_NAME]]";
|
||||
fn F(x: i32 = 0);
|
||||
//@dump-sem-ir-end
|
||||
|
||||
// CHECK:STDOUT: --- nested.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete]
|
||||
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete]
|
||||
// CHECK:STDOUT: %pattern_type.6b6: type = pattern_type %i32 [concrete]
|
||||
// CHECK:STDOUT: %a.param_patt: %pattern_type.6b6 = value_param_pattern [concrete]
|
||||
// CHECK:STDOUT: %a.patt: %pattern_type.6b6 = wrapper_binding_pattern a, %a.param_patt [concrete]
|
||||
// CHECK:STDOUT: %b.param_patt: %pattern_type.6b6 = value_param_pattern [concrete]
|
||||
// CHECK:STDOUT: %b.patt: %pattern_type.6b6 = wrapper_binding_pattern b, %b.param_patt [concrete]
|
||||
// CHECK:STDOUT: %c.param_patt: %pattern_type.6b6 = value_param_pattern [concrete]
|
||||
// CHECK:STDOUT: %c.patt: %pattern_type.6b6 = wrapper_binding_pattern c, %c.param_patt [concrete]
|
||||
// CHECK:STDOUT: %d.param_patt: %pattern_type.6b6 = value_param_pattern [concrete]
|
||||
// CHECK:STDOUT: %d.patt: %pattern_type.6b6 = wrapper_binding_pattern d, %d.param_patt [concrete]
|
||||
// CHECK:STDOUT: %e.param_patt: %pattern_type.6b6 = value_param_pattern [concrete]
|
||||
// CHECK:STDOUT: %e.patt: %pattern_type.6b6 = wrapper_binding_pattern e, %e.param_patt [concrete]
|
||||
// CHECK:STDOUT: %tuple.type.e55: type = tuple_type (%i32, %i32) [concrete]
|
||||
// CHECK:STDOUT: %pattern_type.394: type = pattern_type %tuple.type.e55 [concrete]
|
||||
// CHECK:STDOUT: %.70d: %pattern_type.394 = tuple_pattern (%d.patt, %e.patt) [concrete]
|
||||
// CHECK:STDOUT: %tuple.type.920: type = tuple_type (%i32, %tuple.type.e55) [concrete]
|
||||
// CHECK:STDOUT: %pattern_type.e87: type = pattern_type %tuple.type.920 [concrete]
|
||||
// CHECK:STDOUT: %.aa9: %pattern_type.e87 = tuple_pattern (%c.patt, %.70d) [concrete]
|
||||
// CHECK:STDOUT: %tuple.type.007: type = tuple_type (%i32, %tuple.type.920) [concrete]
|
||||
// CHECK:STDOUT: %pattern_type.802: type = pattern_type %tuple.type.007 [concrete]
|
||||
// CHECK:STDOUT: %.203: %pattern_type.802 = tuple_pattern (%b.patt, %.aa9) [concrete]
|
||||
// CHECK:STDOUT: %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]
|
||||
// CHECK:STDOUT: %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]
|
||||
// CHECK:STDOUT: %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]
|
||||
// CHECK:STDOUT: %int_4.0c1: Core.IntLiteral = int_value 4 [concrete]
|
||||
// CHECK:STDOUT: %tuple.type.f94: type = tuple_type (Core.IntLiteral, Core.IntLiteral) [concrete]
|
||||
// CHECK:STDOUT: %tuple.302: %tuple.type.f94 = tuple_value (%int_3.1ba, %int_4.0c1) [concrete]
|
||||
// CHECK:STDOUT: %tuple.type.bd0: type = tuple_type (Core.IntLiteral, %tuple.type.f94) [concrete]
|
||||
// CHECK:STDOUT: %tuple.b26: %tuple.type.bd0 = tuple_value (%int_2.ecc, %tuple.302) [concrete]
|
||||
// CHECK:STDOUT: %tuple.type.c4f: type = tuple_type (Core.IntLiteral, %tuple.type.bd0) [concrete]
|
||||
// CHECK:STDOUT: %tuple.326: %tuple.type.c4f = tuple_value (%int_1.5b8, %tuple.b26) [concrete]
|
||||
// CHECK:STDOUT: %.19b: %pattern_type.802 = default_value_pattern %.203, index: 0 [concrete]
|
||||
// CHECK:STDOUT: %F.type: type = fn_type @F [concrete]
|
||||
// CHECK:STDOUT: %F: %F.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {
|
||||
// CHECK:STDOUT: %a.param_patt: %pattern_type.6b6 = value_param_pattern [concrete = constants.%a.param_patt]
|
||||
// CHECK:STDOUT: %a.patt: %pattern_type.6b6 = wrapper_binding_pattern a, %a.param_patt [concrete = constants.%a.patt]
|
||||
// CHECK:STDOUT: %b.param_patt: %pattern_type.6b6 = value_param_pattern [concrete = constants.%b.param_patt]
|
||||
// CHECK:STDOUT: %b.patt: %pattern_type.6b6 = wrapper_binding_pattern b, %b.param_patt [concrete = constants.%b.patt]
|
||||
// CHECK:STDOUT: %c.param_patt: %pattern_type.6b6 = value_param_pattern [concrete = constants.%c.param_patt]
|
||||
// CHECK:STDOUT: %c.patt: %pattern_type.6b6 = wrapper_binding_pattern c, %c.param_patt [concrete = constants.%c.patt]
|
||||
// CHECK:STDOUT: %d.param_patt: %pattern_type.6b6 = value_param_pattern [concrete = constants.%d.param_patt]
|
||||
// CHECK:STDOUT: %d.patt: %pattern_type.6b6 = wrapper_binding_pattern d, %d.param_patt [concrete = constants.%d.patt]
|
||||
// CHECK:STDOUT: %e.param_patt: %pattern_type.6b6 = value_param_pattern [concrete = constants.%e.param_patt]
|
||||
// CHECK:STDOUT: %e.patt: %pattern_type.6b6 = wrapper_binding_pattern e, %e.param_patt [concrete = constants.%e.patt]
|
||||
// CHECK:STDOUT: %.loc4_47: %pattern_type.394 = tuple_pattern (%d.patt, %e.patt) [concrete = constants.%.70d]
|
||||
// CHECK:STDOUT: %.loc4_48: %pattern_type.e87 = tuple_pattern (%c.patt, %.loc4_47) [concrete = constants.%.aa9]
|
||||
// CHECK:STDOUT: %.loc4_49: %pattern_type.802 = tuple_pattern (%b.patt, %.loc4_48) [concrete = constants.%.203]
|
||||
// CHECK:STDOUT: %.loc4_51: %pattern_type.802 = default_value_pattern %.loc4_49, index: 0 [concrete = constants.%.19b]
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
|
||||
// CHECK:STDOUT: %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]
|
||||
// CHECK:STDOUT: %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba]
|
||||
// CHECK:STDOUT: %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4.0c1]
|
||||
// CHECK:STDOUT: %.loc4_66: %tuple.type.f94 = tuple_literal (%int_3, %int_4) [concrete = constants.%tuple.302]
|
||||
// CHECK:STDOUT: %.loc4_67: %tuple.type.bd0 = tuple_literal (%int_2, %.loc4_66) [concrete = constants.%tuple.b26]
|
||||
// CHECK:STDOUT: %.loc4_68: %tuple.type.c4f = tuple_literal (%int_1, %.loc4_67) [concrete = constants.%tuple.326]
|
||||
// CHECK:STDOUT: %a.param: %i32 = value_param call_param0
|
||||
// CHECK:STDOUT: %i32.loc4_9: type = type_literal constants.%i32 [concrete = constants.%i32]
|
||||
// CHECK:STDOUT: %a: %i32 = wrapper_binding a, %a.param
|
||||
// CHECK:STDOUT: %b.param: %i32 = value_param call_param1
|
||||
// CHECK:STDOUT: %i32.loc4_18: type = type_literal constants.%i32 [concrete = constants.%i32]
|
||||
// CHECK:STDOUT: %b: %i32 = wrapper_binding b, %b.param
|
||||
// CHECK:STDOUT: %c.param: %i32 = value_param call_param2
|
||||
// CHECK:STDOUT: %i32.loc4_27: type = type_literal constants.%i32 [concrete = constants.%i32]
|
||||
// CHECK:STDOUT: %c: %i32 = wrapper_binding c, %c.param
|
||||
// CHECK:STDOUT: %d.param: %i32 = value_param call_param3
|
||||
// CHECK:STDOUT: %i32.loc4_36: type = type_literal constants.%i32 [concrete = constants.%i32]
|
||||
// CHECK:STDOUT: %d: %i32 = wrapper_binding d, %d.param
|
||||
// CHECK:STDOUT: %e.param: %i32 = value_param call_param4
|
||||
// CHECK:STDOUT: %i32.loc4_44: type = type_literal constants.%i32 [concrete = constants.%i32]
|
||||
// CHECK:STDOUT: %e: %i32 = wrapper_binding e, %e.param
|
||||
// CHECK:STDOUT: %tuple.loc4_47: %tuple.type.e55 = tuple_value (%d.param, %e.param)
|
||||
// CHECK:STDOUT: %tuple.loc4_48: %tuple.type.920 = tuple_value (%c.param, %tuple.loc4_47)
|
||||
// CHECK:STDOUT: %tuple.loc4_49: %tuple.type.007 = tuple_value (%b.param, %tuple.loc4_48)
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F(%a.param: %i32, %b.param: %i32, %c.param: %i32, %d.param: %i32, %e.param: %i32) default_values: {
|
||||
// CHECK:STDOUT: constants.%tuple.326: %tuple.type.c4f = tuple_value (constants.%int_1.5b8, constants.%tuple.b26) [concrete]
|
||||
// CHECK:STDOUT: };
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- basic.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
|
||||
@@ -92,7 +92,8 @@ CARBON_SYMBOL_TOKEN(Backslash, "\\")
|
||||
CARBON_SYMBOL_TOKEN(Caret, "^")
|
||||
CARBON_TOKEN_WITH_VIRTUAL_NODE(
|
||||
CARBON_SYMBOL_TOKEN(Colon, ":"))
|
||||
CARBON_SYMBOL_TOKEN(Equal, "=")
|
||||
CARBON_TOKEN_WITH_VIRTUAL_NODE(
|
||||
CARBON_SYMBOL_TOKEN(Equal, "="))
|
||||
CARBON_SYMBOL_TOKEN(Exclaim, "!")
|
||||
CARBON_SYMBOL_TOKEN(Greater, ">")
|
||||
CARBON_SYMBOL_TOKEN(Less, "<")
|
||||
|
||||
@@ -175,6 +175,10 @@ auto HandlePatternListElementCheckForDefaultValue(Context& context) -> void {
|
||||
return;
|
||||
}
|
||||
|
||||
// Add the first virtual node surrounding the value expr node, to facilitate
|
||||
// handling in check.
|
||||
context.AddLeafNode(NodeKind::DefaultValueExprStart, *equals_token);
|
||||
|
||||
state.token = *equals_token;
|
||||
state.kind = StateKind::PatternListElementFinishDefaultValue;
|
||||
context.PushState(state);
|
||||
|
||||
@@ -242,6 +242,7 @@ CARBON_PARSE_NODE_KIND_PATTERN(FormBindingPattern)
|
||||
CARBON_PARSE_NODE_KIND_PATTERN(TemplateBindingName)
|
||||
CARBON_PARSE_NODE_KIND_PATTERN(CompileTimeBindingPatternTypeStart)
|
||||
CARBON_PARSE_NODE_KIND_PATTERN(CompileTimeBindingPattern)
|
||||
CARBON_PARSE_NODE_KIND_PATTERN(DefaultValueExprStart)
|
||||
CARBON_PARSE_NODE_KIND_PATTERN(DefaultValuePattern)
|
||||
CARBON_PARSE_NODE_KIND_EXPRESSION(DefaultValueUnspecified)
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ fn I(x: i32 = _);
|
||||
// CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':'
|
||||
// CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32'
|
||||
// CHECK:STDOUT: │ │ │ ╭─LetBindingPattern ':'
|
||||
// CHECK:STDOUT: │ │ │ ├─DefaultValueExprStart '='
|
||||
// CHECK:STDOUT: │ │ │ ├─IntLiteral '0'
|
||||
// CHECK:STDOUT: │ │ ├─DefaultValuePattern '='
|
||||
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
|
||||
@@ -47,6 +48,7 @@ fn I(x: i32 = _);
|
||||
// CHECK:STDOUT: │ │ │ │ ├─IntTypeLiteral 'i32'
|
||||
// CHECK:STDOUT: │ │ │ ├─LetBindingPattern ':'
|
||||
// CHECK:STDOUT: │ │ │ ╭─TuplePattern ')'
|
||||
// CHECK:STDOUT: │ │ │ ├─DefaultValueExprStart '='
|
||||
// CHECK:STDOUT: │ │ │ │ ╭─TupleLiteralStart '('
|
||||
// CHECK:STDOUT: │ │ │ │ ├─IntLiteral '1'
|
||||
// CHECK:STDOUT: │ │ │ │ ├─TupleLiteralComma ','
|
||||
@@ -63,6 +65,7 @@ fn I(x: i32 = _);
|
||||
// CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32'
|
||||
// CHECK:STDOUT: │ │ │ ╭─LetBindingPattern ':'
|
||||
// CHECK:STDOUT: │ │ │ ╭─UnusedPattern 'unused'
|
||||
// CHECK:STDOUT: │ │ │ ├─DefaultValueExprStart '='
|
||||
// CHECK:STDOUT: │ │ │ ├─IntLiteral '25'
|
||||
// CHECK:STDOUT: │ │ ├─DefaultValuePattern '='
|
||||
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
|
||||
@@ -80,6 +83,7 @@ fn I(x: i32 = _);
|
||||
// CHECK:STDOUT: │ │ │ │ ├─BindingPatternTypeStart ':'
|
||||
// CHECK:STDOUT: │ │ │ │ ├─IntTypeLiteral 'i32'
|
||||
// CHECK:STDOUT: │ │ │ │ ╭─LetBindingPattern ':'
|
||||
// CHECK:STDOUT: │ │ │ │ ├─DefaultValueExprStart '='
|
||||
// CHECK:STDOUT: │ │ │ │ ├─IntLiteral '0'
|
||||
// CHECK:STDOUT: │ │ │ ├─DefaultValuePattern '='
|
||||
// CHECK:STDOUT: │ │ ├─ExplicitParamList ')'
|
||||
@@ -94,6 +98,7 @@ fn I(x: i32 = _);
|
||||
// CHECK:STDOUT: │ │ │ ├─BindingPatternTypeStart ':'
|
||||
// CHECK:STDOUT: │ │ │ ├─IntTypeLiteral 'i32'
|
||||
// CHECK:STDOUT: │ │ │ ╭─LetBindingPattern ':'
|
||||
// CHECK:STDOUT: │ │ │ ├─DefaultValueExprStart '='
|
||||
// CHECK:STDOUT: │ │ │ ├─DefaultValueUnspecified '_'
|
||||
// CHECK:STDOUT: │ │ ├─DefaultValuePattern '='
|
||||
// CHECK:STDOUT: │ ├─ExplicitParamList ')'
|
||||
|
||||
@@ -567,6 +567,7 @@ let {var _: i32} = {};
|
||||
// CHECK:STDOUT: │ ╭─LetIntroducer 'let'
|
||||
// CHECK:STDOUT: │ │ ╭─StructPatternStart '{'
|
||||
// CHECK:STDOUT: │ │ │ ╭─InvalidParse '=' has_error
|
||||
// CHECK:STDOUT: │ │ │ ├─DefaultValueExprStart '='
|
||||
// CHECK:STDOUT: │ │ │ ├─IdentifierNameExpr 'y'
|
||||
// CHECK:STDOUT: │ │ ├─DefaultValuePattern '=' has_error
|
||||
// CHECK:STDOUT: │ ├─StructPattern '}' has_error
|
||||
@@ -834,6 +835,7 @@ let {var _: i32} = {};
|
||||
// CHECK:STDOUT: │ │ │ ╭─IdentifierNameExpr 'foo'
|
||||
// CHECK:STDOUT: │ │ │ ├─IdentifierNameNotBeforeSignature 'y'
|
||||
// CHECK:STDOUT: │ │ │ ╭─MemberAccessExpr '.'
|
||||
// CHECK:STDOUT: │ │ │ ├─DefaultValueExprStart '='
|
||||
// CHECK:STDOUT: │ │ │ ├─IdentifierNameExpr 'y'
|
||||
// CHECK:STDOUT: │ │ ├─DefaultValuePattern '='
|
||||
// CHECK:STDOUT: │ ├─StructPattern '}' has_error
|
||||
@@ -959,6 +961,7 @@ let {var _: i32} = {};
|
||||
// CHECK:STDOUT: │ ╭─LetIntroducer 'let'
|
||||
// CHECK:STDOUT: │ │ ╭─StructPatternStart '{'
|
||||
// CHECK:STDOUT: │ │ │ ╭─StringLiteral '"foo"'
|
||||
// CHECK:STDOUT: │ │ │ ├─DefaultValueExprStart '='
|
||||
// CHECK:STDOUT: │ │ │ ├─InvalidParse ',' has_error
|
||||
// CHECK:STDOUT: │ │ ├─DefaultValuePattern '=' has_error
|
||||
// CHECK:STDOUT: │ │ ├─PatternListComma ','
|
||||
|
||||
@@ -79,6 +79,7 @@ fn AfterAnd(generic Z: Q where .R impls S and () = .A);
|
||||
// CHECK:STDOUT: │ │ │ │ ├─IntTypeLiteral 'i32'
|
||||
// CHECK:STDOUT: │ │ │ ├─WhereExpr 'where' has_error
|
||||
// CHECK:STDOUT: │ │ │ ╭─CompileTimeBindingPattern ':' has_error
|
||||
// CHECK:STDOUT: │ │ │ ├─DefaultValueExprStart '='
|
||||
// CHECK:STDOUT: │ │ │ │ ╭─IdentifierNameNotBeforeSignature 'U'
|
||||
// CHECK:STDOUT: │ │ │ ├─DesignatorExpr '.'
|
||||
// CHECK:STDOUT: │ │ ├─DefaultValuePattern '=' has_error
|
||||
@@ -101,6 +102,7 @@ fn AfterAnd(generic Z: Q where .R impls S and () = .A);
|
||||
// CHECK:STDOUT: │ │ │ │ ├─ParenExpr ')'
|
||||
// CHECK:STDOUT: │ │ │ ├─WhereExpr 'where' has_error
|
||||
// CHECK:STDOUT: │ │ │ ╭─CompileTimeBindingPattern ':' has_error
|
||||
// CHECK:STDOUT: │ │ │ ├─DefaultValueExprStart '='
|
||||
// CHECK:STDOUT: │ │ │ ├─BoolTypeLiteral 'bool'
|
||||
// CHECK:STDOUT: │ │ ├─DefaultValuePattern '=' has_error
|
||||
// CHECK:STDOUT: │ ├─ExplicitParamList ')' has_error
|
||||
@@ -120,6 +122,7 @@ fn AfterAnd(generic Z: Q where .R impls S and () = .A);
|
||||
// CHECK:STDOUT: │ │ │ │ ├─DesignatorExpr '.'
|
||||
// CHECK:STDOUT: │ │ │ ├─WhereExpr 'where' has_error
|
||||
// CHECK:STDOUT: │ │ │ ╭─CompileTimeBindingPattern ':' has_error
|
||||
// CHECK:STDOUT: │ │ │ ├─DefaultValueExprStart '='
|
||||
// CHECK:STDOUT: │ │ │ ├─FloatTypeLiteral 'f32'
|
||||
// CHECK:STDOUT: │ │ ├─DefaultValuePattern '=' has_error
|
||||
// CHECK:STDOUT: │ ├─ExplicitParamList ')' has_error
|
||||
@@ -139,6 +142,7 @@ fn AfterAnd(generic Z: Q where .R impls S and () = .A);
|
||||
// CHECK:STDOUT: │ │ │ │ ├─DesignatorExpr '.' has_error
|
||||
// CHECK:STDOUT: │ │ │ ├─WhereExpr 'where' has_error
|
||||
// CHECK:STDOUT: │ │ │ ╭─CompileTimeBindingPattern ':' has_error
|
||||
// CHECK:STDOUT: │ │ │ ├─DefaultValueExprStart '='
|
||||
// CHECK:STDOUT: │ │ │ ├─UnsignedIntTypeLiteral 'u8'
|
||||
// CHECK:STDOUT: │ │ ├─DefaultValuePattern '=' has_error
|
||||
// CHECK:STDOUT: │ ├─ExplicitParamList ')' has_error
|
||||
@@ -159,6 +163,7 @@ fn AfterAnd(generic Z: Q where .R impls S and () = .A);
|
||||
// CHECK:STDOUT: │ │ │ │ ├─PostfixOperatorStar '*'
|
||||
// CHECK:STDOUT: │ │ │ ├─WhereExpr 'where' has_error
|
||||
// CHECK:STDOUT: │ │ │ ╭─CompileTimeBindingPattern ':' has_error
|
||||
// CHECK:STDOUT: │ │ │ ├─DefaultValueExprStart '='
|
||||
// CHECK:STDOUT: │ │ │ │ ╭─UnsignedIntTypeLiteral 'u64'
|
||||
// CHECK:STDOUT: │ │ │ ├─PostfixOperatorStar '*'
|
||||
// CHECK:STDOUT: │ │ ├─DefaultValuePattern '=' has_error
|
||||
@@ -182,6 +187,7 @@ fn AfterAnd(generic Z: Q where .R impls S and () = .A);
|
||||
// CHECK:STDOUT: │ │ │ │ ├─InfixOperatorPlus '+'
|
||||
// CHECK:STDOUT: │ │ │ ├─WhereExpr 'where' has_error
|
||||
// CHECK:STDOUT: │ │ │ ╭─CompileTimeBindingPattern ':' has_error
|
||||
// CHECK:STDOUT: │ │ │ ├─DefaultValueExprStart '='
|
||||
// CHECK:STDOUT: │ │ │ │ ╭─StructLiteralStart '{'
|
||||
// CHECK:STDOUT: │ │ │ ├─StructLiteral '}'
|
||||
// CHECK:STDOUT: │ │ ├─DefaultValuePattern '=' has_error
|
||||
@@ -207,6 +213,7 @@ fn AfterAnd(generic Z: Q where .R impls S and () = .A);
|
||||
// CHECK:STDOUT: │ │ │ │ ├─TupleLiteral ')'
|
||||
// CHECK:STDOUT: │ │ │ ├─WhereExpr 'where' has_error
|
||||
// CHECK:STDOUT: │ │ │ ╭─CompileTimeBindingPattern ':' has_error
|
||||
// CHECK:STDOUT: │ │ │ ├─DefaultValueExprStart '='
|
||||
// CHECK:STDOUT: │ │ │ │ ╭─IdentifierNameNotBeforeSignature 'A'
|
||||
// CHECK:STDOUT: │ │ │ ├─DesignatorExpr '.'
|
||||
// CHECK:STDOUT: │ │ ├─DefaultValuePattern '=' has_error
|
||||
|
||||
@@ -377,13 +377,22 @@ using DefaultValueUnspecified =
|
||||
LeafNode<NodeKind::DefaultValueUnspecified, Lex::UnderscoreTokenIndex,
|
||||
NodeCategory::Expr>;
|
||||
|
||||
struct DefaultValueExprStart {
|
||||
static constexpr auto Kind =
|
||||
NodeKind::DefaultValueExprStart.Define({.child_count = 0});
|
||||
// This is a virtual token. The `=` token is owned by the
|
||||
// DefaultValuePattern node.
|
||||
Lex::EqualTokenIndex token;
|
||||
};
|
||||
|
||||
// A pattern with a default value specified: `pattern = expr`.
|
||||
struct DefaultValuePattern {
|
||||
static constexpr auto Kind = NodeKind::DefaultValuePattern.Define(
|
||||
{.category = NodeCategory::Pattern, .child_count = 2});
|
||||
{.category = NodeCategory::Pattern, .child_count = 3});
|
||||
|
||||
AnyPatternId pattern;
|
||||
Lex::EqualTokenIndex token;
|
||||
DefaultValueExprStartId start;
|
||||
AnyExprId default_value_expr;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user