Change the Destroy blanket impls to be more specific (#6098)

The main direction of this change is the edits to `destroy.carbon`
(matching in both prelude and min_prelude).

Previously there was a no-op blanket impl for `Destroy`, which hid all
missing implementations of `Destroy`. This does a few things:

- Sets up builtin aggregate destruction for struct and tuple types as
before, but also adds C++ class types and array types to the same
handling. (all as a TODO for actual implementation)
- Also maybe-unformed destruction, for now at least. (there's a chance I
may try a different approach on this, but the impl lookup wasn't working
as I'd hope in order to write it in code)
- Adds handlers for simple things that are easy to do in code: `type`,
`bool`, pointers. (because these are no-op destruction)
- Redirect `const T` destruction to `T` destruction.

This leaves as future issues:

- `partial T` destruction. (this can't be done similar to `const`
because it only works for non-`final` class types; I think `class`
definitions should just generate what's needed)
- Destruction of other prelude-provided types. (will probably come up as
we implement class destruction, that the adapted builtin type doesn't
implement `Destroy` -- but may end up special-casing that in a way that
moots it)

This moves the `&` operator from `facet_types.carbon` to
`convert.carbon` because more things need to handle type and now that
we're getting separate copy and destroy interfaces. It should be
low-cost (an interface and builtin) so hopefully this is the right
balance for complexity and re-use.

A few tests are also edited in order to focus them more on what they
intend to test, and avoid a `Destroy` dependency.
This commit is contained in:
Jon Ross-Perkins
2025-09-18 22:10:50 +00:00
committed by GitHub
parent 868c4b768c
commit 9704dc670e
143 changed files with 3271 additions and 2413 deletions
+13 -9
View File
@@ -66,9 +66,11 @@ fn F(b: bool, n: i32, m: i32) -> i32 {
// CHECK:STDOUT: %.7fa: type = fn_type_with_self_type %Copy.Op.type, %Copy.facet.c49 [concrete]
// CHECK:STDOUT: %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.f59, @Int.as.Copy.impl.Op(%int_32) [concrete]
// CHECK:STDOUT: %Destroy.type: type = facet_type <@Destroy> [concrete]
// CHECK:STDOUT: %T.as.Destroy.impl.Op.type.a60: type = fn_type @T.as.Destroy.impl.Op, @T.as.Destroy.impl(%array_type) [concrete]
// CHECK:STDOUT: %T.as.Destroy.impl.Op.913: %T.as.Destroy.impl.Op.type.a60 = struct_value () [concrete]
// CHECK:STDOUT: %T.as.Destroy.impl.Op.specific_fn: <specific function> = specific_function %T.as.Destroy.impl.Op.913, @T.as.Destroy.impl.Op(%array_type) [concrete]
// CHECK:STDOUT: %type_where: type = facet_type <type where .Self impls <CanAggregateDestroy>> [concrete]
// CHECK:STDOUT: %facet_value: %type_where = facet_value %array_type, () [concrete]
// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.type.32d: type = fn_type @AggregateT.as_type.as.Destroy.impl.Op, @AggregateT.as_type.as.Destroy.impl(%facet_value) [concrete]
// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.ab1: %AggregateT.as_type.as.Destroy.impl.Op.type.32d = struct_value () [concrete]
// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.specific_fn: <specific function> = specific_function %AggregateT.as_type.as.Destroy.impl.Op.ab1, @AggregateT.as_type.as.Destroy.impl.Op(%facet_value) [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -153,8 +155,8 @@ fn F(b: bool, n: i32, m: i32) -> i32 {
// CHECK:STDOUT: %.loc16_29.3: ref %i32 = array_index %x.var, %int_0.loc16_29
// CHECK:STDOUT: %.loc16_29.4: init %i32 = initialize_from %.loc16_29.2 to %.loc16_29.3 [concrete = constants.%int_0.6a9]
// CHECK:STDOUT: %.loc16_29.5: init %array_type = array_init (%.loc16_29.4) to %x.var [concrete = constants.%array]
// CHECK:STDOUT: %.loc16_3: init %array_type = converted %.loc16_29.1, %.loc16_29.5 [concrete = constants.%array]
// CHECK:STDOUT: assign %x.var, %.loc16_3
// CHECK:STDOUT: %.loc16_3.1: init %array_type = converted %.loc16_29.1, %.loc16_29.5 [concrete = constants.%array]
// CHECK:STDOUT: assign %x.var, %.loc16_3.1
// CHECK:STDOUT: %.loc16_22: type = splice_block %array_type [concrete = constants.%array_type] {
// CHECK:STDOUT: %int_32.loc16: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc16: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
@@ -190,11 +192,13 @@ fn F(b: bool, n: i32, m: i32) -> i32 {
// CHECK:STDOUT: %specific_fn.loc17: <specific function> = specific_function %impl.elem0.loc17, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]
// CHECK:STDOUT: %bound_method.loc17_10.2: <bound method> = bound_method %.loc17_10, %specific_fn.loc17
// CHECK:STDOUT: %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc17_10.2(%.loc17_10)
// CHECK:STDOUT: %T.as.Destroy.impl.Op.bound: <bound method> = bound_method %x.var, constants.%T.as.Destroy.impl.Op.913
// CHECK:STDOUT: %T.as.Destroy.impl.Op.specific_fn: <specific function> = specific_function constants.%T.as.Destroy.impl.Op.913, @T.as.Destroy.impl.Op(constants.%array_type) [concrete = constants.%T.as.Destroy.impl.Op.specific_fn]
// CHECK:STDOUT: %bound_method.loc16_3: <bound method> = bound_method %x.var, %T.as.Destroy.impl.Op.specific_fn
// CHECK:STDOUT: %facet_value: %type_where = facet_value constants.%array_type, () [concrete = constants.%facet_value]
// CHECK:STDOUT: %.loc16_3.2: %type_where = converted constants.%array_type, %facet_value [concrete = constants.%facet_value]
// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.bound: <bound method> = bound_method %x.var, constants.%AggregateT.as_type.as.Destroy.impl.Op.ab1
// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.specific_fn: <specific function> = specific_function constants.%AggregateT.as_type.as.Destroy.impl.Op.ab1, @AggregateT.as_type.as.Destroy.impl.Op(constants.%facet_value) [concrete = constants.%AggregateT.as_type.as.Destroy.impl.Op.specific_fn]
// CHECK:STDOUT: %bound_method.loc16_3: <bound method> = bound_method %x.var, %AggregateT.as_type.as.Destroy.impl.Op.specific_fn
// CHECK:STDOUT: %addr: %ptr.260 = addr_of %x.var
// CHECK:STDOUT: %T.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method.loc16_3(%addr)
// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method.loc16_3(%addr)
// CHECK:STDOUT: return %Int.as.Copy.impl.Op.call to %return
// CHECK:STDOUT: }
// CHECK:STDOUT: