mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-06 10:54:49 +01:00
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:
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)};
|
||||
|
||||
Reference in New Issue
Block a user