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
+39 -39
View File
@@ -58,11 +58,11 @@ import Cpp library "types.h";
//@include-in-dumps
fn PublicDestroy() {
var a: Cpp.PublicDestructor = {};
var unused a: Cpp.PublicDestructor = {};
}
fn TrivialDestroy() {
var a: Cpp.TrivialDestructor = {};
var unused a: Cpp.TrivialDestructor = {};
}
// --- destroy_protected_base_destructor.carbon
@@ -77,7 +77,7 @@ class Derived {
fn DestroyClassWithProtectedBaseDestructor() {
//@dump-sem-ir-begin
var a: Derived = {.base = {}};
var unused a: Derived = {.base = {}};
//@dump-sem-ir-end
}
@@ -94,7 +94,7 @@ class Derived {
fn DestroyClassWithPrivateBaseDestructor() {
//@dump-sem-ir-begin
// TODO: We should not allow this, as the destructor of the base class is private.
var a: Derived = {.base = {}};
var unused a: Derived = {.base = {}};
//@dump-sem-ir-end
}
@@ -121,47 +121,47 @@ library "[[@TEST_NAME]]";
import Cpp library "types.h";
fn AmbiguousDestroy() {
// CHECK:STDERR: fail_destroy_nondestroyable.carbon:[[@LINE+4]]:10: note: while completing C++ type `Cpp.AmbiguousDestructorT` [InCppTypeCompletion]
// CHECK:STDERR: var a: Cpp.AmbiguousDestructor = {};
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR: fail_destroy_nondestroyable.carbon:[[@LINE+4]]:17: note: while completing C++ type `Cpp.AmbiguousDestructorT` [InCppTypeCompletion]
// CHECK:STDERR: var unused a: Cpp.AmbiguousDestructor = {};
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
var a: Cpp.AmbiguousDestructor = {};
var unused a: Cpp.AmbiguousDestructor = {};
}
fn DeletedDestroy() {
// CHECK:STDERR: fail_destroy_nondestroyable.carbon:[[@LINE+8]]:3: error: attempt to use a deleted function [CppInteropParseError]
// CHECK:STDERR: 39 | var a: Cpp.DeletedDestructor = {};
// CHECK:STDERR: 39 | var unused a: Cpp.DeletedDestructor = {};
// CHECK:STDERR: | ^
// CHECK:STDERR: fail_destroy_nondestroyable.carbon:[[@LINE-14]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./types.h:23:3: note: '~DeletedDestructor' has been explicitly marked deleted here [CppInteropParseNote]
// CHECK:STDERR: 23 | ~DeletedDestructor() = delete;
// CHECK:STDERR: | ^
// CHECK:STDERR:
var a: Cpp.DeletedDestructor = {};
var unused a: Cpp.DeletedDestructor = {};
}
fn PrivateDestroy() {
// CHECK:STDERR: fail_destroy_nondestroyable.carbon:[[@LINE+8]]:3: error: cannot access private member `<C++ destructor>` of type `Cpp.PrivateDestructor` [ClassInvalidMemberAccess]
// CHECK:STDERR: var a: Cpp.PrivateDestructor = {};
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR: var unused a: Cpp.PrivateDestructor = {};
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR: fail_destroy_nondestroyable.carbon:[[@LINE-26]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./types.h:28:3: note: declared here [ClassMemberDeclaration]
// CHECK:STDERR: ~PrivateDestructor();
// CHECK:STDERR: ^
// CHECK:STDERR:
var a: Cpp.PrivateDestructor = {};
var unused a: Cpp.PrivateDestructor = {};
}
fn ProtectedDestroy() {
// CHECK:STDERR: fail_destroy_nondestroyable.carbon:[[@LINE+8]]:3: error: cannot access protected member `<C++ destructor>` of type `Cpp.ProtectedDestructor` [ClassInvalidMemberAccess]
// CHECK:STDERR: var a: Cpp.ProtectedDestructor = {};
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR: var unused a: Cpp.ProtectedDestructor = {};
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR: fail_destroy_nondestroyable.carbon:[[@LINE-38]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./types.h:33:3: note: declared here [ClassMemberDeclaration]
// CHECK:STDERR: ~ProtectedDestructor();
// CHECK:STDERR: ^
// CHECK:STDERR:
var a: Cpp.ProtectedDestructor = {};
var unused a: Cpp.ProtectedDestructor = {};
}
// --- destroy_generically.carbon
@@ -171,7 +171,7 @@ library "[[@TEST_NAME]]";
import Cpp library "types.h";
fn Destroy[T:! Core.Copy & Core.Destroy](c: T) {
var d: T = c;
var unused d: T = c;
}
fn DoDestroy() {
@@ -264,11 +264,11 @@ fn EqualWitnesses(p: Wrap(Cpp.PublicDestructor)*) -> Wrap(Cpp.PublicDestructor)*
// CHECK:STDOUT: %a.var_patt: %pattern_type.27d = var_pattern %a.patt [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %a.var: ref %PublicDestructor = var %a.var_patt
// CHECK:STDOUT: %.loc11_34.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
// CHECK:STDOUT: %.loc11_34.2: init %PublicDestructor to %a.var = class_init () [concrete = constants.%PublicDestructor.val]
// CHECK:STDOUT: %.loc11_3: init %PublicDestructor = converted %.loc11_34.1, %.loc11_34.2 [concrete = constants.%PublicDestructor.val]
// CHECK:STDOUT: %.loc11_41.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
// CHECK:STDOUT: %.loc11_41.2: init %PublicDestructor to %a.var = class_init () [concrete = constants.%PublicDestructor.val]
// CHECK:STDOUT: %.loc11_3: init %PublicDestructor = converted %.loc11_41.1, %.loc11_41.2 [concrete = constants.%PublicDestructor.val]
// CHECK:STDOUT: assign %a.var, %.loc11_3
// CHECK:STDOUT: %.loc11_13: type = splice_block %PublicDestructor.ref [concrete = constants.%PublicDestructor] {
// CHECK:STDOUT: %.loc11_20: type = splice_block %PublicDestructor.ref [concrete = constants.%PublicDestructor] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %PublicDestructor.ref: type = name_ref PublicDestructor, imports.%PublicDestructor.decl [concrete = constants.%PublicDestructor]
// CHECK:STDOUT: }
@@ -287,11 +287,11 @@ fn EqualWitnesses(p: Wrap(Cpp.PublicDestructor)*) -> Wrap(Cpp.PublicDestructor)*
// CHECK:STDOUT: %a.var_patt: %pattern_type.1b8 = var_pattern %a.patt [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %a.var: ref %TrivialDestructor = var %a.var_patt
// CHECK:STDOUT: %.loc15_35.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
// CHECK:STDOUT: %.loc15_35.2: init %TrivialDestructor to %a.var = class_init () [concrete = constants.%TrivialDestructor.val]
// CHECK:STDOUT: %.loc15_3: init %TrivialDestructor = converted %.loc15_35.1, %.loc15_35.2 [concrete = constants.%TrivialDestructor.val]
// CHECK:STDOUT: %.loc15_42.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
// CHECK:STDOUT: %.loc15_42.2: init %TrivialDestructor to %a.var = class_init () [concrete = constants.%TrivialDestructor.val]
// CHECK:STDOUT: %.loc15_3: init %TrivialDestructor = converted %.loc15_42.1, %.loc15_42.2 [concrete = constants.%TrivialDestructor.val]
// CHECK:STDOUT: assign %a.var, %.loc15_3
// CHECK:STDOUT: %.loc15_13: type = splice_block %TrivialDestructor.ref [concrete = constants.%TrivialDestructor] {
// CHECK:STDOUT: %.loc15_20: type = splice_block %TrivialDestructor.ref [concrete = constants.%TrivialDestructor] {
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %TrivialDestructor.ref: type = name_ref TrivialDestructor, imports.%TrivialDestructor.decl [concrete = constants.%TrivialDestructor]
// CHECK:STDOUT: }
@@ -330,13 +330,13 @@ fn EqualWitnesses(p: Wrap(Cpp.PublicDestructor)*) -> Wrap(Cpp.PublicDestructor)*
// CHECK:STDOUT: %a.var_patt: %pattern_type.9f6 = var_pattern %a.patt [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %a.var: ref %Derived = var %a.var_patt
// CHECK:STDOUT: %.loc12_30.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
// CHECK:STDOUT: %.loc12_31.1: %struct_type.base.f5e = struct_literal (%.loc12_30.1) [concrete = constants.%struct]
// CHECK:STDOUT: %.loc12_31.2: ref %ProtectedDestructor = class_element_access %a.var, element0
// CHECK:STDOUT: %.loc12_30.2: init %ProtectedDestructor to %.loc12_31.2 = class_init () [concrete = constants.%ProtectedDestructor.val]
// CHECK:STDOUT: %.loc12_31.3: init %ProtectedDestructor = converted %.loc12_30.1, %.loc12_30.2 [concrete = constants.%ProtectedDestructor.val]
// CHECK:STDOUT: %.loc12_31.4: init %Derived to %a.var = class_init (%.loc12_31.3) [concrete = constants.%Derived.val]
// CHECK:STDOUT: %.loc12_3: init %Derived = converted %.loc12_31.1, %.loc12_31.4 [concrete = constants.%Derived.val]
// CHECK:STDOUT: %.loc12_37.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
// CHECK:STDOUT: %.loc12_38.1: %struct_type.base.f5e = struct_literal (%.loc12_37.1) [concrete = constants.%struct]
// CHECK:STDOUT: %.loc12_38.2: ref %ProtectedDestructor = class_element_access %a.var, element0
// CHECK:STDOUT: %.loc12_37.2: init %ProtectedDestructor to %.loc12_38.2 = class_init () [concrete = constants.%ProtectedDestructor.val]
// CHECK:STDOUT: %.loc12_38.3: init %ProtectedDestructor = converted %.loc12_37.1, %.loc12_37.2 [concrete = constants.%ProtectedDestructor.val]
// CHECK:STDOUT: %.loc12_38.4: init %Derived to %a.var = class_init (%.loc12_38.3) [concrete = constants.%Derived.val]
// CHECK:STDOUT: %.loc12_3: init %Derived = converted %.loc12_38.1, %.loc12_38.4 [concrete = constants.%Derived.val]
// CHECK:STDOUT: assign %a.var, %.loc12_3
// CHECK:STDOUT: %Derived.ref: type = name_ref Derived, file.%Derived.decl [concrete = constants.%Derived]
// CHECK:STDOUT: %a: ref %Derived = ref_binding a, %a.var
@@ -374,13 +374,13 @@ fn EqualWitnesses(p: Wrap(Cpp.PublicDestructor)*) -> Wrap(Cpp.PublicDestructor)*
// CHECK:STDOUT: %a.var_patt: %pattern_type.9f6 = var_pattern %a.patt [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %a.var: ref %Derived = var %a.var_patt
// CHECK:STDOUT: %.loc13_30.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
// CHECK:STDOUT: %.loc13_31.1: %struct_type.base.f5e = struct_literal (%.loc13_30.1) [concrete = constants.%struct]
// CHECK:STDOUT: %.loc13_31.2: ref %PrivateDestructor = class_element_access %a.var, element0
// CHECK:STDOUT: %.loc13_30.2: init %PrivateDestructor to %.loc13_31.2 = class_init () [concrete = constants.%PrivateDestructor.val]
// CHECK:STDOUT: %.loc13_31.3: init %PrivateDestructor = converted %.loc13_30.1, %.loc13_30.2 [concrete = constants.%PrivateDestructor.val]
// CHECK:STDOUT: %.loc13_31.4: init %Derived to %a.var = class_init (%.loc13_31.3) [concrete = constants.%Derived.val]
// CHECK:STDOUT: %.loc13_3: init %Derived = converted %.loc13_31.1, %.loc13_31.4 [concrete = constants.%Derived.val]
// CHECK:STDOUT: %.loc13_37.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
// CHECK:STDOUT: %.loc13_38.1: %struct_type.base.f5e = struct_literal (%.loc13_37.1) [concrete = constants.%struct]
// CHECK:STDOUT: %.loc13_38.2: ref %PrivateDestructor = class_element_access %a.var, element0
// CHECK:STDOUT: %.loc13_37.2: init %PrivateDestructor to %.loc13_38.2 = class_init () [concrete = constants.%PrivateDestructor.val]
// CHECK:STDOUT: %.loc13_38.3: init %PrivateDestructor = converted %.loc13_37.1, %.loc13_37.2 [concrete = constants.%PrivateDestructor.val]
// CHECK:STDOUT: %.loc13_38.4: init %Derived to %a.var = class_init (%.loc13_38.3) [concrete = constants.%Derived.val]
// CHECK:STDOUT: %.loc13_3: init %Derived = converted %.loc13_38.1, %.loc13_38.4 [concrete = constants.%Derived.val]
// CHECK:STDOUT: assign %a.var, %.loc13_3
// CHECK:STDOUT: %Derived.ref: type = name_ref Derived, file.%Derived.decl [concrete = constants.%Derived]
// CHECK:STDOUT: %a: ref %Derived = ref_binding a, %a.var