From 145c4b7ec65bfd0ad44655983b0fed68e0a207a5 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 22 Oct 2024 00:33:23 +0000 Subject: [PATCH] Move impl lookup out into its own file. In preparation for adding more logic here. This code doesn't belong in member access. --- toolchain/check/BUILD | 2 ++ toolchain/check/impl_lookup.cpp | 60 +++++++++++++++++++++++++++++++ toolchain/check/impl_lookup.h | 23 ++++++++++++ toolchain/check/member_access.cpp | 54 +--------------------------- 4 files changed, 86 insertions(+), 53 deletions(-) create mode 100644 toolchain/check/impl_lookup.cpp create mode 100644 toolchain/check/impl_lookup.h diff --git a/toolchain/check/BUILD b/toolchain/check/BUILD index cae21cdec0c3..7d217b2a8e27 100644 --- a/toolchain/check/BUILD +++ b/toolchain/check/BUILD @@ -24,6 +24,7 @@ cc_library( "function.cpp", "generic.cpp", "global_init.cpp", + "impl_lookup.cpp", "import.cpp", "import_ref.cpp", "inst_block_stack.cpp", @@ -48,6 +49,7 @@ cc_library( "function.h", "generic.h", "global_init.h", + "impl_lookup.h", "import.h", "import_ref.h", "inst_block_stack.h", diff --git a/toolchain/check/impl_lookup.cpp b/toolchain/check/impl_lookup.cpp new file mode 100644 index 000000000000..d7295d9d5549 --- /dev/null +++ b/toolchain/check/impl_lookup.cpp @@ -0,0 +1,60 @@ +// 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 + +#include "toolchain/check/impl_lookup.h" + +#include "toolchain/check/deduce.h" +#include "toolchain/check/generic.h" +#include "toolchain/check/import_ref.h" + +namespace Carbon::Check { + +auto LookupInterfaceWitness(Context& context, SemIR::LocId loc_id, + SemIR::ConstantId type_const_id, + SemIR::ConstantId interface_const_id) + -> SemIR::InstId { + // TODO: Add a better impl lookup system. At the very least, we should only be + // considering impls that are for the same interface we're querying. We can + // also skip impls that mention any types that aren't part of our impl query. + for (const auto& impl : context.impls().array_ref()) { + auto specific_id = SemIR::SpecificId::Invalid; + if (impl.generic_id.is_valid()) { + specific_id = DeduceImplArguments(context, loc_id, impl, type_const_id, + interface_const_id); + if (!specific_id.is_valid()) { + continue; + } + } + if (!context.constant_values().AreEqualAcrossDeclarations( + SemIR::GetConstantValueInSpecific(context.sem_ir(), specific_id, + impl.self_id), + type_const_id)) { + continue; + } + if (!context.constant_values().AreEqualAcrossDeclarations( + SemIR::GetConstantValueInSpecific(context.sem_ir(), specific_id, + impl.constraint_id), + interface_const_id)) { + // TODO: An impl of a constraint type should be treated as implementing + // the constraint's interfaces. + continue; + } + if (!impl.witness_id.is_valid()) { + // TODO: Diagnose if the impl isn't defined yet? + return SemIR::InstId::Invalid; + } + LoadImportRef(context, impl.witness_id); + if (specific_id.is_valid()) { + // We need a definition of the specific `impl` so we can access its + // witness. + ResolveSpecificDefinition(context, specific_id); + } + return context.constant_values().GetInstId( + SemIR::GetConstantValueInSpecific(context.sem_ir(), specific_id, + impl.witness_id)); + } + return SemIR::InstId::Invalid; +} + +} // namespace Carbon::Check diff --git a/toolchain/check/impl_lookup.h b/toolchain/check/impl_lookup.h new file mode 100644 index 000000000000..e027f99cdf70 --- /dev/null +++ b/toolchain/check/impl_lookup.h @@ -0,0 +1,23 @@ +// 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_IMPL_LOOKUP_H_ +#define CARBON_TOOLCHAIN_CHECK_IMPL_LOOKUP_H_ + +#include "toolchain/check/context.h" +#include "toolchain/sem_ir/ids.h" + +namespace Carbon::Check { + +// Looks up the witness to use for a particular type and interface. Returns the +// witness, or `InstId::Invalid` if the type is not known to implement the +// interface. +auto LookupInterfaceWitness(Context& context, SemIR::LocId loc_id, + SemIR::ConstantId type_const_id, + SemIR::ConstantId interface_const_id) + -> SemIR::InstId; + +} // namespace Carbon::Check + +#endif // CARBON_TOOLCHAIN_CHECK_IMPL_LOOKUP_H_ diff --git a/toolchain/check/member_access.cpp b/toolchain/check/member_access.cpp index 898e95f8f696..7d9e080a2cf2 100644 --- a/toolchain/check/member_access.cpp +++ b/toolchain/check/member_access.cpp @@ -10,9 +10,7 @@ #include "toolchain/base/kind_switch.h" #include "toolchain/check/context.h" #include "toolchain/check/convert.h" -#include "toolchain/check/deduce.h" -#include "toolchain/check/generic.h" -#include "toolchain/check/import_ref.h" +#include "toolchain/check/impl_lookup.h" #include "toolchain/diagnostics/diagnostic_emitter.h" #include "toolchain/sem_ir/generic.h" #include "toolchain/sem_ir/ids.h" @@ -171,56 +169,6 @@ static auto ScopeNeedsImplLookup(Context& context, LookupScope scope) -> bool { return true; } -// Given a type and an interface, searches for an impl that describes how that -// type implements that interface, and returns the corresponding witness. -// Returns an invalid InstId if no matching impl is found. -static auto LookupInterfaceWitness(Context& context, SemIR::LocId loc_id, - SemIR::ConstantId type_const_id, - SemIR::ConstantId interface_const_id) - -> SemIR::InstId { - // TODO: Add a better impl lookup system. At the very least, we should only be - // considering impls that are for the same interface we're querying. We can - // also skip impls that mention any types that aren't part of our impl query. - for (const auto& impl : context.impls().array_ref()) { - auto specific_id = SemIR::SpecificId::Invalid; - if (impl.generic_id.is_valid()) { - specific_id = DeduceImplArguments(context, loc_id, impl, type_const_id, - interface_const_id); - if (!specific_id.is_valid()) { - continue; - } - } - if (!context.constant_values().AreEqualAcrossDeclarations( - SemIR::GetConstantValueInSpecific(context.sem_ir(), specific_id, - impl.self_id), - type_const_id)) { - continue; - } - if (!context.constant_values().AreEqualAcrossDeclarations( - SemIR::GetConstantValueInSpecific(context.sem_ir(), specific_id, - impl.constraint_id), - interface_const_id)) { - // TODO: An impl of a constraint type should be treated as implementing - // the constraint's interfaces. - continue; - } - if (!impl.witness_id.is_valid()) { - // TODO: Diagnose if the impl isn't defined yet? - return SemIR::InstId::Invalid; - } - LoadImportRef(context, impl.witness_id); - if (specific_id.is_valid()) { - // We need a definition of the specific `impl` so we can access its - // witness. - ResolveSpecificDefinition(context, specific_id); - } - return context.constant_values().GetInstId( - SemIR::GetConstantValueInSpecific(context.sem_ir(), specific_id, - impl.witness_id)); - } - return SemIR::InstId::Invalid; -} - // Performs impl lookup for a member name expression. This finds the relevant // impl witness and extracts the corresponding impl member. static auto PerformImplLookup(