Implement unused pattern bindings, continued (#6518)

Implementation of unused pattern bindings #2022, continued.

Whereas previous PR #6460 took care of parsing, and PR #6479 prepared
the stage by using _ in some test cases, this PR has the the actual
implementation, using a simple dataflow analysis.

---------

Co-authored-by: Burak Emir <bqe@google.com>
Co-authored-by: jonmeow <jperkins@google.com>
This commit is contained in:
Burak Emir
2026-02-19 23:33:36 +00:00
committed by GitHub
co-authored by Burak Emir jonmeow
parent bea24a8bee
commit fdb188ccfd
366 changed files with 8453 additions and 7996 deletions
@@ -14,21 +14,21 @@
fn A(n: i32, m: i32) -> i32 = "int.sadd";
// CHECK:STDERR: fail_redefined.carbon:[[@LINE+7]]:1: error: redefinition of `fn A` [RedeclRedef]
// CHECK:STDERR: fn A(n: i32, m: i32) -> i32 { return n; }
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR: fn A(n: i32, unused m: i32) -> i32 { return n; }
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR: fail_redefined.carbon:[[@LINE-4]]:1: note: previously defined here [RedeclPrevDef]
// CHECK:STDERR: fn A(n: i32, m: i32) -> i32 = "int.sadd";
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
fn A(n: i32, m: i32) -> i32 { return n; }
fn A(n: i32, unused m: i32) -> i32 { return n; }
fn B(n: i32, m: i32) -> i32 { return n; }
fn B(n: i32, unused m: i32) -> i32 { return n; }
// CHECK:STDERR: fail_redefined.carbon:[[@LINE+7]]:1: error: redefinition of `fn B` [RedeclRedef]
// CHECK:STDERR: fn B(n: i32, m: i32) -> i32 = "int.sadd";
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR: fail_redefined.carbon:[[@LINE-4]]:1: note: previously defined here [RedeclPrevDef]
// CHECK:STDERR: fn B(n: i32, m: i32) -> i32 { return n; }
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR: fn B(n: i32, unused m: i32) -> i32 { return n; }
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
fn B(n: i32, m: i32) -> i32 = "int.sadd";
@@ -131,9 +131,9 @@ fn C(n: i32, m: i32) -> i32 = "int.sadd";
// CHECK:STDOUT: %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]
// CHECK:STDOUT: %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt, call_param2 [concrete]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %int_32.loc23_25: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc23_25: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %.loc23_25: Core.Form = init_form %i32.loc23_25, call_param2 [concrete = constants.%.8ef]
// CHECK:STDOUT: %int_32.loc23_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc23_32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %.loc23_32: Core.Form = init_form %i32.loc23_32, call_param2 [concrete = constants.%.8ef]
// CHECK:STDOUT: %n.param: %i32 = value_param call_param0
// CHECK:STDOUT: %.loc23_9: type = splice_block %i32.loc23_9 [concrete = constants.%i32] {
// CHECK:STDOUT: %int_32.loc23_9: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
@@ -141,9 +141,9 @@ fn C(n: i32, m: i32) -> i32 = "int.sadd";
// CHECK:STDOUT: }
// CHECK:STDOUT: %n: %i32 = value_binding n, %n.param
// CHECK:STDOUT: %m.param: %i32 = value_param call_param1
// CHECK:STDOUT: %.loc23_17: type = splice_block %i32.loc23_17 [concrete = constants.%i32] {
// CHECK:STDOUT: %int_32.loc23_17: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc23_17: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %.loc23_24: type = splice_block %i32.loc23_24 [concrete = constants.%i32] {
// CHECK:STDOUT: %int_32.loc23_24: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc23_24: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: }
// CHECK:STDOUT: %m: %i32 = value_binding m, %m.param
// CHECK:STDOUT: %return.param: ref %i32 = out_param call_param2
@@ -157,9 +157,9 @@ fn C(n: i32, m: i32) -> i32 = "int.sadd";
// CHECK:STDOUT: %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]
// CHECK:STDOUT: %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt, call_param2 [concrete]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %int_32.loc25_25: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc25_25: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %.loc25_25: Core.Form = init_form %i32.loc25_25, call_param2 [concrete = constants.%.8ef]
// CHECK:STDOUT: %int_32.loc25_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc25_32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %.loc25_32: Core.Form = init_form %i32.loc25_32, call_param2 [concrete = constants.%.8ef]
// CHECK:STDOUT: %n.param: %i32 = value_param call_param0
// CHECK:STDOUT: %.loc25_9: type = splice_block %i32.loc25_9 [concrete = constants.%i32] {
// CHECK:STDOUT: %int_32.loc25_9: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
@@ -167,9 +167,9 @@ fn C(n: i32, m: i32) -> i32 = "int.sadd";
// CHECK:STDOUT: }
// CHECK:STDOUT: %n: %i32 = value_binding n, %n.param
// CHECK:STDOUT: %m.param: %i32 = value_param call_param1
// CHECK:STDOUT: %.loc25_17: type = splice_block %i32.loc25_17 [concrete = constants.%i32] {
// CHECK:STDOUT: %int_32.loc25_17: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc25_17: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %.loc25_24: type = splice_block %i32.loc25_24 [concrete = constants.%i32] {
// CHECK:STDOUT: %int_32.loc25_24: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc25_24: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: }
// CHECK:STDOUT: %m: %i32 = value_binding m, %m.param
// CHECK:STDOUT: %return.param: ref %i32 = out_param call_param2
@@ -261,10 +261,10 @@ fn C(n: i32, m: i32) -> i32 = "int.sadd";
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %n.ref: %i32 = name_ref n, %n
// CHECK:STDOUT: %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]
// CHECK:STDOUT: %bound_method.loc23_38.1: <bound method> = bound_method %n.ref, %impl.elem0
// CHECK:STDOUT: %bound_method.loc23_45.1: <bound method> = bound_method %n.ref, %impl.elem0
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]
// CHECK:STDOUT: %bound_method.loc23_38.2: <bound method> = bound_method %n.ref, %specific_fn
// CHECK:STDOUT: %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc23_38.2(%n.ref)
// CHECK:STDOUT: %bound_method.loc23_45.2: <bound method> = bound_method %n.ref, %specific_fn
// CHECK:STDOUT: %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc23_45.2(%n.ref)
// CHECK:STDOUT: return %Int.as.Copy.impl.Op.call
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -272,10 +272,10 @@ fn C(n: i32, m: i32) -> i32 = "int.sadd";
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %n.ref: %i32 = name_ref n, %n
// CHECK:STDOUT: %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]
// CHECK:STDOUT: %bound_method.loc25_38.1: <bound method> = bound_method %n.ref, %impl.elem0
// CHECK:STDOUT: %bound_method.loc25_45.1: <bound method> = bound_method %n.ref, %impl.elem0
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]
// CHECK:STDOUT: %bound_method.loc25_38.2: <bound method> = bound_method %n.ref, %specific_fn
// CHECK:STDOUT: %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc25_38.2(%n.ref)
// CHECK:STDOUT: %bound_method.loc25_45.2: <bound method> = bound_method %n.ref, %specific_fn
// CHECK:STDOUT: %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc25_45.2(%n.ref)
// CHECK:STDOUT: return %Int.as.Copy.impl.Op.call
// CHECK:STDOUT: }
// CHECK:STDOUT: