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
@@ -12,7 +12,7 @@
class C {
impl as Core.Copy {
fn Op[self: Self]() -> Self { return {}; }
fn Op[unused self: Self]() -> Self { return {}; }
}
}
@@ -60,12 +60,12 @@ fn M() {
// CHECK:STDOUT:
// CHECK:STDOUT: %type = type {}
// CHECK:STDOUT:
// CHECK:STDOUT: @C.val.loc15_44 = internal constant {} zeroinitializer
// CHECK:STDOUT: @C.val.loc15_51 = internal constant {} zeroinitializer
// CHECK:STDOUT:
// CHECK:STDOUT: ; Function Attrs: nounwind
// CHECK:STDOUT: define void @"_COp.C.Main:Copy.Core"(ptr sret({}) %return, ptr %self) #0 !dbg !4 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 %return, ptr align 1 @C.val.loc15_44, i64 0, i1 false), !dbg !10
// CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 %return, ptr align 1 @C.val.loc15_51, i64 0, i1 false), !dbg !10
// CHECK:STDOUT: ret void, !dbg !10
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -245,7 +245,7 @@ fn M() {
// CHECK:STDOUT: !7 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 8)
// CHECK:STDOUT: !8 = !{!9}
// CHECK:STDOUT: !9 = !DILocalVariable(arg: 1, scope: !4, type: !7)
// CHECK:STDOUT: !10 = !DILocation(line: 15, column: 35, scope: !4)
// CHECK:STDOUT: !10 = !DILocation(line: 15, column: 42, scope: !4)
// CHECK:STDOUT: !11 = distinct !DISubprogram(name: "M", linkageName: "_CM.Main", scope: null, file: !3, line: 48, type: !12, spFlags: DISPFlagDefinition, unit: !2)
// CHECK:STDOUT: !12 = !DISubroutineType(types: !13)
// CHECK:STDOUT: !13 = !{null}
@@ -11,7 +11,7 @@
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/lower/testdata/function/generic/call_method.carbon
class C {
fn F[self: Self, T:! Core.Copy](x: T) -> T {
fn F[unused self: Self, T:! Core.Copy](x: T) -> T {
return x;
}
}
@@ -12,7 +12,7 @@
class C {
impl as Core.Copy {
fn Op[self: Self]() -> Self { return {}; }
fn Op[unused self: Self]() -> Self { return {}; }
}
}
@@ -43,12 +43,12 @@ fn M() {
// CHECK:STDOUT: ; ModuleID = 'call_recursive_basic.carbon'
// CHECK:STDOUT: source_filename = "call_recursive_basic.carbon"
// CHECK:STDOUT:
// CHECK:STDOUT: @C.val.loc15_44 = internal constant {} zeroinitializer
// CHECK:STDOUT: @C.val.loc15_51 = internal constant {} zeroinitializer
// CHECK:STDOUT:
// CHECK:STDOUT: ; Function Attrs: nounwind
// CHECK:STDOUT: define void @"_COp.C.Main:Copy.Core"(ptr sret({}) %return, ptr %self) #0 !dbg !4 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 %return, ptr align 1 @C.val.loc15_44, i64 0, i1 false), !dbg !10
// CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 %return, ptr align 1 @C.val.loc15_51, i64 0, i1 false), !dbg !10
// CHECK:STDOUT: ret void, !dbg !10
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -169,7 +169,7 @@ fn M() {
// CHECK:STDOUT: !7 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 8)
// CHECK:STDOUT: !8 = !{!9}
// CHECK:STDOUT: !9 = !DILocalVariable(arg: 1, scope: !4, type: !7)
// CHECK:STDOUT: !10 = !DILocation(line: 15, column: 35, scope: !4)
// CHECK:STDOUT: !10 = !DILocation(line: 15, column: 42, scope: !4)
// CHECK:STDOUT: !11 = distinct !DISubprogram(name: "M", linkageName: "_CM.Main", scope: null, file: !3, line: 28, type: !12, spFlags: DISPFlagDefinition, unit: !2)
// CHECK:STDOUT: !12 = !DISubroutineType(types: !13)
// CHECK:STDOUT: !13 = !{null}
@@ -15,7 +15,7 @@
// generic function for an object, from a generic context.
// The specifics with a pointer type could be deduplicated here.
class C {
fn Cfn[self: Self, T:! Core.Copy](x: T) -> T {
fn Cfn[unused self: Self, T:! Core.Copy](x: T) -> T {
return x;
}
}
@@ -17,7 +17,7 @@ fn second[T:! type, U:! type, V:! type](arg1: T, arg2: U, arg3: V);
fn third[T:! type, U:! type, V:! type](arg1: T, arg2: U, arg3: V);
fn fourth[T:! type, U:! type, V:! type](arg1: T, arg2: U, arg3: V);
fn first[T:! type, U:! type, V:! type](arg1: T, arg2: U, arg3: V) {
fn first[T:! type, U:! type, V:! type](unused arg1: T, arg2: U, unused arg3: V) {
var local_name: C1*;
second(arg2, arg2, local_name);
@@ -37,7 +37,7 @@ fn third[T:! type, U:! type, V:! type](arg1: T, arg2: U, arg3: V) {
fourth(arg3, arg3, arg2);
}
fn fourth[T:! type, U:! type, V:! type](arg1: T, arg2: U, arg3: V) {
fn fourth[T:! type, U:! type, V:! type](unused arg1: T, unused arg2: U, unused arg3: V) {
}
fn Main() {
@@ -32,7 +32,7 @@ fn first_function[T:! type](arg: T);
fn second_function[T:! type, U:! type, V:! type](arg1: T, arg2: U, arg3: V);
fn third_function[T:! type, U:! type, V:! type](arg1: T, arg2: U, arg3: V) {
fn third_function[T:! type, U:! type, V:! type](arg1: T, arg2: U, unused arg3: V) {
var local1: class_name2*;
var local2: class_name2*;
@@ -40,13 +40,13 @@ fn third_function[T:! type, U:! type, V:! type](arg1: T, arg2: U, arg3: V) {
fourth_function(local1);
}
fn unused_1[T:! type, U:! type, V:! type](arg1: T, arg2: U, arg3: V) {
fn unused_1[T:! type, U:! type, V:! type](arg1: T, unused arg2: U, arg3: V) {
var local1: class_name6*;
third_function(arg1, arg3, local1);
}
fn fourth_function[T:! type](arg: T) {
fn fourth_function[T:! type](unused arg: T) {
var local1: class_name5**;
var local2: class_name6*;
@@ -67,7 +67,7 @@ fn unused_2[T:! type, U:! type](arg1: T, arg2: U) {
second_function(arg1, arg2, local1);
}
fn second_function[T:! type, U:! type, V:! type](arg1: T, arg2: U, arg3: V) {
fn second_function[T:! type, U:! type, V:! type](arg1: T, unused arg2: U, arg3: V) {
var local1: class_name3*;
var local2: class_name4*;
var local3: class_name2*;
@@ -45,7 +45,7 @@ fn F_X(a: X) -> X {
}
impl () as Copy {
fn Op[self: ()]() -> () {
fn Op[unused self: ()]() -> () {
return ();
}
}