diff --git a/toolchain/check/handle_impl.cpp b/toolchain/check/handle_impl.cpp index 6e9fd86789116..33ebb26de0999 100644 --- a/toolchain/check/handle_impl.cpp +++ b/toolchain/check/handle_impl.cpp @@ -202,12 +202,17 @@ static auto PopImplIntroducerAndParamsAsNameComponent( context.node_stack().PopWithNodeIdIf(); if (implicit_param_patterns_id) { - // Emit the `forall` match. This shouldn't produce any `Call` params, + // Emit the `forall` match. This shouldn't produce any valid `Call` params, // because `impl`s are never actually called at runtime. auto call_params_id = CalleePatternMatch(context, *implicit_param_patterns_id, SemIR::InstBlockId::Invalid, SemIR::InstId::Invalid); - CARBON_CHECK(call_params_id == SemIR::InstBlockId::Empty); + CARBON_CHECK(call_params_id == SemIR::InstBlockId::Empty || + llvm::all_of(context.inst_blocks().Get(call_params_id), + [](SemIR::InstId inst_id) { + return inst_id == + SemIR::ErrorInst::SingletonInstId; + })); } Parse::NodeId first_param_node_id = diff --git a/toolchain/check/testdata/impl/no_prelude/error_recovery.carbon b/toolchain/check/testdata/impl/no_prelude/error_recovery.carbon new file mode 100644 index 0000000000000..a0dbffd769ddd --- /dev/null +++ b/toolchain/check/testdata/impl/no_prelude/error_recovery.carbon @@ -0,0 +1,67 @@ +// 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/check/testdata/impl/no_prelude/error_recovery.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/no_prelude/error_recovery.carbon + +// --- fail_fuzz_crash.carbon + +class C {} +interface I {} + +// CHECK:STDERR: fail_fuzz_crash.carbon:[[@LINE+3]]:14: error: parameters of generic types must be constant [GenericParamMustBeConstant] +// CHECK:STDERR: impl forall [T: type] C as I { } +// CHECK:STDERR: ^~~~~~~ +impl forall [T: type] C as I { } + +// CHECK:STDOUT: --- fail_fuzz_crash.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [template] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [template] +// CHECK:STDOUT: %I.type: type = facet_type <@I> [template] +// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic] +// CHECK:STDOUT: %interface: = interface_witness () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .I = %I.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} {} +// CHECK:STDOUT: %I.decl: type = interface_decl @I [template = constants.%I.type] {} {} +// CHECK:STDOUT: impl_decl @impl [template] {} { +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [template = constants.%I.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @I { +// CHECK:STDOUT: %Self: %I.type = bind_symbolic_name Self, 0 [symbolic = constants.%Self] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl: %C.ref as %I.ref { +// CHECK:STDOUT: %interface: = interface_witness () [template = constants.%interface] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: witness = %interface +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [template = constants.%complete_type] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: complete_type_witness = %complete_type +// CHECK:STDOUT: } +// CHECK:STDOUT: