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
+30 -30
View File
@@ -15,13 +15,13 @@
fn F() {
var s: {.a: i32, .b: i32} = {.a = 1, .b = 2};
var p: {.a: i32, .b: i32}* = &s;
var q: i32* = &s.a;
var r: i32* = &s.b;
var unused p: {.a: i32, .b: i32}* = &s;
var unused q: i32* = &s.a;
var unused r: i32* = &s.b;
var t: (i32, i32) = (1, 2);
var t0: i32* = &t.0;
var t1: i32* = &t.1;
var unused t0: i32* = &t.0;
var unused t1: i32* = &t.1;
}
// CHECK:STDOUT: --- address_of_lvalue.carbon
@@ -174,16 +174,16 @@ fn F() {
// CHECK:STDOUT: %s.ref.loc18: ref %struct_type.a.b.501 = name_ref s, %s
// CHECK:STDOUT: %addr.loc18: %ptr.3ee = addr_of %s.ref.loc18
// CHECK:STDOUT: %impl.elem0.loc18: %.4da = impl_witness_access constants.%Copy.impl_witness.00b, element0 [concrete = constants.%ptr.as.Copy.impl.Op.6e1]
// CHECK:STDOUT: %bound_method.loc18_32.1: <bound method> = bound_method %addr.loc18, %impl.elem0.loc18
// CHECK:STDOUT: %bound_method.loc18_39.1: <bound method> = bound_method %addr.loc18, %impl.elem0.loc18
// CHECK:STDOUT: %specific_fn.loc18: <specific function> = specific_function %impl.elem0.loc18, @ptr.as.Copy.impl.Op(constants.%struct_type.a.b.501) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn.8f3]
// CHECK:STDOUT: %bound_method.loc18_32.2: <bound method> = bound_method %addr.loc18, %specific_fn.loc18
// CHECK:STDOUT: %ptr.as.Copy.impl.Op.call.loc18: init %ptr.3ee = call %bound_method.loc18_32.2(%addr.loc18)
// CHECK:STDOUT: %bound_method.loc18_39.2: <bound method> = bound_method %addr.loc18, %specific_fn.loc18
// CHECK:STDOUT: %ptr.as.Copy.impl.Op.call.loc18: init %ptr.3ee = call %bound_method.loc18_39.2(%addr.loc18)
// CHECK:STDOUT: assign %p.var, %ptr.as.Copy.impl.Op.call.loc18
// CHECK:STDOUT: %.loc18: type = splice_block %ptr.loc18 [concrete = constants.%ptr.3ee] {
// CHECK:STDOUT: %int_32.loc18_15: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc18_15: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %int_32.loc18_24: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc18_24: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %int_32.loc18_22: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc18_22: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %int_32.loc18_31: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc18_31: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %struct_type.a.b.loc18: type = struct_type {.a: %i32, .b: %i32} [concrete = constants.%struct_type.a.b.501]
// CHECK:STDOUT: %ptr.loc18: type = ptr_type %struct_type.a.b.loc18 [concrete = constants.%ptr.3ee]
// CHECK:STDOUT: }
@@ -194,15 +194,15 @@ fn F() {
// CHECK:STDOUT: }
// CHECK:STDOUT: %q.var: ref %ptr.235 = var %q.var_patt
// CHECK:STDOUT: %s.ref.loc19: ref %struct_type.a.b.501 = name_ref s, %s
// CHECK:STDOUT: %.loc19_19: ref %i32 = struct_access %s.ref.loc19, element0
// CHECK:STDOUT: %addr.loc19: %ptr.235 = addr_of %.loc19_19
// CHECK:STDOUT: %.loc19_26: ref %i32 = struct_access %s.ref.loc19, element0
// CHECK:STDOUT: %addr.loc19: %ptr.235 = addr_of %.loc19_26
// CHECK:STDOUT: %impl.elem0.loc19: %.a62 = impl_witness_access constants.%Copy.impl_witness.843, element0 [concrete = constants.%ptr.as.Copy.impl.Op.011]
// CHECK:STDOUT: %bound_method.loc19_17.1: <bound method> = bound_method %addr.loc19, %impl.elem0.loc19
// CHECK:STDOUT: %bound_method.loc19_24.1: <bound method> = bound_method %addr.loc19, %impl.elem0.loc19
// CHECK:STDOUT: %specific_fn.loc19: <specific function> = specific_function %impl.elem0.loc19, @ptr.as.Copy.impl.Op(constants.%i32) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn.101]
// CHECK:STDOUT: %bound_method.loc19_17.2: <bound method> = bound_method %addr.loc19, %specific_fn.loc19
// CHECK:STDOUT: %ptr.as.Copy.impl.Op.call.loc19: init %ptr.235 = call %bound_method.loc19_17.2(%addr.loc19)
// CHECK:STDOUT: %bound_method.loc19_24.2: <bound method> = bound_method %addr.loc19, %specific_fn.loc19
// CHECK:STDOUT: %ptr.as.Copy.impl.Op.call.loc19: init %ptr.235 = call %bound_method.loc19_24.2(%addr.loc19)
// CHECK:STDOUT: assign %q.var, %ptr.as.Copy.impl.Op.call.loc19
// CHECK:STDOUT: %.loc19_13: type = splice_block %ptr.loc19 [concrete = constants.%ptr.235] {
// CHECK:STDOUT: %.loc19_20: type = splice_block %ptr.loc19 [concrete = constants.%ptr.235] {
// CHECK:STDOUT: %int_32.loc19: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc19: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %ptr.loc19: type = ptr_type %i32.loc19 [concrete = constants.%ptr.235]
@@ -214,15 +214,15 @@ fn F() {
// CHECK:STDOUT: }
// CHECK:STDOUT: %r.var: ref %ptr.235 = var %r.var_patt
// CHECK:STDOUT: %s.ref.loc20: ref %struct_type.a.b.501 = name_ref s, %s
// CHECK:STDOUT: %.loc20_19: ref %i32 = struct_access %s.ref.loc20, element1
// CHECK:STDOUT: %addr.loc20: %ptr.235 = addr_of %.loc20_19
// CHECK:STDOUT: %.loc20_26: ref %i32 = struct_access %s.ref.loc20, element1
// CHECK:STDOUT: %addr.loc20: %ptr.235 = addr_of %.loc20_26
// CHECK:STDOUT: %impl.elem0.loc20: %.a62 = impl_witness_access constants.%Copy.impl_witness.843, element0 [concrete = constants.%ptr.as.Copy.impl.Op.011]
// CHECK:STDOUT: %bound_method.loc20_17.1: <bound method> = bound_method %addr.loc20, %impl.elem0.loc20
// CHECK:STDOUT: %bound_method.loc20_24.1: <bound method> = bound_method %addr.loc20, %impl.elem0.loc20
// CHECK:STDOUT: %specific_fn.loc20: <specific function> = specific_function %impl.elem0.loc20, @ptr.as.Copy.impl.Op(constants.%i32) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn.101]
// CHECK:STDOUT: %bound_method.loc20_17.2: <bound method> = bound_method %addr.loc20, %specific_fn.loc20
// CHECK:STDOUT: %ptr.as.Copy.impl.Op.call.loc20: init %ptr.235 = call %bound_method.loc20_17.2(%addr.loc20)
// CHECK:STDOUT: %bound_method.loc20_24.2: <bound method> = bound_method %addr.loc20, %specific_fn.loc20
// CHECK:STDOUT: %ptr.as.Copy.impl.Op.call.loc20: init %ptr.235 = call %bound_method.loc20_24.2(%addr.loc20)
// CHECK:STDOUT: assign %r.var, %ptr.as.Copy.impl.Op.call.loc20
// CHECK:STDOUT: %.loc20_13: type = splice_block %ptr.loc20 [concrete = constants.%ptr.235] {
// CHECK:STDOUT: %.loc20_20: type = splice_block %ptr.loc20 [concrete = constants.%ptr.235] {
// CHECK:STDOUT: %int_32.loc20: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc20: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %ptr.loc20: type = ptr_type %i32.loc20 [concrete = constants.%ptr.235]
@@ -274,10 +274,10 @@ fn F() {
// CHECK:STDOUT: %tuple.elem0.loc23: ref %i32 = tuple_access %t.ref.loc23, element0
// CHECK:STDOUT: %addr.loc23: %ptr.235 = addr_of %tuple.elem0.loc23
// CHECK:STDOUT: %impl.elem0.loc23: %.a62 = impl_witness_access constants.%Copy.impl_witness.843, element0 [concrete = constants.%ptr.as.Copy.impl.Op.011]
// CHECK:STDOUT: %bound_method.loc23_18.1: <bound method> = bound_method %addr.loc23, %impl.elem0.loc23
// CHECK:STDOUT: %bound_method.loc23_25.1: <bound method> = bound_method %addr.loc23, %impl.elem0.loc23
// CHECK:STDOUT: %specific_fn.loc23: <specific function> = specific_function %impl.elem0.loc23, @ptr.as.Copy.impl.Op(constants.%i32) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn.101]
// CHECK:STDOUT: %bound_method.loc23_18.2: <bound method> = bound_method %addr.loc23, %specific_fn.loc23
// CHECK:STDOUT: %ptr.as.Copy.impl.Op.call.loc23: init %ptr.235 = call %bound_method.loc23_18.2(%addr.loc23)
// CHECK:STDOUT: %bound_method.loc23_25.2: <bound method> = bound_method %addr.loc23, %specific_fn.loc23
// CHECK:STDOUT: %ptr.as.Copy.impl.Op.call.loc23: init %ptr.235 = call %bound_method.loc23_25.2(%addr.loc23)
// CHECK:STDOUT: assign %t0.var, %ptr.as.Copy.impl.Op.call.loc23
// CHECK:STDOUT: %.loc23: type = splice_block %ptr.loc23 [concrete = constants.%ptr.235] {
// CHECK:STDOUT: %int_32.loc23: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
@@ -295,10 +295,10 @@ fn F() {
// CHECK:STDOUT: %tuple.elem1.loc24: ref %i32 = tuple_access %t.ref.loc24, element1
// CHECK:STDOUT: %addr.loc24: %ptr.235 = addr_of %tuple.elem1.loc24
// CHECK:STDOUT: %impl.elem0.loc24: %.a62 = impl_witness_access constants.%Copy.impl_witness.843, element0 [concrete = constants.%ptr.as.Copy.impl.Op.011]
// CHECK:STDOUT: %bound_method.loc24_18.1: <bound method> = bound_method %addr.loc24, %impl.elem0.loc24
// CHECK:STDOUT: %bound_method.loc24_25.1: <bound method> = bound_method %addr.loc24, %impl.elem0.loc24
// CHECK:STDOUT: %specific_fn.loc24: <specific function> = specific_function %impl.elem0.loc24, @ptr.as.Copy.impl.Op(constants.%i32) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn.101]
// CHECK:STDOUT: %bound_method.loc24_18.2: <bound method> = bound_method %addr.loc24, %specific_fn.loc24
// CHECK:STDOUT: %ptr.as.Copy.impl.Op.call.loc24: init %ptr.235 = call %bound_method.loc24_18.2(%addr.loc24)
// CHECK:STDOUT: %bound_method.loc24_25.2: <bound method> = bound_method %addr.loc24, %specific_fn.loc24
// CHECK:STDOUT: %ptr.as.Copy.impl.Op.call.loc24: init %ptr.235 = call %bound_method.loc24_25.2(%addr.loc24)
// CHECK:STDOUT: assign %t1.var, %ptr.as.Copy.impl.Op.call.loc24
// CHECK:STDOUT: %.loc24: type = splice_block %ptr.loc24 [concrete = constants.%ptr.235] {
// CHECK:STDOUT: %int_32.loc24: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
@@ -95,9 +95,9 @@ fn AddressOfTupleElementValue() {
}
fn AddressOfParam(param: i32) {
// CHECK:STDERR: fail_address_of_value.carbon:[[@LINE+4]]:26: error: cannot take the address of non-reference expression [AddrOfNonRef]
// CHECK:STDERR: var param_addr: i32* = &param;
// CHECK:STDERR: ^
// CHECK:STDERR: fail_address_of_value.carbon:[[@LINE+4]]:33: error: cannot take the address of non-reference expression [AddrOfNonRef]
// CHECK:STDERR: var unused param_addr: i32* = &param;
// CHECK:STDERR: ^
// CHECK:STDERR:
var param_addr: i32* = &param;
var unused param_addr: i32* = &param;
}