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
+2 -2
View File
@@ -11,12 +11,12 @@
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/generic/call_basic_depth.carbon
class C {
fn Cfn[self: Self, T:! type](x: T) {
fn Cfn[unused self: Self, T:! type](unused x: T) {
}
}
//@dump-sem-ir-begin
fn F[T:! type](x: T) {
fn F[T:! type](unused x: T) {
}
//@dump-sem-ir-end
+7 -7
View File
@@ -28,18 +28,18 @@ class A(T:! type) {
var v: T;
}
// CHECK:STDERR: fail_incomplete_in_class.carbon:[[@LINE+11]]:6: note: in `A(B)` used here [ResolvingSpecificHere]
// CHECK:STDERR: fn F(x: A(B)) {}
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: fail_incomplete_in_class.carbon:[[@LINE+11]]:13: note: in `A(B)` used here [ResolvingSpecificHere]
// CHECK:STDERR: fn F(unused x: A(B)) {}
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR:
// CHECK:STDERR: fail_incomplete_in_class.carbon:[[@LINE+7]]:6: error: parameter has incomplete type `A(B)` in function definition [IncompleteTypeInFunctionParam]
// CHECK:STDERR: fn F(x: A(B)) {}
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: fail_incomplete_in_class.carbon:[[@LINE+7]]:13: error: parameter has incomplete type `A(B)` in function definition [IncompleteTypeInFunctionParam]
// CHECK:STDERR: fn F(unused x: A(B)) {}
// CHECK:STDERR: ^~~~~~~
// CHECK:STDERR: fail_incomplete_in_class.carbon:[[@LINE-19]]:1: note: class was forward declared here [ClassForwardDeclaredHere]
// CHECK:STDERR: class B;
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR:
fn F(x: A(B)) {}
fn F(unused x: A(B)) {}
class B {}
@@ -21,7 +21,7 @@ class C(CC:! type) {
// The `.Self` bind_symbolic_name here should have a
// symbolic constant value, not symbolic_self, because
// its type depends on `CC`.
fn F(T:! A(CC) where .X = CC) {}
fn F(unused T:! A(CC) where .X = CC) {}
//@dump-sem-ir-end
}
@@ -32,8 +32,8 @@ class D(DD:! type) {
// CHECK:STDERR: C(DD).F(T);
// CHECK:STDERR: ^~~~~~~~~~
// CHECK:STDERR: fail_dot_self_symbolic_type.carbon:[[@LINE-10]]:3: note: while deducing parameters of generic declared here [DeductionGenericHere]
// CHECK:STDERR: fn F(T:! A(CC) where .X = CC) {}
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR: fn F(unused T:! A(CC) where .X = CC) {}
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
C(DD).F(T);
//@dump-sem-ir-end
@@ -134,25 +134,25 @@ fn H(T:! type) {
// CHECK:STDOUT: %C.F.decl: @C.%C.F.type (%C.F.type.1f899e.1) = fn_decl @C.F [symbolic = @C.%C.F (constants.%C.F.faeec9.1)] {
// CHECK:STDOUT: %T.patt: @C.F.%pattern_type (%pattern_type.1d5) = symbolic_binding_pattern T, 1 [concrete]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %.loc11_18.1: type = splice_block %.loc11_18.2 [symbolic = %A_where.type (constants.%A_where.type.4028e0.1)] {
// CHECK:STDOUT: %.loc11_25.1: type = splice_block %.loc11_25.2 [symbolic = %A_where.type (constants.%A_where.type.4028e0.1)] {
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %A.ref: %A.type.464 = name_ref A, file.%A.decl [concrete = constants.%A.generic]
// CHECK:STDOUT: %CC.ref.loc11_14: type = name_ref CC, @C.%CC.loc6_9.2 [symbolic = %CC (constants.%CC)]
// CHECK:STDOUT: %A.type.loc11_16.2: type = facet_type <@A, @A(constants.%CC)> [symbolic = %A.type.loc11_16.1 (constants.%A.type.ade3d9.2)]
// CHECK:STDOUT: %CC.ref.loc11_21: type = name_ref CC, @C.%CC.loc6_9.2 [symbolic = %CC (constants.%CC)]
// CHECK:STDOUT: %A.type.loc11_23.2: type = facet_type <@A, @A(constants.%CC)> [symbolic = %A.type.loc11_23.1 (constants.%A.type.ade3d9.2)]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %.Self.ref: @C.F.%A.type.loc11_16.1 (%A.type.ade3d9.2) = name_ref .Self, %.Self.3 [symbolic = %.Self.1 (constants.%.Self.660472.1)]
// CHECK:STDOUT: %.Self.ref: @C.F.%A.type.loc11_23.1 (%A.type.ade3d9.2) = name_ref .Self, %.Self.3 [symbolic = %.Self.1 (constants.%.Self.660472.1)]
// CHECK:STDOUT: %.Self.as_type: type = facet_access_type %.Self.ref [symbolic = %.Self.binding.as_type (constants.%.Self.binding.as_type)]
// CHECK:STDOUT: %.loc11_24.1: type = converted %.Self.ref, %.Self.as_type [symbolic = %.Self.binding.as_type (constants.%.Self.binding.as_type)]
// CHECK:STDOUT: %.loc11_24.2: @C.F.%A.assoc_type (%A.assoc_type.9f4820.2) = specific_constant @X.%assoc0, @A(constants.%CC, constants.%.Self.660472.1) [symbolic = %assoc0 (constants.%assoc0.9fa860.2)]
// CHECK:STDOUT: %X.ref: @C.F.%A.assoc_type (%A.assoc_type.9f4820.2) = name_ref X, %.loc11_24.2 [symbolic = %assoc0 (constants.%assoc0.9fa860.2)]
// CHECK:STDOUT: %impl.elem0.loc11_24.2: type = impl_witness_access constants.%A.lookup_impl_witness.04abbb.1, element0 [symbolic = %impl.elem0.loc11_24.1 (constants.%impl.elem0.f51d29.1)]
// CHECK:STDOUT: %CC.ref.loc11_29: type = name_ref CC, @C.%CC.loc6_9.2 [symbolic = %CC (constants.%CC)]
// CHECK:STDOUT: %.loc11_18.2: type = where_expr %.Self.3 [symbolic = %A_where.type (constants.%A_where.type.4028e0.1)] {
// CHECK:STDOUT: %.loc11_31.1: type = converted %.Self.ref, %.Self.as_type [symbolic = %.Self.binding.as_type (constants.%.Self.binding.as_type)]
// CHECK:STDOUT: %.loc11_31.2: @C.F.%A.assoc_type (%A.assoc_type.9f4820.2) = specific_constant @X.%assoc0, @A(constants.%CC, constants.%.Self.660472.1) [symbolic = %assoc0 (constants.%assoc0.9fa860.2)]
// CHECK:STDOUT: %X.ref: @C.F.%A.assoc_type (%A.assoc_type.9f4820.2) = name_ref X, %.loc11_31.2 [symbolic = %assoc0 (constants.%assoc0.9fa860.2)]
// CHECK:STDOUT: %impl.elem0.loc11_31.2: type = impl_witness_access constants.%A.lookup_impl_witness.04abbb.1, element0 [symbolic = %impl.elem0.loc11_31.1 (constants.%impl.elem0.f51d29.1)]
// CHECK:STDOUT: %CC.ref.loc11_36: type = name_ref CC, @C.%CC.loc6_9.2 [symbolic = %CC (constants.%CC)]
// CHECK:STDOUT: %.loc11_25.2: type = where_expr %.Self.3 [symbolic = %A_where.type (constants.%A_where.type.4028e0.1)] {
// CHECK:STDOUT: requirement_base_facet_type constants.%A.type.ade3d9.2
// CHECK:STDOUT: requirement_rewrite %impl.elem0.loc11_24.2, %CC.ref.loc11_29
// CHECK:STDOUT: requirement_rewrite %impl.elem0.loc11_31.2, %CC.ref.loc11_36
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT: %T.loc11_8.2: @C.F.%A_where.type (%A_where.type.4028e0.1) = symbolic_binding T, 1 [symbolic = %T.loc11_8.1 (constants.%T.6c0)]
// CHECK:STDOUT: %T.loc11_15.2: @C.F.%A_where.type (%A_where.type.4028e0.1) = symbolic_binding T, 1 [symbolic = %T.loc11_15.1 (constants.%T.6c0)]
// CHECK:STDOUT: }
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: complete_type_witness = %complete_type
@@ -183,18 +183,18 @@ fn H(T:! type) {
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: generic fn @C.F(@C.%CC.loc6_9.2: type, %T.loc11_8.2: @C.F.%A_where.type (%A_where.type.4028e0.1)) {
// CHECK:STDOUT: generic fn @C.F(@C.%CC.loc6_9.2: type, %T.loc11_15.2: @C.F.%A_where.type (%A_where.type.4028e0.1)) {
// CHECK:STDOUT: %CC: type = symbolic_binding CC, 0 [symbolic = %CC (constants.%CC)]
// CHECK:STDOUT: %A.type.loc11_16.1: type = facet_type <@A, @A(%CC)> [symbolic = %A.type.loc11_16.1 (constants.%A.type.ade3d9.2)]
// CHECK:STDOUT: %A.type.loc11_23.1: type = facet_type <@A, @A(%CC)> [symbolic = %A.type.loc11_23.1 (constants.%A.type.ade3d9.2)]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %require_complete: <witness> = require_complete_type %A.type.loc11_16.1 [symbolic = %require_complete (constants.%require_complete.f58)]
// CHECK:STDOUT: %require_complete: <witness> = require_complete_type %A.type.loc11_23.1 [symbolic = %require_complete (constants.%require_complete.f58)]
// CHECK:STDOUT: %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self.1 [symbolic = %.Self.binding.as_type (constants.%.Self.binding.as_type)]
// CHECK:STDOUT: %A.assoc_type: type = assoc_entity_type @A, @A(%CC) [symbolic = %A.assoc_type (constants.%A.assoc_type.9f4820.2)]
// CHECK:STDOUT: %assoc0: @C.F.%A.assoc_type (%A.assoc_type.9f4820.2) = assoc_entity element0, @A.%X [symbolic = %assoc0 (constants.%assoc0.9fa860.2)]
// CHECK:STDOUT: %A.lookup_impl_witness: <witness> = lookup_impl_witness %.Self.1, @A, @A(%CC) [symbolic = %A.lookup_impl_witness (constants.%A.lookup_impl_witness.04abbb.1)]
// CHECK:STDOUT: %impl.elem0.loc11_24.1: type = impl_witness_access %A.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc11_24.1 (constants.%impl.elem0.f51d29.1)]
// CHECK:STDOUT: %A_where.type: type = facet_type <@A, @A(%CC) where %impl.elem0.loc11_24.1 = %CC> [symbolic = %A_where.type (constants.%A_where.type.4028e0.1)]
// CHECK:STDOUT: %T.loc11_8.1: @C.F.%A_where.type (%A_where.type.4028e0.1) = symbolic_binding T, 1 [symbolic = %T.loc11_8.1 (constants.%T.6c0)]
// CHECK:STDOUT: %impl.elem0.loc11_31.1: type = impl_witness_access %A.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc11_31.1 (constants.%impl.elem0.f51d29.1)]
// CHECK:STDOUT: %A_where.type: type = facet_type <@A, @A(%CC) where %impl.elem0.loc11_31.1 = %CC> [symbolic = %A_where.type (constants.%A_where.type.4028e0.1)]
// CHECK:STDOUT: %T.loc11_15.1: @C.F.%A_where.type (%A_where.type.4028e0.1) = symbolic_binding T, 1 [symbolic = %T.loc11_15.1 (constants.%T.6c0)]
// CHECK:STDOUT: %pattern_type: type = pattern_type %A_where.type [symbolic = %pattern_type (constants.%pattern_type.1d5)]
// CHECK:STDOUT:
// CHECK:STDOUT: !definition:
@@ -241,16 +241,16 @@ fn H(T:! type) {
// CHECK:STDOUT:
// CHECK:STDOUT: specific @C.F(constants.%CC, constants.%T.6c0) {
// CHECK:STDOUT: %CC => constants.%CC
// CHECK:STDOUT: %A.type.loc11_16.1 => constants.%A.type.ade3d9.2
// CHECK:STDOUT: %A.type.loc11_23.1 => constants.%A.type.ade3d9.2
// CHECK:STDOUT: %.Self.1 => constants.%.Self.660472.1
// CHECK:STDOUT: %require_complete => constants.%require_complete.f58
// CHECK:STDOUT: %.Self.binding.as_type => constants.%.Self.binding.as_type
// CHECK:STDOUT: %A.assoc_type => constants.%A.assoc_type.9f4820.2
// CHECK:STDOUT: %assoc0 => constants.%assoc0.9fa860.2
// CHECK:STDOUT: %A.lookup_impl_witness => constants.%A.lookup_impl_witness.04abbb.1
// CHECK:STDOUT: %impl.elem0.loc11_24.1 => constants.%impl.elem0.f51d29.1
// CHECK:STDOUT: %impl.elem0.loc11_31.1 => constants.%impl.elem0.f51d29.1
// CHECK:STDOUT: %A_where.type => constants.%A_where.type.4028e0.1
// CHECK:STDOUT: %T.loc11_8.1 => constants.%T.6c0
// CHECK:STDOUT: %T.loc11_15.1 => constants.%T.6c0
// CHECK:STDOUT: %pattern_type => constants.%pattern_type.1d5
// CHECK:STDOUT: }
// CHECK:STDOUT:
+7 -7
View File
@@ -30,12 +30,12 @@ fn F[T:! type](x: T) -> T {
library "[[@TEST_NAME]]";
fn F[T:! Core.Destroy](x: T) {
// CHECK:STDERR: fail_var.carbon:[[@LINE+7]]:14: error: cannot copy value of type `T` [CopyOfUncopyableType]
// CHECK:STDERR: var y: T = x;
// CHECK:STDERR: ^
// CHECK:STDERR: fail_var.carbon:[[@LINE+4]]:14: note: type `T` does not implement interface `Core.Copy` [MissingImplInMemberAccessNote]
// CHECK:STDERR: var y: T = x;
// CHECK:STDERR: ^
// CHECK:STDERR: fail_var.carbon:[[@LINE+7]]:21: error: cannot copy value of type `T` [CopyOfUncopyableType]
// CHECK:STDERR: var unused y: T = x;
// CHECK:STDERR: ^
// CHECK:STDERR: fail_var.carbon:[[@LINE+4]]:21: note: type `T` does not implement interface `Core.Copy` [MissingImplInMemberAccessNote]
// CHECK:STDERR: var unused y: T = x;
// CHECK:STDERR: ^
// CHECK:STDERR:
var y: T = x;
var unused y: T = x;
}
+1 -1
View File
@@ -21,4 +21,4 @@ fn F() {
G({} as C);
}
fn G[T:! Z](p: T) {}
fn G[T:! Z](unused p: T) {}
+11 -11
View File
@@ -20,7 +20,7 @@ fn F() {
class C(T:! type) {
var x: T;
}
var v: C(i32) = {.x = 1};
var unused v: C(i32) = {.x = 1};
}
// --- fail_param_shadows_class.carbon
@@ -161,19 +161,19 @@ class C(C:! type) {
// CHECK:STDOUT: }
// CHECK:STDOUT: %v.var: ref %C.d45 = var %v.var_patt
// CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
// CHECK:STDOUT: %.loc8_26.1: %struct_type.x.c96 = struct_literal (%int_1) [concrete = constants.%struct]
// CHECK:STDOUT: %.loc8_33.1: %struct_type.x.c96 = struct_literal (%int_1) [concrete = constants.%struct]
// CHECK:STDOUT: %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]
// CHECK:STDOUT: %bound_method.loc8_26.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]
// CHECK:STDOUT: %bound_method.loc8_33.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]
// CHECK:STDOUT: %bound_method.loc8_26.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method]
// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc8_26.2(%int_1) [concrete = constants.%int_1.5d2]
// CHECK:STDOUT: %.loc8_26.2: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.5d2]
// CHECK:STDOUT: %.loc8_26.3: ref %i32 = class_element_access %v.var, element0
// CHECK:STDOUT: %.loc8_26.4: init %i32 to %.loc8_26.3 = in_place_init %.loc8_26.2 [concrete = constants.%int_1.5d2]
// CHECK:STDOUT: %.loc8_26.5: init %C.d45 to %v.var = class_init (%.loc8_26.4) [concrete = constants.%C.val]
// CHECK:STDOUT: %.loc8_3: init %C.d45 = converted %.loc8_26.1, %.loc8_26.5 [concrete = constants.%C.val]
// CHECK:STDOUT: %bound_method.loc8_33.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method]
// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc8_33.2(%int_1) [concrete = constants.%int_1.5d2]
// CHECK:STDOUT: %.loc8_33.2: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.5d2]
// CHECK:STDOUT: %.loc8_33.3: ref %i32 = class_element_access %v.var, element0
// CHECK:STDOUT: %.loc8_33.4: init %i32 to %.loc8_33.3 = in_place_init %.loc8_33.2 [concrete = constants.%int_1.5d2]
// CHECK:STDOUT: %.loc8_33.5: init %C.d45 to %v.var = class_init (%.loc8_33.4) [concrete = constants.%C.val]
// CHECK:STDOUT: %.loc8_3: init %C.d45 = converted %.loc8_33.1, %.loc8_33.5 [concrete = constants.%C.val]
// CHECK:STDOUT: assign %v.var, %.loc8_3
// CHECK:STDOUT: %.loc8_15: type = splice_block %C [concrete = constants.%C.d45] {
// CHECK:STDOUT: %.loc8_22: type = splice_block %C [concrete = constants.%C.d45] {
// CHECK:STDOUT: %C.ref: %C.type = name_ref C, %C.decl [concrete = constants.%C.generic]
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
@@ -52,22 +52,22 @@ library "[[@TEST_NAME]]";
fn F[template T:! Core.Destroy](x: T) {
// TODO: These diagnostics aren't very good, and we should only produce one error here.
// CHECK:STDERR: fail_todo_unimplemented_convert.carbon:[[@LINE+8]]:3: error: member name of type `<dependent type>` in compound member access is not an instance member or an interface member [CompoundMemberAccessDoesNotUseBase]
// CHECK:STDERR: var v: T = 0;
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR: var unused v: T = 0;
// CHECK:STDERR: ^~~~~~~~~~~~~~~
// CHECK:STDERR:
// CHECK:STDERR: fail_todo_unimplemented_convert.carbon:[[@LINE+4]]:3: error: value of type `<dependent type>` is not callable [CallToNonCallable]
// CHECK:STDERR: var v: T = 0;
// CHECK:STDERR: ^~~~~~~~
// CHECK:STDERR: var unused v: T = 0;
// CHECK:STDERR: ^~~~~~~~~~~~~~~
// CHECK:STDERR:
var v: T = 0;
var unused v: T = 0;
// CHECK:STDERR: fail_todo_unimplemented_convert.carbon:[[@LINE+7]]:3: error: cannot implicitly convert expression of type `T` to `i32` [ConversionFailure]
// CHECK:STDERR: var w: i32 = x;
// CHECK:STDERR: ^~~~~~~~~~
// CHECK:STDERR: var unused w: i32 = x;
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~
// CHECK:STDERR: fail_todo_unimplemented_convert.carbon:[[@LINE+4]]:3: note: type `T` does not implement interface `Core.ImplicitAs(i32)` [MissingImplInMemberAccessNote]
// CHECK:STDERR: var w: i32 = x;
// CHECK:STDERR: ^~~~~~~~~~
// CHECK:STDERR: var unused w: i32 = x;
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~
// CHECK:STDERR:
var w: i32 = x;
var unused w: i32 = x;
}
// CHECK:STDOUT: --- fail_todo_unimplemented_operator.carbon
@@ -347,10 +347,10 @@ fn F[template T:! Core.Destroy](x: T) {
// CHECK:STDOUT: %.loc14_3.1: @F.%.loc14_3.4 (@F.%.loc14_3.4) = splice_inst %.loc14_3.3
// CHECK:STDOUT: %.loc14_3.2: @F.%T.binding.as_type (%T.binding.as_type.140) = converted %int_0, <error> [concrete = <error>]
// CHECK:STDOUT: assign %v.var, <error>
// CHECK:STDOUT: %.loc14_10.1: type = splice_block %.loc14_10.2 [template = %T.binding.as_type (constants.%T.binding.as_type.140)] {
// CHECK:STDOUT: %.loc14_17.1: type = splice_block %.loc14_17.2 [template = %T.binding.as_type (constants.%T.binding.as_type.140)] {
// CHECK:STDOUT: %T.ref.loc14: %Destroy.type = name_ref T, %T.loc4_15.2 [template = %T.loc4_15.1 (constants.%T.765)]
// CHECK:STDOUT: %T.as_type.loc14: type = facet_access_type %T.ref.loc14 [template = %T.binding.as_type (constants.%T.binding.as_type.140)]
// CHECK:STDOUT: %.loc14_10.2: type = converted %T.ref.loc14, %T.as_type.loc14 [template = %T.binding.as_type (constants.%T.binding.as_type.140)]
// CHECK:STDOUT: %.loc14_17.2: type = converted %T.ref.loc14, %T.as_type.loc14 [template = %T.binding.as_type (constants.%T.binding.as_type.140)]
// CHECK:STDOUT: }
// CHECK:STDOUT: %v: ref @F.%T.binding.as_type (%T.binding.as_type.140) = ref_binding v, %v.var
// CHECK:STDOUT: name_binding_decl {
@@ -361,7 +361,7 @@ fn F[template T:! Core.Destroy](x: T) {
// CHECK:STDOUT: %x.ref: @F.%T.binding.as_type (%T.binding.as_type.140) = name_ref x, %x
// CHECK:STDOUT: %.loc22_3: %i32 = converted %x.ref, <error> [concrete = <error>]
// CHECK:STDOUT: assign %w.var, <error>
// CHECK:STDOUT: %.loc22_10: type = splice_block %i32 [concrete = constants.%i32] {
// CHECK:STDOUT: %.loc22_17: type = splice_block %i32 [concrete = constants.%i32] {
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: }