Skip to content

Commit

Permalink
Move impl lookup out into its own file. (#4435)
Browse files Browse the repository at this point in the history
In preparation for adding more logic here. This code doesn't belong in
member access.
  • Loading branch information
zygoloid authored Oct 22, 2024
1 parent 17bf9f1 commit af816cd
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 53 deletions.
2 changes: 2 additions & 0 deletions toolchain/check/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand Down
60 changes: 60 additions & 0 deletions toolchain/check/impl_lookup.cpp
Original file line number Diff line number Diff line change
@@ -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
23 changes: 23 additions & 0 deletions toolchain/check/impl_lookup.h
Original file line number Diff line number Diff line change
@@ -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_
54 changes: 1 addition & 53 deletions toolchain/check/member_access.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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(
Expand Down

0 comments on commit af816cd

Please sign in to comment.