Change Context::IsImplFile to File::is_impl (#4931)

Note this mirrors parse_tree().packaging_decl().is_impl, but I'm
preferring to keep the version that doesn't access the parse tree so
that we could change tree storage without hurting as much.
This commit is contained in:
Jon Ross-Perkins
2025-02-12 19:42:07 +00:00
committed by GitHub
parent 71c91eaf14
commit 8af64ceca6
9 changed files with 35 additions and 32 deletions
+1 -1
View File
@@ -52,7 +52,7 @@ Context::Context(DiagnosticEmitter* emitter,
param_and_arg_refs_stack_(*sem_ir, vlog_stream, node_stack_),
args_type_info_stack_("args_type_info_stack_", *sem_ir, vlog_stream),
decl_name_stack_(this),
scope_stack_(sem_ir_->identifiers()),
scope_stack_(sem_ir_),
vtable_stack_("vtable_stack_", *sem_ir, vlog_stream),
global_init_(this),
region_stack_(
-13
View File
@@ -287,13 +287,6 @@ class Context {
auto NoteUndefinedInterface(SemIR::InterfaceId interface_id,
DiagnosticBuilder& builder) -> void;
// Returns the current scope, if it is of the specified kind. Otherwise,
// returns nullopt.
template <typename InstT>
auto GetCurrentScopeAs() -> std::optional<InstT> {
return scope_stack().GetCurrentScopeAs<InstT>(sem_ir());
}
// Returns the type ID for a constant that is a type value, i.e. it is a value
// of type `TypeType`.
//
@@ -390,12 +383,6 @@ class Context {
auto Finalize() -> void;
// True if the current file is an impl file.
auto IsImplFile() -> bool {
return sem_ir_->import_irs().Get(SemIR::ImportIRId::ApiForImpl).sem_ir !=
nullptr;
}
// Prints information for a stack dump.
auto PrintForStackDump(llvm::raw_ostream& output) const -> void;
+3 -2
View File
@@ -111,7 +111,8 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
// A `var` binding in a class scope declares a field, not a true binding,
// so we handle it separately.
if (auto parent_class_decl = context.GetCurrentScopeAs<SemIR::ClassDecl>();
if (auto parent_class_decl =
context.scope_stack().GetCurrentScopeAs<SemIR::ClassDecl>();
parent_class_decl.has_value() &&
node_kind == Parse::NodeKind::VarBindingPattern) {
cast_type_id = AsConcreteType(
@@ -152,7 +153,7 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
// A binding in an interface scope declares an associated constant, not a
// true binding, so we handle it separately.
if (auto parent_interface_decl =
context.GetCurrentScopeAs<SemIR::InterfaceDecl>();
context.scope_stack().GetCurrentScopeAs<SemIR::InterfaceDecl>();
parent_interface_decl.has_value() && is_generic) {
cast_type_id = AsCompleteType(context, cast_type_id, type_node, [&] {
CARBON_DIAGNOSTIC(IncompleteTypeInAssociatedDecl, Error,
+4 -2
View File
@@ -10,6 +10,7 @@
#include "toolchain/check/eval.h"
#include "toolchain/check/generic.h"
#include "toolchain/check/handle.h"
#include "toolchain/check/import.h"
#include "toolchain/check/import_ref.h"
#include "toolchain/check/merge.h"
#include "toolchain/check/modifiers.h"
@@ -265,7 +266,7 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id,
.specific_id = specific_id}));
}
if (!is_definition && context.IsImplFile() && !is_extern) {
if (!is_definition && context.sem_ir().is_impl() && !is_extern) {
context.definitions_required().push_back(class_decl_id);
}
@@ -333,7 +334,8 @@ static auto DiagnoseClassSpecificDeclOutsideClass(Context& context,
static auto GetCurrentScopeAsClassOrDiagnose(Context& context, SemIRLoc loc,
Lex::TokenKind tok)
-> std::optional<SemIR::ClassDecl> {
auto class_scope = context.GetCurrentScopeAs<SemIR::ClassDecl>();
auto class_scope =
context.scope_stack().GetCurrentScopeAs<SemIR::ClassDecl>();
if (!class_scope) {
DiagnoseClassSpecificDeclOutsideClass(context, loc, tok);
}
+3 -2
View File
@@ -11,6 +11,7 @@
#include "toolchain/check/function.h"
#include "toolchain/check/generic.h"
#include "toolchain/check/handle.h"
#include "toolchain/check/import.h"
#include "toolchain/check/import_ref.h"
#include "toolchain/check/interface.h"
#include "toolchain/check/literal.h"
@@ -280,7 +281,7 @@ static auto BuildFunctionDecl(Context& context,
// Create a new function if this isn't a valid redeclaration.
if (!function_decl.function_id.has_value()) {
if (function_info.is_extern && context.IsImplFile()) {
if (function_info.is_extern && context.sem_ir().is_impl()) {
DiagnoseExternRequiresDeclInApiFile(context, node_id);
}
function_info.generic_id = BuildGenericDecl(context, decl_id);
@@ -343,7 +344,7 @@ static auto BuildFunctionDecl(Context& context,
}
}
if (!is_definition && context.IsImplFile() && !is_extern) {
if (!is_definition && context.sem_ir().is_impl() && !is_extern) {
context.definitions_required().push_back(decl_id);
}
+8 -7
View File
@@ -88,7 +88,7 @@ static auto HandleIntroducer(Context& context, Parse::NodeId node_id) -> bool {
}
auto HandleParseNode(Context& context, Parse::LetIntroducerId node_id) -> bool {
if (context.GetCurrentScopeAs<SemIR::InterfaceDecl>()) {
if (context.scope_stack().GetCurrentScopeAs<SemIR::InterfaceDecl>()) {
StartAssociatedConstant(context);
}
@@ -154,7 +154,7 @@ auto HandleParseNode(Context& context, Parse::VariablePatternId node_id)
// Handle the end of the full-pattern of a let/var declaration (before the
// start of the initializer, if any).
static auto EndFullPattern(Context& context) -> void {
if (context.GetCurrentScopeAs<SemIR::InterfaceDecl>()) {
if (context.scope_stack().GetCurrentScopeAs<SemIR::InterfaceDecl>()) {
// Don't emit NameBindingDecl for an associated constant, because it will
// always be empty.
context.pattern_block_stack().PopAndDiscard();
@@ -190,7 +190,8 @@ static auto HandleInitializer(Context& context, Parse::NodeId node_id) -> bool {
auto HandleParseNode(Context& context, Parse::LetInitializerId node_id)
-> bool {
if (auto interface_decl = context.GetCurrentScopeAs<SemIR::InterfaceDecl>()) {
if (auto interface_decl =
context.scope_stack().GetCurrentScopeAs<SemIR::InterfaceDecl>()) {
EndAssociatedConstantDeclRegion(context, interface_decl->interface_id);
// Start building the definition region of the constant.
@@ -239,7 +240,7 @@ static auto HandleDecl(Context& context) -> DeclInfo {
// now. We will have done this at the `=` if there was an initializer.
if (IntroducerTokenKind == Lex::TokenKind::Let) {
if (auto interface_decl =
context.GetCurrentScopeAs<SemIR::InterfaceDecl>()) {
context.scope_stack().GetCurrentScopeAs<SemIR::InterfaceDecl>()) {
EndAssociatedConstantDeclRegion(context, interface_decl->interface_id);
}
}
@@ -347,7 +348,7 @@ auto HandleParseNode(Context& context, Parse::LetDeclId node_id) -> bool {
// At interface scope, we are forming an associated constant, which has
// different rules.
if (auto interface_scope =
context.GetCurrentScopeAs<SemIR::InterfaceDecl>()) {
context.scope_stack().GetCurrentScopeAs<SemIR::InterfaceDecl>()) {
FinishAssociatedConstant(context, node_id, interface_scope->interface_id,
decl_info);
return true;
@@ -379,7 +380,7 @@ auto HandleParseNode(Context& context, Parse::VariableDeclId node_id) -> bool {
context, decl_info.introducer,
KeywordModifierSet::Access | KeywordModifierSet::Returned);
if (context.GetCurrentScopeAs<SemIR::ClassDecl>()) {
if (context.scope_stack().GetCurrentScopeAs<SemIR::ClassDecl>()) {
if (decl_info.init_id.has_value()) {
// TODO: In a class scope, we should instead save the initializer
// somewhere so that we can use it as a default.
@@ -387,7 +388,7 @@ auto HandleParseNode(Context& context, Parse::VariableDeclId node_id) -> bool {
}
return true;
}
if (context.GetCurrentScopeAs<SemIR::InterfaceDecl>()) {
if (context.scope_stack().GetCurrentScopeAs<SemIR::InterfaceDecl>()) {
CARBON_DIAGNOSTIC(VarInInterfaceDecl, Error,
"`var` declaration in interface");
context.emitter().Emit(node_id, VarInInterfaceDecl);
+2 -1
View File
@@ -5,6 +5,7 @@
#include "toolchain/check/merge.h"
#include "toolchain/base/kind_switch.h"
#include "toolchain/check/import.h"
#include "toolchain/check/import_ref.h"
#include "toolchain/diagnostics/format_providers.h"
#include "toolchain/sem_ir/ids.h"
@@ -135,7 +136,7 @@ auto DiagnoseIfInvalidRedecl(Context& context, Lex::TokenKind decl_kind,
}
// Check for disallowed redeclarations cross-library.
if (new_decl.is_extern && context.IsImplFile()) {
if (new_decl.is_extern && context.sem_ir().is_impl()) {
// We continue after issuing the "missing API declaration" diagnostic,
// because it may still be helpful to note other issues with the
// declarations.
+9 -4
View File
@@ -20,8 +20,10 @@ namespace Carbon::Check {
// checking within.
class ScopeStack {
public:
explicit ScopeStack(const CanonicalValueStore<IdentifierId>& identifiers)
: lexical_lookup_(identifiers), full_pattern_stack_(&lexical_lookup_) {}
explicit ScopeStack(const SemIR::File* sem_ir)
: sem_ir_(sem_ir),
lexical_lookup_(sem_ir->identifiers()),
full_pattern_stack_(&lexical_lookup_) {}
// A scope in which `break` and `continue` can be used.
struct BreakContinueScope {
@@ -99,12 +101,12 @@ class ScopeStack {
// Returns the current scope, if it is of the specified kind. Otherwise,
// returns nullopt.
template <typename InstT>
auto GetCurrentScopeAs(const SemIR::File& sem_ir) -> std::optional<InstT> {
auto GetCurrentScopeAs() -> std::optional<InstT> {
auto inst_id = PeekInstId();
if (!inst_id.has_value()) {
return std::nullopt;
}
return sem_ir.insts().TryGetAs<InstT>(inst_id);
return sem_ir_->insts().TryGetAs<InstT>(inst_id);
}
// If there is no `returned var` in scope, sets the given instruction to be
@@ -225,6 +227,9 @@ class ScopeStack {
auto VerifyNextCompileTimeBindIndex(llvm::StringLiteral label,
const ScopeStackEntry& scope) -> void;
// The current file.
const SemIR::File* sem_ir_;
// A stack of scopes from which we can `return`.
llvm::SmallVector<ReturnScope> return_scope_stack_;
+5
View File
@@ -94,6 +94,11 @@ class File : public Printable<File> {
return types().GetAs<PointerType>(pointer_id).pointee_id;
}
// Returns true if this file is an `impl`.
auto is_impl() -> bool {
return import_irs().Get(SemIR::ImportIRId::ApiForImpl).sem_ir != nullptr;
}
auto check_ir_id() const -> CheckIRId { return check_ir_id_; }
auto package_id() const -> PackageNameId { return package_id_; }
auto library_id() const -> SemIR::LibraryNameId { return library_id_; }