diff --git a/toolchain/parse/handle_binding_pattern.cpp b/toolchain/parse/handle_binding_pattern.cpp index 06230d0f4b65..a0a43e7563e4 100644 --- a/toolchain/parse/handle_binding_pattern.cpp +++ b/toolchain/parse/handle_binding_pattern.cpp @@ -26,14 +26,12 @@ auto HandleBindingPattern(Context& context) -> void { // Handle an invalid pattern introducer for parameters and variables. auto on_error = [&]() { - CARBON_DIAGNOSTIC(ExpectedBindingPattern, Error, - "Expected binding pattern."); - context.emitter().Emit(*context.position(), ExpectedBindingPattern); - // Add a placeholder for the type. - context.AddLeafNode(NodeKind::InvalidParse, *context.position(), - /*has_error=*/true); - state.has_error = true; - context.PushState(state, State::BindingPatternFinishAsRegular); + if (!state.has_error) { + CARBON_DIAGNOSTIC(ExpectedBindingPattern, Error, + "Expected binding pattern."); + context.emitter().Emit(*context.position(), ExpectedBindingPattern); + state.has_error = true; + } }; // The first item should be an identifier or `self`. @@ -53,7 +51,6 @@ auto HandleBindingPattern(Context& context) -> void { context.AddLeafNode(NodeKind::IdentifierName, *context.position(), /*has_error=*/true); on_error(); - return; } if (auto kind = context.PositionKind(); @@ -67,7 +64,10 @@ auto HandleBindingPattern(Context& context) -> void { context.PushStateForExpr(PrecedenceGroup::ForType()); } else { on_error(); - return; + // Add a placeholder for the type. + context.AddLeafNode(NodeKind::InvalidParse, *context.position(), + /*has_error=*/true); + context.PushState(state, State::BindingPatternFinishAsRegular); } } diff --git a/toolchain/parse/testdata/let/fail_missing_name.carbon b/toolchain/parse/testdata/let/fail_missing_name.carbon new file mode 100644 index 000000000000..533fe6df1c4f --- /dev/null +++ b/toolchain/parse/testdata/let/fail_missing_name.carbon @@ -0,0 +1,49 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/parse/testdata/let/fail_missing_name.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/let/fail_missing_name.carbon + +// --- fail_runtime_binding.carbon + +// CHECK:STDERR: fail_runtime_binding.carbon:[[@LINE+4]]:5: ERROR: Expected binding pattern. +// CHECK:STDERR: let : i32 = 4; +// CHECK:STDERR: ^ +// CHECK:STDERR: +let : i32 = 4; + +// --- fail_complietime_binding.carbon + +// CHECK:STDERR: fail_complietime_binding.carbon:[[@LINE+3]]:5: ERROR: Expected binding pattern. +// CHECK:STDERR: let :! bool = true; +// CHECK:STDERR: ^~ +let :! bool = true; + +// CHECK:STDOUT: - filename: fail_runtime_binding.carbon +// CHECK:STDOUT: parse_tree: [ +// CHECK:STDOUT: {kind: 'FileStart', text: ''}, +// CHECK:STDOUT: {kind: 'LetIntroducer', text: 'let'}, +// CHECK:STDOUT: {kind: 'IdentifierName', text: ':', has_error: yes}, +// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, +// CHECK:STDOUT: {kind: 'BindingPattern', text: ':', has_error: yes, subtree_size: 3}, +// CHECK:STDOUT: {kind: 'LetInitializer', text: '='}, +// CHECK:STDOUT: {kind: 'IntLiteral', text: '4'}, +// CHECK:STDOUT: {kind: 'LetDecl', text: ';', subtree_size: 7}, +// CHECK:STDOUT: {kind: 'FileEnd', text: ''}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: - filename: fail_complietime_binding.carbon +// CHECK:STDOUT: parse_tree: [ +// CHECK:STDOUT: {kind: 'FileStart', text: ''}, +// CHECK:STDOUT: {kind: 'LetIntroducer', text: 'let'}, +// CHECK:STDOUT: {kind: 'IdentifierName', text: ':!', has_error: yes}, +// CHECK:STDOUT: {kind: 'BoolTypeLiteral', text: 'bool'}, +// CHECK:STDOUT: {kind: 'CompileTimeBindingPattern', text: ':!', has_error: yes, subtree_size: 3}, +// CHECK:STDOUT: {kind: 'LetInitializer', text: '='}, +// CHECK:STDOUT: {kind: 'BoolLiteralTrue', text: 'true'}, +// CHECK:STDOUT: {kind: 'LetDecl', text: ';', subtree_size: 7}, +// CHECK:STDOUT: {kind: 'FileEnd', text: ''}, +// CHECK:STDOUT: ]