mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 18:30:30 +01:00
Use identified facet type to get impl-as target (#7519)
This supports impl lookup choosing an impl that targets a generic interface through a named constraint, without crashing. Instead of assuming the impl's target is a facet type containing an interface, we use the identified facet type to find the specific interface it targets.
This commit is contained in:
@@ -243,15 +243,16 @@ static auto TreatImplAsFinal(Context& context, const SemIR::Impl& impl)
|
||||
static auto TryGetSpecificWitnessIdForImpl(
|
||||
Context& context, SemIR::LocId loc_id,
|
||||
SemIR::ConstantId query_self_const_id,
|
||||
const SemIR::SpecificInterface& interface, SemIR::ImplId impl_id,
|
||||
const SemIR::Impl& impl) -> SemIR::ConstantId {
|
||||
const SemIR::SpecificInterface& query_specific_interface,
|
||||
SemIR::ImplId impl_id, const SemIR::Impl& impl) -> SemIR::ConstantId {
|
||||
// The impl may have generic arguments, in which case we need to deduce them
|
||||
// to find what they are given the specific type and interface query. We use
|
||||
// that specific to map values in the impl to the deduced values.
|
||||
auto specific_id = SemIR::SpecificId::None;
|
||||
if (impl.generic_id.has_value()) {
|
||||
specific_id = DeduceImplArguments(
|
||||
context, loc_id, impl_id, query_self_const_id, interface.specific_id);
|
||||
specific_id =
|
||||
DeduceImplArguments(context, loc_id, impl_id, query_self_const_id,
|
||||
query_specific_interface.specific_id);
|
||||
if (!specific_id.has_value()) {
|
||||
return SemIR::ConstantId::None;
|
||||
}
|
||||
@@ -282,21 +283,31 @@ static auto TryGetSpecificWitnessIdForImpl(
|
||||
return SemIR::ConstantId::None;
|
||||
}
|
||||
|
||||
auto deduced_constraint_facet_type_id =
|
||||
context.constant_values()
|
||||
.GetInstAs<SemIR::FacetType>(deduced_constraint_id)
|
||||
.facet_type_id;
|
||||
const auto& deduced_constraint_facet_type_info =
|
||||
context.facet_types().Get(deduced_constraint_facet_type_id);
|
||||
CARBON_CHECK(deduced_constraint_facet_type_info.extend_constraints.size() ==
|
||||
1);
|
||||
// Get the identified facet type of the deduced impl's constraint, so we can
|
||||
// get the specific interface being implemented after deduction.
|
||||
auto deduced_constrant_type_inst_id =
|
||||
context.types().GetTypeInstIdForTypeConstantId(deduced_constraint_id);
|
||||
auto deduced_constraint_identified_facet_type_id =
|
||||
TryToIdentifyFacetType(context, loc_id, deduced_self_const_id,
|
||||
deduced_constrant_type_inst_id, false);
|
||||
if (!deduced_constraint_identified_facet_type_id.has_value()) {
|
||||
return SemIR::ConstantId::None;
|
||||
}
|
||||
|
||||
const auto& deduced_constraint_identified_facet_type =
|
||||
context.identified_facet_types().Get(
|
||||
deduced_constraint_identified_facet_type_id);
|
||||
// We only find valid impls in impl lookup, which implement a single specific
|
||||
// interface.
|
||||
CARBON_CHECK(
|
||||
deduced_constraint_identified_facet_type.is_valid_impl_as_target());
|
||||
|
||||
// The specifics in the queried interface must match the deduced specifics in
|
||||
// the impl's constraint facet type.
|
||||
auto impl_interface_specific_id =
|
||||
deduced_constraint_facet_type_info.extend_constraints[0].specific_id;
|
||||
auto query_interface_specific_id = interface.specific_id;
|
||||
if (impl_interface_specific_id != query_interface_specific_id) {
|
||||
deduced_constraint_identified_facet_type.impl_as_target_interface()
|
||||
.specific_id;
|
||||
if (impl_interface_specific_id != query_specific_interface.specific_id) {
|
||||
return SemIR::ConstantId::None;
|
||||
}
|
||||
|
||||
|
||||
+20
-11
@@ -185,8 +185,7 @@ impl C as N where .I1 = C {}
|
||||
|
||||
fn F(generic _: I where .I1 = .Self) {}
|
||||
fn G() {
|
||||
// TODO: This crashes.
|
||||
// F(C);
|
||||
F(C);
|
||||
}
|
||||
|
||||
// --- impl_as_concrete_generic_constraint_where_rewrite.carbon
|
||||
@@ -206,11 +205,10 @@ impl C as N where .I1 = C {}
|
||||
|
||||
fn F(generic _: I(.Self) where .I1 = .Self) {}
|
||||
fn G() {
|
||||
// TODO: This crashes.
|
||||
// F(C);
|
||||
F(C);
|
||||
}
|
||||
|
||||
// --- todo_impl_as_symbolic_generic_constraint_where_rewrite.carbon
|
||||
// --- impl_as_symbolic_generic_constraint_where_rewrite.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
interface I(T: type) {
|
||||
@@ -226,8 +224,7 @@ impl C as N where .I1 = C {}
|
||||
|
||||
fn F(generic _: I(.Self) where .I1 = .Self) {}
|
||||
fn G() {
|
||||
// TODO: This crashes.
|
||||
// F(C);
|
||||
F(C);
|
||||
}
|
||||
|
||||
// --- fail_todo_impl_as_constraint_containing_rewrite_for_concrete_interface.carbon
|
||||
@@ -253,8 +250,14 @@ impl C as N {}
|
||||
|
||||
fn F(generic _: I where .I1 = .Self) {}
|
||||
fn G() {
|
||||
// TODO: This crashes.
|
||||
// F(C);
|
||||
// CHECK:STDERR: fail_todo_impl_as_constraint_containing_rewrite_for_concrete_interface.carbon:[[@LINE+7]]:3: error: cannot convert type `C` into type implementing `I where .(I.I1) = .Self` [ConversionFailureTypeToFacet]
|
||||
// CHECK:STDERR: F(C);
|
||||
// CHECK:STDERR: ^~~~
|
||||
// CHECK:STDERR: fail_todo_impl_as_constraint_containing_rewrite_for_concrete_interface.carbon:[[@LINE-5]]:14: note: initializing generic parameter `_` declared here [InitializingGenericParam]
|
||||
// CHECK:STDERR: fn F(generic _: I where .I1 = .Self) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
F(C);
|
||||
}
|
||||
|
||||
// --- fail_todo_impl_as_constraint_containing_rewrite_for_generic_interface.carbon
|
||||
@@ -280,8 +283,14 @@ impl C as N {}
|
||||
|
||||
fn F(generic _: I(.Self) where .I1 = .Self) {}
|
||||
fn G() {
|
||||
// TODO: This crashes.
|
||||
// F(C);
|
||||
// CHECK:STDERR: fail_todo_impl_as_constraint_containing_rewrite_for_generic_interface.carbon:[[@LINE+7]]:3: error: cannot convert type `C` into type implementing `I(.Self) where .(I(.Self).I1) = .Self` [ConversionFailureTypeToFacet]
|
||||
// CHECK:STDERR: F(C);
|
||||
// CHECK:STDERR: ^~~~
|
||||
// CHECK:STDERR: fail_todo_impl_as_constraint_containing_rewrite_for_generic_interface.carbon:[[@LINE-5]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]
|
||||
// CHECK:STDERR: fn F(generic _: I(.Self) where .I1 = .Self) {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
F(C);
|
||||
}
|
||||
|
||||
// --- fail_no_require_self.carbon
|
||||
|
||||
Reference in New Issue
Block a user