mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-04 22:02:52 +01:00
@@ -156,167 +156,4 @@ auto AddSelfSymbolicBindingToScope(Context& context,
|
||||
return self_param_inst_id;
|
||||
}
|
||||
|
||||
template <typename EntityT>
|
||||
requires std::same_as<EntityT, SemIR::Interface>
|
||||
static constexpr auto DeclTokenKind() -> Lex::TokenKind {
|
||||
return Lex::TokenKind::Interface;
|
||||
}
|
||||
|
||||
template <typename EntityT>
|
||||
requires std::same_as<EntityT, SemIR::NamedConstraint>
|
||||
static constexpr auto DeclTokenKind() -> Lex::TokenKind {
|
||||
return Lex::TokenKind::Constraint;
|
||||
}
|
||||
|
||||
template <typename EntityT>
|
||||
requires SameAsOneOf<EntityT, SemIR::Interface, SemIR::NamedConstraint>
|
||||
auto TryGetExistingDecl(Context& context, const NameComponent& name,
|
||||
SemIR::ScopeLookupResult lookup_result,
|
||||
const EntityT& entity, bool is_definition)
|
||||
-> std::optional<SemIR::Inst> {
|
||||
using EntityIdT =
|
||||
std::conditional_t<std::is_same_v<EntityT, SemIR::Interface>,
|
||||
SemIR::InterfaceId, SemIR::NamedConstraintId>;
|
||||
constexpr bool IsInterface = std::is_same_v<EntityIdT, SemIR::InterfaceId>;
|
||||
|
||||
if (lookup_result.is_poisoned()) {
|
||||
// This is a declaration of a poisoned name.
|
||||
DiagnosePoisonedName(context, name.name_id,
|
||||
lookup_result.poisoning_loc_id(), name.name_loc_id);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (!lookup_result.is_found()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto prev_id = lookup_result.target_inst_id();
|
||||
auto prev = context.insts().Get(prev_id);
|
||||
|
||||
auto prev_entity_id = EntityIdT::None;
|
||||
auto prev_import_ir_id = SemIR::ImportIRId::None;
|
||||
auto existing_decl_id = SemIR::InstId::None;
|
||||
CARBON_KIND_SWITCH(prev) {
|
||||
case CARBON_KIND(SemIR::InterfaceDecl interface_decl): {
|
||||
if constexpr (IsInterface) {
|
||||
prev_entity_id = interface_decl.interface_id;
|
||||
existing_decl_id = prev_id;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CARBON_KIND(SemIR::NamedConstraintDecl named_constraint_decl): {
|
||||
if constexpr (!IsInterface) {
|
||||
prev_entity_id = named_constraint_decl.named_constraint_id;
|
||||
existing_decl_id = prev_id;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CARBON_KIND(SemIR::ImportRefLoaded import_ref): {
|
||||
auto import_ir_inst =
|
||||
context.import_ir_insts().Get(import_ref.import_ir_inst_id);
|
||||
|
||||
// Verify the decl so that things like aliases are name conflicts.
|
||||
const auto* import_ir =
|
||||
context.import_irs().Get(import_ir_inst.ir_id()).sem_ir;
|
||||
if constexpr (IsInterface) {
|
||||
if (!import_ir->insts().Is<SemIR::InterfaceDecl>(
|
||||
import_ir_inst.inst_id())) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (!import_ir->insts().Is<SemIR::NamedConstraintDecl>(
|
||||
import_ir_inst.inst_id())) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Use the constant value to get the ID.
|
||||
auto decl_value = context.insts().Get(
|
||||
context.constant_values().GetConstantInstId(prev_id));
|
||||
if (auto facet_type = decl_value.TryAs<SemIR::FacetType>()) {
|
||||
auto declared_facet_type = context.declared_facet_types().Get(
|
||||
facet_type->declared_facet_type_id);
|
||||
if constexpr (IsInterface) {
|
||||
prev_entity_id =
|
||||
declared_facet_type.extend_constraints[0].interface_id;
|
||||
} else {
|
||||
prev_entity_id = declared_facet_type.extend_named_constraints[0]
|
||||
.named_constraint_id;
|
||||
}
|
||||
prev_import_ir_id = import_ir_inst.ir_id();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!prev_entity_id.has_value()) {
|
||||
// This is a redeclaration with a different entity kind.
|
||||
DiagnoseDuplicateName(context, name.name_id, name.name_loc_id,
|
||||
SemIR::LocId(prev_id));
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto& prev_entity = [&]() -> EntityT& {
|
||||
if constexpr (IsInterface) {
|
||||
return context.interfaces().Get(prev_entity_id);
|
||||
} else {
|
||||
return context.named_constraints().Get(prev_entity_id);
|
||||
}
|
||||
}();
|
||||
|
||||
if (!CheckRedeclParamsMatch(
|
||||
context,
|
||||
DeclParams(SemIR::LocId(entity.latest_decl_id()),
|
||||
name.first_param_node_id, name.last_param_node_id,
|
||||
name.implicit_param_patterns_id, name.param_patterns_id),
|
||||
DeclParams(prev_entity))) {
|
||||
// Mismatch is diagnosed already if found.
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
DiagnoseIfInvalidRedecl(
|
||||
context, DeclTokenKind<EntityT>(), prev_entity.name_id,
|
||||
RedeclInfo(entity, SemIR::LocId(entity.latest_decl_id()), is_definition),
|
||||
RedeclInfo(prev_entity, SemIR::LocId(prev_entity.latest_decl_id()),
|
||||
prev_entity.has_definition_started()),
|
||||
prev_import_ir_id);
|
||||
|
||||
if (is_definition && prev_entity.has_definition_started()) {
|
||||
// DiagnoseIfInvalidRedecl would diagnose an error in this case, since we'd
|
||||
// have two definitions. Given the declaration parts of the definitions
|
||||
// match, we would be able to use the prior declaration for error recovery,
|
||||
// except that having two definitions causes larger problems for generics.
|
||||
// All interfaces (and named constraints) are generic with an implicit Self
|
||||
// compile time binding.
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (is_definition) {
|
||||
prev_entity.MergeDefinition(entity);
|
||||
}
|
||||
|
||||
if (prev_import_ir_id.has_value()) {
|
||||
prev_entity.first_owning_decl_id = entity.first_owning_decl_id;
|
||||
ReplacePrevInstForMerge(context, entity.parent_scope_id,
|
||||
prev_entity.name_id, entity.first_owning_decl_id);
|
||||
}
|
||||
|
||||
// This is a matching redeclaration of an existing entity of the same type.
|
||||
return existing_decl_id.has_value() ? std::optional<SemIR::Inst>(prev)
|
||||
: std::nullopt;
|
||||
}
|
||||
|
||||
template auto TryGetExistingDecl(Context& context, const NameComponent& name,
|
||||
SemIR::ScopeLookupResult lookup_result,
|
||||
const SemIR::Interface& entity,
|
||||
bool is_definition)
|
||||
-> std::optional<SemIR::Inst>;
|
||||
template auto TryGetExistingDecl(Context& context, const NameComponent& name,
|
||||
SemIR::ScopeLookupResult lookup_result,
|
||||
const SemIR::NamedConstraint& entity,
|
||||
bool is_definition)
|
||||
-> std::optional<SemIR::Inst>;
|
||||
|
||||
} // namespace Carbon::Check
|
||||
|
||||
Reference in New Issue
Block a user