diff --git a/toolchain/check/convert.cpp b/toolchain/check/convert.cpp index 060aca8c4992..701974a413fb 100644 --- a/toolchain/check/convert.cpp +++ b/toolchain/check/convert.cpp @@ -1225,9 +1225,6 @@ static auto PerformBuiltinConversion( // form. We can skip past the whole impl lookup step then and do that // here. // - // See also test: - // facet_access_type_converts_back_to_original_facet_value.carbon - // // TODO: This instruction is going to become a `SymbolicBindingType`, so // we'll need to handle that instead. auto const_type_inst_id = diff --git a/toolchain/check/eval_inst.cpp b/toolchain/check/eval_inst.cpp index eab04d69cd5a..3eb83ad5ed43 100644 --- a/toolchain/check/eval_inst.cpp +++ b/toolchain/check/eval_inst.cpp @@ -210,14 +210,12 @@ auto EvalConstantInst(Context& context, SemIR::FacetValue inst) if (auto access = context.insts().TryGetAs(inst.type_inst_id)) { auto bind_id = access->facet_value_inst_id; - auto bind = context.insts().Get(bind_id); - if (bind.Is()) { - // If the FacetTypes are the same, then the FacetValue didn't add/remove - // any witnesses. - if (bind.type_id() == inst.type_id) { - return ConstantEvalResult::Existing( - context.constant_values().Get(bind_id)); - } + auto bind = context.insts().TryGetAs(bind_id); + // If the FacetTypes are the same, then the FacetValue didn't add/remove + // any witnesses. + if (bind.has_value() && bind->type_id == inst.type_id) { + return ConstantEvalResult::Existing( + context.constant_values().Get(bind_id)); } } diff --git a/toolchain/check/impl_lookup.cpp b/toolchain/check/impl_lookup.cpp index 6d8ff2fbd1d8..6f95091600a4 100644 --- a/toolchain/check/impl_lookup.cpp +++ b/toolchain/check/impl_lookup.cpp @@ -545,8 +545,19 @@ static auto GetOrAddLookupImplWitness(Context& context, SemIR::LocId loc_id, // Returns true if the `Self` should impl `Destroy`. static auto TypeCanDestroy(Context& context, SemIR::ConstantId query_self_const_id) -> bool { - auto inst = context.insts().Get( - context.constant_values().GetInstId(query_self_const_id)); + auto inst = context.insts().Get(context.constant_values().GetInstId( + GetCanonicalizedFacetOrTypeValue(context, query_self_const_id))); + + // For facet values, look if the FacetType provides the same. + if (auto facet_type = + context.types().TryGetAs(inst.type_id())) { + const auto& info = context.facet_types().Get(facet_type->facet_type_id); + if (info.builtin_constraint_mask.HasAnyOf( + SemIR::BuiltinConstraintMask::TypeCanDestroy)) { + return true; + } + } + CARBON_KIND_SWITCH(inst) { case CARBON_KIND(SemIR::ClassType class_type): { auto class_info = context.classes().Get(class_type.class_id); diff --git a/toolchain/check/testdata/builtins/type/can_destroy.carbon b/toolchain/check/testdata/builtins/type/can_destroy.carbon index 78f25d45223b..e833ec110906 100644 --- a/toolchain/check/testdata/builtins/type/can_destroy.carbon +++ b/toolchain/check/testdata/builtins/type/can_destroy.carbon @@ -38,6 +38,21 @@ fn G() { //@dump-sem-ir-end } +// --- symbolic.carbon +library "[[@TEST_NAME]]"; + +interface Z {} + +fn CanDestroy() -> type = "type.can_destroy"; + +fn G(U:! CanDestroy()) {} + +fn F(T:! Z & CanDestroy()) { + // Requires a conversion (and thus impl lookup into `T`) since `T` and `U` + // have different (but compatible) facet types. + G(T); +} + // --- fail_incomplete.carbon library "[[@TEST_NAME]]";