Pass SpecificInterface through custom and C++ witness generation (#7784)

We were passing a SpecificInterfaceId which just makes code have to do a
lookup to get the actual SpecificInterface. The caller already has the
SpecificInterface, so plumb that around.

SpecificInterfaceId really only exists when we need to stick a
SpecificInterface into an instruction as an operand.
This commit is contained in:
Dana Jansens
2026-09-15 21:23:28 +00:00
committed by GitHub
parent 9e68ee0806
commit bfebb7cb42
5 changed files with 111 additions and 143 deletions
+42 -50
View File
@@ -127,10 +127,10 @@ static auto MakeSignature(
modes, SemIR::ClangDeclSignature::Normal, self_passing_mode));
}
static auto BuildCopyWitness(
Context& context, SemIR::LocId loc_id,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterfaceId query_specific_interface_id) -> SemIR::InstId {
static auto BuildCopyWitness(Context& context, SemIR::LocId loc_id,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterface query_specific_interface)
-> SemIR::InstId {
auto& clang_sema = context.clang_sema();
auto* tag_decl = TypeAsTagDecl(context, query_self_const_id);
@@ -160,18 +160,18 @@ static auto BuildCopyWitness(
return fn_id;
}
return BuildCustomWitness(context, loc_id, query_self_const_id,
query_specific_interface_id, {fn_id});
query_specific_interface, {fn_id});
}
// Otherwise it's an enum (or eventually a C struct type). Perform a primitive
// copy.
return BuildPrimitiveCopyWitness(context, loc_id, query_self_const_id,
query_specific_interface_id);
query_specific_interface);
}
static auto BuildCppUnsafeDerefWitness(
Context& context, SemIR::LocId loc_id,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterfaceId query_specific_interface_id) -> SemIR::InstId {
SemIR::SpecificInterface query_specific_interface) -> SemIR::InstId {
auto& clang_sema = context.clang_sema();
auto* class_decl = TypeAsClassDecl(context, query_self_const_id);
@@ -206,7 +206,7 @@ static auto BuildCppUnsafeDerefWitness(
.Get(context.insts().GetAs<SemIR::FunctionDecl>(fn_id).function_id)
.return_type_inst_id;
return BuildCustomWitness(
context, loc_id, query_self_const_id, query_specific_interface_id,
context, loc_id, query_self_const_id, query_specific_interface,
{context.types().GetTypeInstId(context.types().GetUnqualifiedType(
context.types().GetTypeIdForTypeInstId(result_type_inst_id))),
fn_id});
@@ -215,7 +215,7 @@ static auto BuildCppUnsafeDerefWitness(
static auto BuildDefaultWitness(
Context& context, SemIR::LocId loc_id,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterfaceId query_specific_interface_id) -> SemIR::InstId {
SemIR::SpecificInterface query_specific_interface) -> SemIR::InstId {
auto& clang_sema = context.clang_sema();
auto* class_decl = TypeAsClassDecl(context, query_self_const_id);
@@ -238,13 +238,13 @@ static auto BuildDefaultWitness(
return fn_id;
}
return BuildCustomWitness(context, loc_id, query_self_const_id,
query_specific_interface_id, {fn_id});
query_specific_interface, {fn_id});
}
static auto BuildDestroyWitness(
Context& context, SemIR::LocId loc_id,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterfaceId query_specific_interface_id) -> SemIR::InstId {
SemIR::SpecificInterface query_specific_interface) -> SemIR::InstId {
auto& clang_sema = context.clang_sema();
auto* tag_decl = TypeAsTagDecl(context, query_self_const_id);
@@ -254,7 +254,7 @@ static auto BuildDestroyWitness(
auto* class_decl = dyn_cast<clang::CXXRecordDecl>(tag_decl);
if (!class_decl) {
return BuildTrivialDestroyWitness(context, loc_id, query_self_const_id,
query_specific_interface_id);
query_specific_interface);
}
SemIR::ClangDeclSignatureId signature_id = MakeSignature(context, {});
@@ -265,14 +265,14 @@ static auto BuildDestroyWitness(
return fn_id;
}
return BuildCustomWitness(context, loc_id, query_self_const_id,
query_specific_interface_id, {fn_id});
query_specific_interface, {fn_id});
}
// Attempts to build a witness table entry for a C++ unary operator.
static auto BuildCppUnaryOperatorWitness(
Context& context, SemIR::LocId loc_id, SemIR::CoreInterface core_interface,
bool has_associated_result_type, SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterfaceId query_specific_interface_id) -> SemIR::InstId {
SemIR::SpecificInterface query_specific_interface) -> SemIR::InstId {
auto self_type_id =
context.types().GetTypeIdForTypeConstantId(query_self_const_id);
auto fn_id = LookupCppOperator(
@@ -292,26 +292,22 @@ static auto BuildCppUnaryOperatorWitness(
}
return BuildCustomWitness(context, loc_id, query_self_const_id,
query_specific_interface_id,
query_specific_interface,
{result_type_id, fn_id});
}
return BuildCustomWitness(context, loc_id, query_self_const_id,
query_specific_interface_id, {fn_id});
query_specific_interface, {fn_id});
}
// Attempts to build a witness table entry for a C++ binary operator.
static auto BuildCppBinaryOperatorWitness(
Context& context, SemIR::LocId loc_id, SemIR::CoreInterface core_interface,
bool has_associated_result_type, SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterfaceId query_specific_interface_id) -> SemIR::InstId {
SemIR::SpecificInterface query_specific_interface) -> SemIR::InstId {
auto self_type_id =
context.types().GetTypeIdForTypeConstantId(query_self_const_id);
auto args =
context.inst_blocks().Get(context.specifics()
.Get(context.specific_interfaces()
.Get(query_specific_interface_id)
.specific_id)
.args_id);
auto args = context.inst_blocks().Get(
context.specifics().Get(query_specific_interface.specific_id).args_id);
CARBON_CHECK(args.size() == 1, "Binary operator missing an argument");
auto arg_type_id = context.types().GetTypeIdForTypeInstId(args.front());
auto fn_id = LookupCppOperator(
@@ -329,26 +325,22 @@ static auto BuildCppBinaryOperatorWitness(
return SemIR::ErrorInst::InstId;
}
return BuildCustomWitness(context, loc_id, query_self_const_id,
query_specific_interface_id,
query_specific_interface,
{result_type_id, fn_id});
}
return BuildCustomWitness(context, loc_id, query_self_const_id,
query_specific_interface_id, {fn_id});
query_specific_interface, {fn_id});
}
static auto BuildCppComparisonWitness(
Context& context, SemIR::LocId loc_id, CoreIdentifier interface,
llvm::ArrayRef<CoreIdentifier> operator_names,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterfaceId query_specific_interface_id) -> SemIR::InstId {
SemIR::SpecificInterface query_specific_interface) -> SemIR::InstId {
auto self_type_id =
context.types().GetTypeIdForTypeConstantId(query_self_const_id);
auto args =
context.inst_blocks().Get(context.specifics()
.Get(context.specific_interfaces()
.Get(query_specific_interface_id)
.specific_id)
.args_id);
auto args = context.inst_blocks().Get(
context.specifics().Get(query_specific_interface.specific_id).args_id);
CARBON_CHECK(args.size() == 1, "Binary operator missing an argument");
auto arg_type_id = context.types().GetTypeIdForTypeInstId(args[0]);
@@ -384,7 +376,7 @@ static auto BuildCppComparisonWitness(
}
return BuildCustomWitness(context, loc_id, query_self_const_id,
query_specific_interface_id, operators);
query_specific_interface, operators);
}
static auto LookupCppMethod(Context& context, clang::Sema& clang_sema,
@@ -496,7 +488,7 @@ static auto BuildCppRangeForIterateWitnessImpl(
Context& context, SemIR::LocId loc_id,
LookupBeginEndCallees range_for_lookup, clang::CXXRecordDecl* class_decl,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterfaceId query_specific_interface_id) -> SemIR::InstId {
SemIR::SpecificInterface query_specific_interface) -> SemIR::InstId {
auto& clang_sema = context.clang_sema();
auto begin_name_info = clang::DeclarationNameInfo(
&clang_sema.PP.getIdentifierTable().get("begin"),
@@ -536,31 +528,31 @@ static auto BuildCppRangeForIterateWitnessImpl(
end_result_type_id != SemIR::InstId::None);
return BuildCustomWitness(
context, loc_id, query_self_const_id, query_specific_interface_id,
context, loc_id, query_self_const_id, query_specific_interface,
{begin_result_type_id, end_result_type_id, begin_fn_id, end_fn_id});
}
static auto BuildCppRangeForIterateWitness(
Context& context, SemIR::LocId loc_id,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterfaceId query_specific_interface_id) -> SemIR::InstId {
SemIR::SpecificInterface query_specific_interface) -> SemIR::InstId {
auto* class_decl = TypeAsClassDecl(context, query_self_const_id);
if (auto with_members = BuildCppRangeForIterateWitnessImpl(
context, loc_id, LookupCppMethod, class_decl, query_self_const_id,
query_specific_interface_id);
query_specific_interface);
with_members != SemIR::InstId::None) {
return with_members;
}
return BuildCppRangeForIterateWitnessImpl(
context, loc_id, LookupCppUnqualified, class_decl, query_self_const_id,
query_specific_interface_id);
query_specific_interface);
}
auto LookupCppImpl(Context& context, SemIR::LocId loc_id,
SemIR::CoreInterface core_interface,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterfaceId query_specific_interface_id,
SemIR::SpecificInterface query_specific_interface,
const TypeStructure* best_impl_type_structure,
SemIR::LocId best_impl_loc_id) -> SemIR::InstId {
// TODO: Infer a C++ type structure and check whether it's less strict than
@@ -574,11 +566,11 @@ auto LookupCppImpl(Context& context, SemIR::LocId loc_id,
return BuildCppUnaryOperatorWitness(context, loc_id, core_interface,
/*has_associated_result_type=*/false,
query_self_const_id,
query_specific_interface_id);
query_specific_interface);
case SemIR::CoreInterface::Negate:
return BuildCppUnaryOperatorWitness(
context, loc_id, core_interface, /*has_associated_result_type=*/true,
query_self_const_id, query_specific_interface_id);
query_self_const_id, query_specific_interface);
case SemIR::CoreInterface::AddWith:
case SemIR::CoreInterface::SubWith:
case SemIR::CoreInterface::MulWith:
@@ -587,7 +579,7 @@ auto LookupCppImpl(Context& context, SemIR::LocId loc_id,
return BuildCppBinaryOperatorWitness(context, loc_id, core_interface,
/*has_associated_result_type=*/true,
query_self_const_id,
query_specific_interface_id);
query_specific_interface);
case SemIR::CoreInterface::AddAssignWith:
case SemIR::CoreInterface::SubAssignWith:
case SemIR::CoreInterface::MulAssignWith:
@@ -596,34 +588,34 @@ auto LookupCppImpl(Context& context, SemIR::LocId loc_id,
return BuildCppBinaryOperatorWitness(context, loc_id, core_interface,
/*has_associated_result_type=*/false,
query_self_const_id,
query_specific_interface_id);
query_specific_interface);
case SemIR::CoreInterface::EqWith:
return BuildCppComparisonWitness(
context, loc_id, CoreIdentifier::EqWith,
{CoreIdentifier::Equal, CoreIdentifier::NotEqual},
query_self_const_id, query_specific_interface_id);
query_self_const_id, query_specific_interface);
case SemIR::CoreInterface::OrderedWith:
return BuildCppComparisonWitness(
context, loc_id, CoreIdentifier::OrderedWith,
{CoreIdentifier::Less, CoreIdentifier::LessOrEquivalent,
CoreIdentifier::Greater, CoreIdentifier::GreaterOrEquivalent},
query_self_const_id, query_specific_interface_id);
query_self_const_id, query_specific_interface);
case SemIR::CoreInterface::Copy:
return BuildCopyWitness(context, loc_id, query_self_const_id,
query_specific_interface_id);
query_specific_interface);
case SemIR::CoreInterface::CppUnsafeDeref:
return BuildCppUnsafeDerefWitness(context, loc_id, query_self_const_id,
query_specific_interface_id);
query_specific_interface);
case SemIR::CoreInterface::Default:
return BuildDefaultWitness(context, loc_id, query_self_const_id,
query_specific_interface_id);
query_specific_interface);
case SemIR::CoreInterface::Destroy:
return BuildDestroyWitness(context, loc_id, query_self_const_id,
query_specific_interface_id);
query_specific_interface);
case SemIR::CoreInterface::CppRangeForIterate:
return BuildCppRangeForIterateWitness(
context, loc_id, query_self_const_id, query_specific_interface_id);
context, loc_id, query_self_const_id, query_specific_interface);
// *FitsIn are implemented only by Carbon primitive types.
case SemIR::CoreInterface::IntFitsIn:
+1 -1
View File
@@ -40,7 +40,7 @@ namespace Carbon::Check {
auto LookupCppImpl(Context& context, SemIR::LocId loc_id,
SemIR::CoreInterface core_interface,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterfaceId query_specific_interface_id,
SemIR::SpecificInterface query_specific_interface,
const TypeStructure* best_impl_type_structure,
SemIR::LocId best_impl_loc_id) -> SemIR::InstId;
+58 -77
View File
@@ -146,11 +146,7 @@ auto MakeBuiltinOperatorFunction(Context& context, SemIR::LocId loc_id,
// Returns a FacetType that contains only the query interface.
static auto GetFacetTypeForQuerySpecificInterface(
Context& context, SemIR::LocId loc_id,
SemIR::SpecificInterfaceId query_specific_interface_id)
-> SemIR::ConstantId {
const auto query_specific_interface =
context.specific_interfaces().Get(query_specific_interface_id);
SemIR::SpecificInterface query_specific_interface) -> SemIR::ConstantId {
// The Self facet will have type FacetType, for the query interface.
auto const_id = EvalOrAddInst<SemIR::FacetType>(
context, loc_id,
@@ -163,13 +159,12 @@ static auto GetFacetTypeForQuerySpecificInterface(
// for lookups in `HasWitnessForRepeatedField`.
static auto PrepareForHasWitness(
Context& context, SemIR::LocId loc_id,
SemIR::SpecificInterfaceId query_specific_interface_id)
-> SemIR::ConstantId {
SemIR::SpecificInterface query_specific_interface) -> SemIR::ConstantId {
context.inst_block_stack().Push();
StartGenericDecl(context);
return GetFacetTypeForQuerySpecificInterface(context, loc_id,
query_specific_interface_id);
query_specific_interface);
}
// Cleans up state `PrepareForHasWitness`.
@@ -200,9 +195,9 @@ enum class DestroyFormat {
// field, this can handle the call to `PrepareForHasWitness`.
static auto HasWitnessForOneField(
Context& context, SemIR::LocId loc_id, SemIR::InstId field_inst_id,
SemIR::SpecificInterfaceId query_specific_interface_id) -> DestroyFormat {
SemIR::SpecificInterface query_specific_interface) -> DestroyFormat {
auto query_facet_type_const_id =
PrepareForHasWitness(context, loc_id, query_specific_interface_id);
PrepareForHasWitness(context, loc_id, query_specific_interface);
auto has_witness = HasWitnessForRepeatedField(context, loc_id, field_inst_id,
query_facet_type_const_id);
CleanupAfterHasWitness(context);
@@ -210,11 +205,11 @@ static auto HasWitnessForOneField(
}
// Returns true if `class_type` should impl `Destroy`.
static auto CanDestroyClass(
Context& context, SemIR::LocId loc_id, SemIR::ClassType class_type,
const SemIR::CompleteTypeInfo& complete_info,
SemIR::SpecificInterfaceId query_specific_interface_id, bool is_partial)
-> DestroyFormat {
static auto CanDestroyClass(Context& context, SemIR::LocId loc_id,
SemIR::ClassType class_type,
const SemIR::CompleteTypeInfo& complete_info,
SemIR::SpecificInterface query_specific_interface,
bool is_partial) -> DestroyFormat {
// Abstract classes can't be destroyed.
if (!is_partial && complete_info.IsAbstract()) {
return DestroyFormat::NoDestroy;
@@ -236,16 +231,16 @@ static auto CanDestroyClass(
return HasWitnessForOneField(context, loc_id,
context.types().GetTypeInstId(object_repr_id),
query_specific_interface_id);
query_specific_interface);
}
// Returns true if the `Self` should impl `Destroy`. This will recurse into impl
// lookup of `Destroy` for members, similar to `where .Self.members each impls
// Destroy`.
static auto CanDestroyType(
Context& context, SemIR::LocId loc_id,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterfaceId query_specific_interface_id) -> DestroyFormat {
static auto CanDestroyType(Context& context, SemIR::LocId loc_id,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterface query_specific_interface)
-> DestroyFormat {
auto inst_id = context.constant_values().GetInstId(
GetCanonicalFacetOrTypeValue(context, query_self_const_id));
auto inst = context.insts().Get(inst_id);
@@ -283,7 +278,7 @@ static auto CanDestroyType(
// Verify the element can be destroyed.
return HasWitnessForOneField(context, loc_id,
array_type.element_type_inst_id,
query_specific_interface_id);
query_specific_interface);
}
case SemIR::Call::Kind:
@@ -294,19 +289,19 @@ static auto CanDestroyType(
case CARBON_KIND(SemIR::ClassType class_type): {
return CanDestroyClass(context, loc_id, class_type,
context.types().GetCompleteTypeInfo(type_id),
query_specific_interface_id,
query_specific_interface,
/*is_partial=*/false);
}
case CARBON_KIND(SemIR::ConstType const_type): {
return HasWitnessForOneField(context, loc_id, const_type.inner_id,
query_specific_interface_id);
query_specific_interface);
}
case CARBON_KIND(SemIR::MaybeUnformedType maybe_unformed_type): {
return HasWitnessForOneField(context, loc_id,
maybe_unformed_type.inner_id,
query_specific_interface_id);
query_specific_interface);
}
case CARBON_KIND(SemIR::PartialType partial_type): {
@@ -316,7 +311,7 @@ static auto CanDestroyType(
context.insts().GetAs<SemIR::ClassType>(partial_type.inner_id);
return CanDestroyClass(context, loc_id, class_type,
context.types().GetCompleteTypeInfo(type_id),
query_specific_interface_id,
query_specific_interface,
/*is_partial=*/true);
}
@@ -326,7 +321,7 @@ static auto CanDestroyType(
return DestroyFormat::Trivial;
}
auto query_facet_type_const_id =
PrepareForHasWitness(context, loc_id, query_specific_interface_id);
PrepareForHasWitness(context, loc_id, query_specific_interface);
bool has_witness = true;
for (const auto& field : fields) {
if (!HasWitnessForRepeatedField(context, loc_id, field.type_inst_id,
@@ -345,7 +340,7 @@ static auto CanDestroyType(
return DestroyFormat::Trivial;
}
auto query_facet_type_const_id =
PrepareForHasWitness(context, loc_id, query_specific_interface_id);
PrepareForHasWitness(context, loc_id, query_specific_interface);
bool has_witness = true;
for (const auto& element_id : block) {
if (!HasWitnessForRepeatedField(context, loc_id, element_id,
@@ -455,7 +450,7 @@ static auto MakeDestroyOpFunction(Context& context, SemIR::LocId loc_id,
static auto MakeCustomWitnessConstantInst(
Context& context, SemIR::LocId loc_id,
SemIR::SpecificInterfaceId query_specific_interface_id,
SemIR::SpecificInterface query_specific_interface,
SemIR::InstBlockId associated_entities_block_id) -> SemIR::InstId {
// The witness is a CustomWitness of the query interface with a table that
// contains each associated entity.
@@ -463,7 +458,8 @@ static auto MakeCustomWitnessConstantInst(
context, loc_id,
{.type_id = GetSingletonType(context, SemIR::WitnessType::TypeInstId),
.elements_id = associated_entities_block_id,
.query_specific_interface_id = query_specific_interface_id});
.query_specific_interface_id =
context.specific_interfaces().Add(query_specific_interface)});
return context.constant_values().GetInstId(const_id);
}
@@ -477,13 +473,12 @@ struct TypesForSelfFacet {
static auto GetTypesForSelfFacet(
Context& context, SemIR::LocId loc_id,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterfaceId query_specific_interface_id)
-> TypesForSelfFacet {
SemIR::SpecificInterface query_specific_interface) -> TypesForSelfFacet {
// The Self facet will have type FacetType, for the query interface.
auto facet_type_for_query_specific_interface =
context.types().GetTypeIdForTypeConstantId(
GetFacetTypeForQuerySpecificInterface(context, loc_id,
query_specific_interface_id));
query_specific_interface));
// The Self facet needs to point to a type value. If it's not one already,
// convert to type.
auto query_self_as_type_id = GetFacetAsType(context, query_self_const_id);
@@ -494,14 +489,13 @@ static auto GetTypesForSelfFacet(
// interface with an entry for each associated entity so far.
static auto MakeSelfFacetWithCustomWitness(
Context& context, SemIR::LocId loc_id, TypesForSelfFacet query_types,
SemIR::SpecificInterfaceId query_specific_interface_id,
SemIR::SpecificInterface query_specific_interface,
SemIR::InstBlockId associated_entities_block_id) -> SemIR::ConstantId {
// We are building a facet value for a single interface, so the witness block
// is a single witness for that interface.
auto witnesses_block_id =
context.inst_blocks().Add({MakeCustomWitnessConstantInst(
context, loc_id, query_specific_interface_id,
associated_entities_block_id)});
auto witnesses_block_id = context.inst_blocks().Add(
{MakeCustomWitnessConstantInst(context, loc_id, query_specific_interface,
associated_entities_block_id)});
return EvalOrAddInst<SemIR::FacetValue>(
context, loc_id,
@@ -513,10 +507,8 @@ static auto MakeSelfFacetWithCustomWitness(
auto BuildCustomWitness(Context& context, SemIR::LocId loc_id,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterfaceId query_specific_interface_id,
SemIR::SpecificInterface query_specific_interface,
llvm::ArrayRef<SemIR::InstId> values) -> SemIR::InstId {
const auto query_specific_interface =
context.specific_interfaces().Get(query_specific_interface_id);
const auto& interface =
context.interfaces().Get(query_specific_interface.interface_id);
auto assoc_entities =
@@ -529,7 +521,7 @@ auto BuildCustomWitness(Context& context, SemIR::LocId loc_id,
}
auto query_types_for_self_facet = GetTypesForSelfFacet(
context, loc_id, query_self_const_id, query_specific_interface_id);
context, loc_id, query_self_const_id, query_specific_interface);
// The values that will go in the witness table.
llvm::SmallVector<SemIR::InstId> entries;
@@ -570,7 +562,7 @@ auto BuildCustomWitness(Context& context, SemIR::LocId loc_id,
if (associated_entity_state < new_associated_entity_state) {
auto self_facet = MakeSelfFacetWithCustomWitness(
context, loc_id, query_types_for_self_facet,
query_specific_interface_id, context.inst_blocks().Add(entries));
query_specific_interface, context.inst_blocks().Add(entries));
interface_with_self_specific_id = MakeSpecificWithInnerSelf(
context, loc_id, interface.generic_id,
interface.generic_with_self_id,
@@ -639,7 +631,7 @@ auto BuildCustomWitness(Context& context, SemIR::LocId loc_id,
}
return MakeCustomWitnessConstantInst(context, loc_id,
query_specific_interface_id,
query_specific_interface,
context.inst_blocks().Add(entries));
}
@@ -670,17 +662,15 @@ auto GetCoreInterface(Context& context, SemIR::InterfaceId interface_id)
auto BuildPrimitiveCopyWitness(
Context& context, SemIR::LocId loc_id,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterfaceId query_specific_interface_id) -> SemIR::InstId {
SemIR::SpecificInterface query_specific_interface) -> SemIR::InstId {
auto self_type_id = GetFacetAsType(context, query_self_const_id);
auto op_id = MakeBuiltinOperatorFunction(
context, loc_id, {self_type_id}, self_type_id, CoreIdentifier::Op,
SemIR::BuiltinFunctionKind::PrimitiveCopy,
context.specific_interfaces()
.Get(query_specific_interface_id)
.interface_id);
query_specific_interface.interface_id);
return BuildCustomWitness(context, loc_id, query_self_const_id,
query_specific_interface_id, {op_id});
query_specific_interface, {op_id});
}
// Builds and returns a custom witness that performs the specified kind of
@@ -688,18 +678,16 @@ auto BuildPrimitiveCopyWitness(
static auto BuildDestroyWitness(
Context& context, SemIR::LocId loc_id,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterfaceId query_specific_interface_id,
DestroyFormat format) -> SemIR::InstId {
SemIR::SpecificInterface query_specific_interface, DestroyFormat format)
-> SemIR::InstId {
CARBON_CHECK(format != DestroyFormat::NoDestroy);
auto self_type_id = GetFacetAsType(context, query_self_const_id);
auto op_id = MakeDestroyOpFunction(context, loc_id, self_type_id,
context.specific_interfaces()
.Get(query_specific_interface_id)
.interface_id,
format);
auto op_id =
MakeDestroyOpFunction(context, loc_id, self_type_id,
query_specific_interface.interface_id, format);
return BuildCustomWitness(context, loc_id, query_self_const_id,
query_specific_interface_id, {op_id});
query_specific_interface, {op_id});
}
// Returns the custom witness to use for destruction of the given type. See
@@ -707,10 +695,10 @@ static auto BuildDestroyWitness(
static auto LookupDestroyWitness(
Context& context, SemIR::LocId loc_id,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterfaceId query_specific_interface_id, bool build_witness)
SemIR::SpecificInterface query_specific_interface, bool build_witness)
-> std::optional<SemIR::InstId> {
auto format = CanDestroyType(context, loc_id, query_self_const_id,
query_specific_interface_id);
query_specific_interface);
if (format == DestroyFormat::NoDestroy) {
return std::nullopt;
}
@@ -721,26 +709,22 @@ static auto LookupDestroyWitness(
}
return BuildDestroyWitness(context, loc_id, query_self_const_id,
query_specific_interface_id, format);
query_specific_interface, format);
}
auto BuildTrivialDestroyWitness(
Context& context, SemIR::LocId loc_id,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterfaceId query_specific_interface_id) -> SemIR::InstId {
SemIR::SpecificInterface query_specific_interface) -> SemIR::InstId {
return BuildDestroyWitness(context, loc_id, query_self_const_id,
query_specific_interface_id,
DestroyFormat::Trivial);
query_specific_interface, DestroyFormat::Trivial);
}
static auto MakeIntFitsInWitness(
Context& context, SemIR::LocId loc_id,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterfaceId query_specific_interface_id, bool build_witness)
SemIR::SpecificInterface query_specific_interface, bool build_witness)
-> std::optional<SemIR::InstId> {
auto query_specific_interface =
context.specific_interfaces().Get(query_specific_interface_id);
auto args_id = query_specific_interface.specific_id;
if (!args_id.has_value()) {
return std::nullopt;
@@ -792,7 +776,7 @@ static auto MakeIntFitsInWitness(
return SemIR::InstId::None;
}
return BuildCustomWitness(context, loc_id, query_self_const_id,
query_specific_interface_id, {});
query_specific_interface, {});
}
return std::nullopt;
}
@@ -829,17 +813,14 @@ static auto MakeIntFitsInWitness(
}
return BuildCustomWitness(context, loc_id, query_self_const_id,
query_specific_interface_id, {});
query_specific_interface, {});
}
static auto MakeFloatFitsInWitness(
Context& context, SemIR::LocId loc_id,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterfaceId query_specific_interface_id, bool build_witness)
SemIR::SpecificInterface query_specific_interface, bool build_witness)
-> std::optional<SemIR::InstId> {
auto query_specific_interface =
context.specific_interfaces().Get(query_specific_interface_id);
auto args_id = query_specific_interface.specific_id;
if (!args_id.has_value()) {
return std::nullopt;
@@ -901,24 +882,24 @@ static auto MakeFloatFitsInWitness(
}
return BuildCustomWitness(context, loc_id, query_self_const_id,
query_specific_interface_id, {});
query_specific_interface, {});
}
auto LookupCustomWitness(Context& context, SemIR::LocId loc_id,
SemIR::CoreInterface core_interface,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterfaceId query_specific_interface_id,
SemIR::SpecificInterface query_specific_interface,
bool build_witness) -> std::optional<SemIR::InstId> {
switch (core_interface) {
case SemIR::CoreInterface::Destroy:
return LookupDestroyWitness(context, loc_id, query_self_const_id,
query_specific_interface_id, build_witness);
query_specific_interface, build_witness);
case SemIR::CoreInterface::FloatFitsIn:
return MakeFloatFitsInWitness(context, loc_id, query_self_const_id,
query_specific_interface_id, build_witness);
query_specific_interface, build_witness);
case SemIR::CoreInterface::IntFitsIn:
return MakeIntFitsInWitness(context, loc_id, query_self_const_id,
query_specific_interface_id, build_witness);
query_specific_interface, build_witness);
case SemIR::CoreInterface::AddAssignWith:
case SemIR::CoreInterface::AddWith:
case SemIR::CoreInterface::Copy:
+4 -4
View File
@@ -17,14 +17,14 @@ namespace Carbon::Check {
// values aren't suitable for the interface.
auto BuildCustomWitness(Context& context, SemIR::LocId loc_id,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterfaceId query_specific_interface_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::SpecificInterfaceId query_specific_interface_id) -> SemIR::InstId;
SemIR::SpecificInterface query_specific_interface) -> SemIR::InstId;
// Returns a manufactured operator function.
// `param_types` contains the parameter types. The first element of
@@ -44,7 +44,7 @@ auto MakeBuiltinOperatorFunction(Context& context, SemIR::LocId loc_id,
auto BuildTrivialDestroyWitness(
Context& context, SemIR::LocId loc_id,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterfaceId query_specific_interface_id) -> SemIR::InstId;
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.
@@ -64,7 +64,7 @@ auto AsCoreIdentifier(SemIR::CoreInterface core_interface) -> CoreIdentifier;
auto LookupCustomWitness(Context& context, SemIR::LocId loc_id,
SemIR::CoreInterface core_interface,
SemIR::ConstantId query_self_const_id,
SemIR::SpecificInterfaceId query_specific_interface_id,
SemIR::SpecificInterface query_specific_interface,
bool build_witness) -> std::optional<SemIR::InstId>;
} // namespace Carbon::Check
+6 -11
View File
@@ -889,19 +889,14 @@ static auto FindNonFinalWitness(
}
}
// TODO: Remove SpecificInterfaceId from LookupCustomWitness apis, switch to
// just SpecificInterface.
auto query_specific_interface_id =
context.specific_interfaces().Add(req_specific_interface);
// Consider a custom witness for core interfaces.
// TODO: This needs to expand to more interfaces, and we might want to have
// that dispatch in custom_witness.cpp instead of here.
auto core_interface =
GetCoreInterface(context, req_specific_interface.interface_id);
if (auto witness_id = LookupCustomWitness(
context, loc_id, core_interface, req_self_const_id,
query_specific_interface_id, false)) {
if (auto witness_id = LookupCustomWitness(context, loc_id, core_interface,
req_self_const_id,
req_specific_interface, false)) {
// If there's a final witness, we would have already found it via evaluating
// the LookupImplWitness instruction.
CARBON_CHECK(!witness_id->has_value());
@@ -1275,7 +1270,7 @@ auto EvalLookupSingleFinalWitness(Context& context, SemIR::LocId loc_id,
bool used_custom_witness = false;
if (auto witness_inst_id = LookupCustomWitness(
context, loc_id, core_interface, query_self_const_id,
eval_query.query_specific_interface_id, true)) {
query_specific_interface, true)) {
if (witness_inst_id->has_value()) {
lookup_result = {.witness_id =
context.constant_values().Get(*witness_inst_id)};
@@ -1316,8 +1311,8 @@ auto EvalLookupSingleFinalWitness(Context& context, SemIR::LocId loc_id,
// `impl` we may have found in Carbon.
auto cpp_witness_id = LookupCppImpl(
context, loc_id, core_interface, query_self_const_id,
eval_query.query_specific_interface_id,
lookup_result.impl_type_structure, lookup_result.impl_loc_id);
query_specific_interface, lookup_result.impl_type_structure,
lookup_result.impl_loc_id);
if (cpp_witness_id.has_value()) {
lookup_result = {.witness_id =
context.constant_values().Get(cpp_witness_id)};