From 3963aee8635da74112feafde22ca6a8f59a66ef9 Mon Sep 17 00:00:00 2001 From: jonmeow Date: Thu, 31 Oct 2024 09:50:43 -0700 Subject: [PATCH] Fix deduction crash for function with missing parameters. --- toolchain/check/handle_function.cpp | 2 + .../no_prelude/fail_todo_no_params.carbon | 78 +++++++++++++++++-- 2 files changed, 75 insertions(+), 5 deletions(-) diff --git a/toolchain/check/handle_function.cpp b/toolchain/check/handle_function.cpp index 5260339335a02..a510565f8d6c6 100644 --- a/toolchain/check/handle_function.cpp +++ b/toolchain/check/handle_function.cpp @@ -183,8 +183,10 @@ static auto BuildFunctionDecl(Context& context, auto name = PopNameComponent(context, return_slot_pattern_id); if (!name.params_id.is_valid()) { + CARBON_CHECK(!name.param_patterns_id.is_valid()); context.TODO(node_id, "function with positional parameters"); name.params_id = SemIR::InstBlockId::Empty; + name.param_patterns_id = SemIR::InstBlockId::Empty; } auto name_context = context.decl_name_stack().FinishName(name); diff --git a/toolchain/check/testdata/function/declaration/no_prelude/fail_todo_no_params.carbon b/toolchain/check/testdata/function/declaration/no_prelude/fail_todo_no_params.carbon index 4376d205c240f..77bb8d5116773 100644 --- a/toolchain/check/testdata/function/declaration/no_prelude/fail_todo_no_params.carbon +++ b/toolchain/check/testdata/function/declaration/no_prelude/fail_todo_no_params.carbon @@ -31,15 +31,40 @@ fn A { // TODO: We don't have parsing support for this yet. library "[[@TEST_NAME]]"; -// CHECK:STDERR: fail_todo_arrow_body.carbon:[[@LINE+7]]:1: error: semantics TODO: `function with positional parameters` [SemanticsTodo] +// CHECK:STDERR: fail_todo_arrow_body.carbon:[[@LINE+8]]:1: error: semantics TODO: `function with positional parameters` [SemanticsTodo] // CHECK:STDERR: fn A => 0; // CHECK:STDERR: ^~~~~~~~~~ // CHECK:STDERR: -// CHECK:STDERR: fail_todo_arrow_body.carbon:[[@LINE+3]]:6: error: `fn` declarations must either end with a `;` or have a `{ ... }` block for a definition [ExpectedDeclSemiOrDefinition] +// CHECK:STDERR: fail_todo_arrow_body.carbon:[[@LINE+4]]:6: error: `fn` declarations must either end with a `;` or have a `{ ... }` block for a definition [ExpectedDeclSemiOrDefinition] // CHECK:STDERR: fn A => 0; // CHECK:STDERR: ^~ +// CHECK:STDERR: fn A => 0; +// --- fail_invalid_file_generic_regression_test.carbon + +library "[[@TEST_NAME]]"; + +// CHECK:STDERR: fail_invalid_file_generic_regression_test.carbon:[[@LINE+4]]:9: error: `var` declaration cannot declare a compile-time binding [CompileTimeBindingInVarDecl] +// CHECK:STDERR: var x:! () = (); +// CHECK:STDERR: ^~ +// CHECK:STDERR: +var x:! () = (); + +// CHECK:STDERR: fail_invalid_file_generic_regression_test.carbon:[[@LINE+4]]:1: error: semantics TODO: `function with positional parameters` [SemanticsTodo] +// CHECK:STDERR: fn A { +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: +fn A { + // CHECK:STDERR: fail_invalid_file_generic_regression_test.carbon:[[@LINE+6]]:3: error: cannot deduce value for generic parameter `x` [DeductionIncomplete] + // CHECK:STDERR: A(); + // CHECK:STDERR: ^~ + // CHECK:STDERR: fail_invalid_file_generic_regression_test.carbon:[[@LINE-4]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere] + // CHECK:STDERR: fn A { + // CHECK:STDERR: ^~~~~~ + A(); +} + // CHECK:STDOUT: --- fail_no_body.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -55,7 +80,7 @@ fn A => 0; // CHECK:STDOUT: %A.decl: %A.type = fn_decl @A [template = constants.%A] {} {} // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @A; +// CHECK:STDOUT: fn @A(); // CHECK:STDOUT: // CHECK:STDOUT: --- fail_todo_brace_body.carbon // CHECK:STDOUT: @@ -72,7 +97,7 @@ fn A => 0; // CHECK:STDOUT: %A.decl: %A.type = fn_decl @A [template = constants.%A] {} {} // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @A { +// CHECK:STDOUT: fn @A() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } @@ -92,5 +117,48 @@ fn A => 0; // CHECK:STDOUT: %A.decl: %A.type = fn_decl @A [template = constants.%A] {} {} // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @A; +// CHECK:STDOUT: fn @A(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_invalid_file_generic_regression_test.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %x: %.1 = bind_symbolic_name x, 0 [symbolic] +// CHECK:STDOUT: %tuple: %.1 = tuple_value () [template] +// CHECK:STDOUT: %A.type: type = fn_type @A [template] +// CHECK:STDOUT: %A: %A.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .x = %x +// CHECK:STDOUT: .A = %A.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc8_10.1: %.1 = tuple_literal () +// CHECK:STDOUT: %.loc8_10.2: type = converted %.loc8_10.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %x.var: ref %.1 = var x +// CHECK:STDOUT: %x: %.1 = bind_symbolic_name x, 0, %x.var [symbolic = constants.%x] +// CHECK:STDOUT: %A.decl: %A.type = fn_decl @A [template = constants.%A] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @A(file.%x: %.1) { +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: +// CHECK:STDOUT: fn() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %A.ref: %A.type = name_ref A, file.%A.decl [template = constants.%A] +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc8_15.1: %.1 = tuple_literal () +// CHECK:STDOUT: %.loc8_15.2: init %.1 = tuple_init () to file.%x.var [template = constants.%tuple] +// CHECK:STDOUT: %.loc8_16: init %.1 = converted %.loc8_15.1, %.loc8_15.2 [template = constants.%tuple] +// CHECK:STDOUT: assign file.%x.var, %.loc8_16 +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @A(constants.%x) {} // CHECK:STDOUT: