Files
carbon-lang/toolchain/check/custom_witness.h
T
Christopher Di Bella 05a7ecbd34 Move SubobjectDestroy and SelfDestruct out of interface Destroy (#7942)
Determining that a type has trivial destruction requires checking
whether all of its subobjects have trivial destruction and whether its
type has a custom witness for `Destroy.Op`. This isn't possible when
`Destroy` is the custodian for `Destroy.Op` and `SubobjectDestroy.Op`,
so we need to make `SubobjectDestroy` its own interface.

`Destroy.SelfDestruct` becomes a standalone function because it depends
on `SubobjectDestroy` and `Destroy` being implemented, and is also
responsible for generating any custom witnesses for both interfaces.
Making `SelfDestruct` an interface was experimented with, but this
required a blanket impl that caused issues for facet types.

`Destroy` depends on `SubobjectDestroy` to be implemented. We'd ideally
use `require impls SubobjectDestroy`, but it isn't complete yet, and it
also causes problems when `Destroy` is implemented inside the class
definition. We work around this by temporarily renaming the `Destroy`
interface to `DestroyImpl`, and introducing a constraint called
`Destroy` so that user code doesn't need to write `Core.SubobjectDestroy
& Core.Destroy`.
2026-10-26 21:35:01 +00:00

73 lines
3.5 KiB
C++

// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#ifndef CARBON_TOOLCHAIN_CHECK_CUSTOM_WITNESS_H_
#define CARBON_TOOLCHAIN_CHECK_CUSTOM_WITNESS_H_
#include "toolchain/check/context.h"
#include "toolchain/sem_ir/builtin_function_kind.h"
#include "toolchain/sem_ir/ids.h"
namespace Carbon::Check {
// Builds a witness that the given type implements the given interface,
// populating it with the specified set of values. Returns a corresponding
// lookup result. Produces a diagnostic and returns `None` if the specified
// values aren't suitable for the interface.
auto BuildCustomWitness(Context& context, SemIR::LocId loc_id,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterface query_specific_interface,
llvm::ArrayRef<SemIR::InstId> values) -> SemIR::InstId;
// Builds a witness that the given type is copyable via a primitive copy.
auto BuildPrimitiveCopyWitness(
Context& context, SemIR::LocId loc_id,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterface query_specific_interface) -> SemIR::InstId;
// Returns a manufactured operator function.
// `param_types` contains the parameter types. The first element of
// `param_types` is treated as the `self` type, and any subsequent elements
// are treated as the types of the remaining explicit parameters.
// The `interface_id` is the interface containing the `op_name` function, which
// should be an interface in Core.
auto MakeBuiltinOperatorFunction(Context& context, SemIR::LocId loc_id,
llvm::ArrayRef<SemIR::TypeId> param_types,
SemIR::TypeId return_type_id,
CoreIdentifier op_name,
SemIR::BuiltinFunctionKind builtin_kind,
SemIR::InterfaceId interface_id)
-> SemIR::InstId;
// Builds a witness that the given type is trivially destroyable.
auto BuildTrivialSubobjectDestroyWitness(
Context& context, SemIR::LocId loc_id,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterface query_specific_interface) -> SemIR::InstId;
// Given an interface, returns the corresponding enum if it's covered by
// `CoreInterface`, or `Unknown` if it's some other interface.
auto GetCoreInterface(Context& context, SemIR::InterfaceId interface_id)
-> SemIR::CoreInterface;
// Maps a `CoreInterface` to its `CoreIdentifier` equivalent.
auto AsCoreIdentifier(SemIR::CoreInterface core_interface) -> CoreIdentifier;
// Returns a witness for a `CoreInterface` `CustomWitness`. A return value of
// `None` indicates a non-final witness should be produced, while `std::nullopt`
// indicates the query is final and no witness can be produced.
//
// If `build_witness` is false, this function always returns `None` as the
// witness, whether it would be final or not. It is used to indicate the
// presence of such a witness without adding instructions for it.
auto LookupCustomWitness(Context& context, SemIR::LocId loc_id,
SemIR::CoreInterface core_interface,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterface query_specific_interface,
bool build_witness) -> std::optional<SemIR::InstId>;
} // namespace Carbon::Check
#endif // CARBON_TOOLCHAIN_CHECK_CUSTOM_WITNESS_H_