From 47a1e99b9e0dfe677a6e517a53bf2df804955e73 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Mon, 30 Jan 2023 16:12:04 -0800 Subject: [PATCH] Factor `ValueNodeView` out of `StaticScope`. (#2562) Also remove unused support in `StaticScope` for a scope to have multiple parents. No functionality change intended. --- explorer/ast/BUILD | 5 +- explorer/ast/README.md | 4 +- explorer/ast/declaration.h | 6 +- explorer/ast/expression.h | 2 +- explorer/ast/pattern.h | 2 +- explorer/ast/statement.h | 2 +- explorer/ast/static_scope.cpp | 54 ++++----- explorer/ast/static_scope.h | 148 ++---------------------- explorer/ast/value_node.h | 143 +++++++++++++++++++++++ explorer/interpreter/element_path.h | 2 +- explorer/interpreter/resolve_names.cpp | 39 +++---- explorer/interpreter/resolve_unformed.h | 3 + explorer/interpreter/type_checker.h | 5 + 13 files changed, 205 insertions(+), 210 deletions(-) create mode 100644 explorer/ast/value_node.h diff --git a/explorer/ast/BUILD b/explorer/ast/BUILD index 3b6687c252a5..97d23e5e598c 100644 --- a/explorer/ast/BUILD +++ b/explorer/ast/BUILD @@ -54,12 +54,12 @@ cc_library( "pattern.h", "return_term.h", "statement.h", + "value_node.h", ], deps = [ ":ast_node", ":library_name", ":paren_contents", - ":static_scope", ":value_category", "//common:check", "//common:error", @@ -160,8 +160,7 @@ cc_library( srcs = ["static_scope.cpp"], hdrs = ["static_scope.h"], deps = [ - ":ast_node", - ":value_category", + ":ast", "//common:check", "//common:error", "//explorer/common:error_builders", diff --git a/explorer/ast/README.md b/explorer/ast/README.md index 07d494f3c187..dd65ac01c55a 100644 --- a/explorer/ast/README.md +++ b/explorer/ast/README.md @@ -40,5 +40,5 @@ inheritance, we handle these cases using a form of type erasure: we specify a notional interface that those types conform to, and then define a "view" class that behaves like a pointer to an instance of that interface. Types declare that they model an interface `Foo` by defining a public static member named -`ImplementsCarbonFoo`. See [ValueNodeView](static_scope.h) for an example of -this pattern. +`ImplementsCarbonFoo`. See [ValueNodeView](value_node.h) for an example of this +pattern. diff --git a/explorer/ast/declaration.h b/explorer/ast/declaration.h index 3725f58b0df7..b966702dd291 100644 --- a/explorer/ast/declaration.h +++ b/explorer/ast/declaration.h @@ -17,8 +17,8 @@ #include "explorer/ast/pattern.h" #include "explorer/ast/return_term.h" #include "explorer/ast/statement.h" -#include "explorer/ast/static_scope.h" #include "explorer/ast/value_category.h" +#include "explorer/ast/value_node.h" #include "explorer/common/nonnull.h" #include "explorer/common/source_location.h" #include "llvm/ADT/ArrayRef.h" @@ -82,12 +82,12 @@ class Declaration : public AstNode { constant_value_ = value; } - // See static_scope.h for API. + // See value_node.h for API. auto constant_value() const -> std::optional> { return constant_value_; } - // See static_scope.h for API. + // See value_node.h for API. auto symbolic_identity() const -> std::optional> { return constant_value_; } diff --git a/explorer/ast/expression.h b/explorer/ast/expression.h index e6c0ea0090b2..df74dd4b2f07 100644 --- a/explorer/ast/expression.h +++ b/explorer/ast/expression.h @@ -17,8 +17,8 @@ #include "explorer/ast/bindings.h" #include "explorer/ast/element.h" #include "explorer/ast/paren_contents.h" -#include "explorer/ast/static_scope.h" #include "explorer/ast/value_category.h" +#include "explorer/ast/value_node.h" #include "explorer/common/arena.h" #include "explorer/common/source_location.h" #include "llvm/ADT/ArrayRef.h" diff --git a/explorer/ast/pattern.h b/explorer/ast/pattern.h index 5f5cff4c3c35..64b0eee934d2 100644 --- a/explorer/ast/pattern.h +++ b/explorer/ast/pattern.h @@ -13,8 +13,8 @@ #include "explorer/ast/ast_node.h" #include "explorer/ast/ast_rtti.h" #include "explorer/ast/expression.h" -#include "explorer/ast/static_scope.h" #include "explorer/ast/value_category.h" +#include "explorer/ast/value_node.h" #include "explorer/common/source_location.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLFunctionalExtras.h" diff --git a/explorer/ast/statement.h b/explorer/ast/statement.h index 8a7311c593e5..eb29efc1bd3f 100644 --- a/explorer/ast/statement.h +++ b/explorer/ast/statement.h @@ -13,8 +13,8 @@ #include "explorer/ast/expression.h" #include "explorer/ast/pattern.h" #include "explorer/ast/return_term.h" -#include "explorer/ast/static_scope.h" #include "explorer/ast/value_category.h" +#include "explorer/ast/value_node.h" #include "explorer/common/arena.h" #include "explorer/common/source_location.h" #include "llvm/ADT/ArrayRef.h" diff --git a/explorer/ast/static_scope.cpp b/explorer/ast/static_scope.cpp index ada3da76cdbf..02c99896acb6 100644 --- a/explorer/ast/static_scope.cpp +++ b/explorer/ast/static_scope.cpp @@ -55,34 +55,24 @@ auto StaticScope::Resolve(const std::string& name, auto StaticScope::TryResolve(const std::string& name, SourceLocation source_loc) const -> ErrorOr> { - auto it = declared_names_.find(name); - if (it != declared_names_.end()) { - switch (it->second.status) { - case NameStatus::KnownButNotDeclared: - return ProgramError(source_loc) - << "'" << name << "' has not been declared yet"; - case NameStatus::DeclaredButNotUsable: - return ProgramError(source_loc) - << "'" << name - << "' is not usable until after it has been completely declared"; - case NameStatus::Usable: - return std::make_optional(it->second.entity); + for (const StaticScope* scope = this; scope; + scope = scope->parent_scope_.value_or(nullptr)) { + auto it = scope->declared_names_.find(name); + if (it != scope->declared_names_.end()) { + switch (it->second.status) { + case NameStatus::KnownButNotDeclared: + return ProgramError(source_loc) + << "'" << name << "' has not been declared yet"; + case NameStatus::DeclaredButNotUsable: + return ProgramError(source_loc) << "'" << name + << "' is not usable until after it " + "has been completely declared"; + case NameStatus::Usable: + return std::make_optional(it->second.entity); + } } } - std::optional result; - for (Nonnull parent : parent_scopes_) { - CARBON_ASSIGN_OR_RETURN(std::optional parent_result, - parent->TryResolve(name, source_loc)); - if (parent_result.has_value() && result.has_value() && - *parent_result != *result) { - return ProgramError(source_loc) - << "'" << name << "' is ambiguous between " - << result->base().source_loc() << " and " - << parent_result->base().source_loc(); - } - result = parent_result; - } - return result; + return {std::nullopt}; } auto StaticScope::AddReturnedVar(ValueNodeView returned_var_def_view) @@ -98,14 +88,10 @@ auto StaticScope::AddReturnedVar(ValueNodeView returned_var_def_view) } auto StaticScope::ResolveReturned() const -> std::optional { - if (returned_var_def_view_.has_value()) { - return returned_var_def_view_; - } - for (Nonnull parent : parent_scopes_) { - std::optional parent_returned_var = - parent->ResolveReturned(); - if (parent_returned_var.has_value()) { - return parent_returned_var; + for (const StaticScope* scope = this; scope; + scope = scope->parent_scope_.value_or(nullptr)) { + if (scope->returned_var_def_view_.has_value()) { + return scope->returned_var_def_view_; } } return std::nullopt; diff --git a/explorer/ast/static_scope.h b/explorer/ast/static_scope.h index 9991452c7f72..9f956931cdfe 100644 --- a/explorer/ast/static_scope.h +++ b/explorer/ast/static_scope.h @@ -5,145 +5,16 @@ #ifndef CARBON_EXPLORER_AST_STATIC_SCOPE_H_ #define CARBON_EXPLORER_AST_STATIC_SCOPE_H_ -#include #include #include -#include -#include -#include "common/check.h" #include "common/error.h" -#include "explorer/ast/ast_node.h" -#include "explorer/ast/value_category.h" +#include "explorer/ast/value_node.h" #include "explorer/common/nonnull.h" #include "explorer/common/source_location.h" -#include "llvm/Support/Error.h" namespace Carbon { -class Value; - -// The placeholder name exposed by anonymous ValueNodes. -static constexpr std::string_view AnonymousName = "_"; - -// ImplementsValueNode is true if NodeType::ImplementsCarbonValueNode -// is valid and names a type, indicating that NodeType implements the -// ValueNode interface, defined below. - -template -static constexpr bool ImplementsValueNode = false; - -// ValueNode is an interface implemented by AstNodes that can be associated -// with a value, such as declarations and bindings. The interface consists of -// the following methods: -// -// // Returns the constant associated with the node. -// // This is called by the interpreter, not the type checker. -// auto constant_value() const -> std::optional>; -// -// // Returns the symbolic compile-time identity of the node. -// // This is called by the type checker, not the interpreter. -// auto symbolic_identity() const -> std::optional>; -// -// // Returns the static type of an IdentifierExpression that names *this. -// auto static_type() const -> const Value&; -// -// // Returns the value category of an IdentifierExpression that names *this. -// auto value_category() const -> ValueCategory; -// -// // Print the node's identity (e.g. its name). -// void PrintID(llvm::raw_ostream& out) const; -// -// TODO: consider turning the above documentation into real code, as sketched -// at https://godbolt.org/z/186oEozhc - -template -static constexpr bool - ImplementsValueNode = true; - -class ValueNodeView { - public: - template >> - // NOLINTNEXTLINE(google-explicit-constructor) - ValueNodeView(Nonnull node) - // Type-erase NodeType, retaining a pointer to the base class AstNode - // and using std::function to encapsulate the ability to call - // the derived class's methods. - : base_(node), - constant_value_( - [](const AstNode& base) -> std::optional> { - return llvm::cast(base).constant_value(); - }), - symbolic_identity_( - [](const AstNode& base) -> std::optional> { - return llvm::cast(base).symbolic_identity(); - }), - print_([](const AstNode& base, llvm::raw_ostream& out) -> void { - // TODO: change this to print a summary of the node - return llvm::cast(base).PrintID(out); - }), - static_type_([](const AstNode& base) -> const Value& { - return llvm::cast(base).static_type(); - }), - value_category_([](const AstNode& base) -> ValueCategory { - return llvm::cast(base).value_category(); - }) {} - - ValueNodeView(const ValueNodeView&) = default; - ValueNodeView(ValueNodeView&&) = default; - auto operator=(const ValueNodeView&) -> ValueNodeView& = default; - auto operator=(ValueNodeView&&) -> ValueNodeView& = default; - - // Returns `node` as an instance of the base class AstNode. - auto base() const -> const AstNode& { return *base_; } - - // Returns node->constant_value() - auto constant_value() const -> std::optional> { - return constant_value_(*base_); - } - - // Returns node->symbolic_identity() - auto symbolic_identity() const -> std::optional> { - return symbolic_identity_(*base_); - } - - void Print(llvm::raw_ostream& out) const { print_(*base_, out); } - - // Returns node->static_type() - auto static_type() const -> const Value& { return static_type_(*base_); } - - // Returns node->value_category() - auto value_category() const -> ValueCategory { - return value_category_(*base_); - } - - friend auto operator==(const ValueNodeView& lhs, const ValueNodeView& rhs) - -> bool { - return lhs.base_ == rhs.base_; - } - - friend auto operator!=(const ValueNodeView& lhs, const ValueNodeView& rhs) - -> bool { - return lhs.base_ != rhs.base_; - } - - friend auto operator<(const ValueNodeView& lhs, const ValueNodeView& rhs) - -> bool { - return std::less<>()(lhs.base_, rhs.base_); - } - - private: - Nonnull base_; - std::function>(const AstNode&)> - constant_value_; - std::function>(const AstNode&)> - symbolic_identity_; - std::function print_; - std::function static_type_; - std::function value_category_; -}; - // Maps the names visible in a given scope to the entities they name. // A scope may have parent scopes, whose names will also be visible in the // child scope. @@ -162,6 +33,13 @@ class StaticScope { Usable, }; + // Construct a root scope. + StaticScope() {} + + // Construct a scope that is nested within the given scope. + explicit StaticScope(Nonnull parent) + : parent_scope_(parent) {} + // Defines `name` to be `entity` in this scope, or reports a compilation error // if `name` is already defined to be a different entity in this scope. // If `usable` is `false`, `name` cannot yet be referenced and `Resolve()` @@ -174,12 +52,6 @@ class StaticScope { // Marks `name` as being completely declared and hence usable. void MarkUsable(const std::string& name); - // Make `parent` a parent of this scope. - // REQUIRES: `parent` is not already a parent of this scope. - void AddParent(Nonnull parent) { - parent_scopes_.push_back(parent); - } - // Returns the nearest definition of `name` in the ancestor graph of this // scope, or reports a compilation error at `source_loc` there isn't exactly // one such definition. @@ -209,8 +81,8 @@ class StaticScope { // Maps locally declared names to their entities. std::unordered_map declared_names_; - // A list of scopes used for name lookup within this scope. - std::vector> parent_scopes_; + // The parent scope of this scope, if it not the root scope. + std::optional> parent_scope_; // Stores the value node of the BindingPattern of the returned var definition. std::optional returned_var_def_view_; diff --git a/explorer/ast/value_node.h b/explorer/ast/value_node.h new file mode 100644 index 000000000000..dd7ad58057a5 --- /dev/null +++ b/explorer/ast/value_node.h @@ -0,0 +1,143 @@ +// 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_EXPLORER_AST_VALUE_NODE_H_ +#define CARBON_EXPLORER_AST_VALUE_NODE_H_ + +#include +#include +#include + +#include "explorer/ast/ast_node.h" +#include "explorer/ast/value_category.h" +#include "explorer/common/nonnull.h" + +namespace Carbon { + +class Value; + +// The placeholder name exposed by anonymous ValueNodes. +static constexpr std::string_view AnonymousName = "_"; + +// ImplementsValueNode is true if NodeType::ImplementsCarbonValueNode +// is valid and names a type, indicating that NodeType implements the +// ValueNode interface, defined below. + +template +static constexpr bool ImplementsValueNode = false; + +// ValueNode is an interface implemented by AstNodes that can be associated +// with a value, such as declarations and bindings. The interface consists of +// the following methods: +// +// // Returns the constant associated with the node. +// // This is called by the interpreter, not the type checker. +// auto constant_value() const -> std::optional>; +// +// // Returns the symbolic compile-time identity of the node. +// // This is called by the type checker, not the interpreter. +// auto symbolic_identity() const -> std::optional>; +// +// // Returns the static type of an IdentifierExpression that names *this. +// auto static_type() const -> const Value&; +// +// // Returns the value category of an IdentifierExpression that names *this. +// auto value_category() const -> ValueCategory; +// +// // Print the node's identity (e.g. its name). +// void PrintID(llvm::raw_ostream& out) const; +// +// TODO: consider turning the above documentation into real code, as sketched +// at https://godbolt.org/z/186oEozhc + +template +static constexpr bool + ImplementsValueNode = true; + +class ValueNodeView { + public: + template >> + // NOLINTNEXTLINE(google-explicit-constructor) + ValueNodeView(Nonnull node) + // Type-erase NodeType, retaining a pointer to the base class AstNode + // and using std::function to encapsulate the ability to call + // the derived class's methods. + : base_(node), + constant_value_( + [](const AstNode& base) -> std::optional> { + return llvm::cast(base).constant_value(); + }), + symbolic_identity_( + [](const AstNode& base) -> std::optional> { + return llvm::cast(base).symbolic_identity(); + }), + print_([](const AstNode& base, llvm::raw_ostream& out) -> void { + // TODO: change this to print a summary of the node + return llvm::cast(base).PrintID(out); + }), + static_type_([](const AstNode& base) -> const Value& { + return llvm::cast(base).static_type(); + }), + value_category_([](const AstNode& base) -> ValueCategory { + return llvm::cast(base).value_category(); + }) {} + + ValueNodeView(const ValueNodeView&) = default; + ValueNodeView(ValueNodeView&&) = default; + auto operator=(const ValueNodeView&) -> ValueNodeView& = default; + auto operator=(ValueNodeView&&) -> ValueNodeView& = default; + + // Returns `node` as an instance of the base class AstNode. + auto base() const -> const AstNode& { return *base_; } + + // Returns node->constant_value() + auto constant_value() const -> std::optional> { + return constant_value_(*base_); + } + + // Returns node->symbolic_identity() + auto symbolic_identity() const -> std::optional> { + return symbolic_identity_(*base_); + } + + void Print(llvm::raw_ostream& out) const { print_(*base_, out); } + + // Returns node->static_type() + auto static_type() const -> const Value& { return static_type_(*base_); } + + // Returns node->value_category() + auto value_category() const -> ValueCategory { + return value_category_(*base_); + } + + friend auto operator==(const ValueNodeView& lhs, const ValueNodeView& rhs) + -> bool { + return lhs.base_ == rhs.base_; + } + + friend auto operator!=(const ValueNodeView& lhs, const ValueNodeView& rhs) + -> bool { + return lhs.base_ != rhs.base_; + } + + friend auto operator<(const ValueNodeView& lhs, const ValueNodeView& rhs) + -> bool { + return std::less<>()(lhs.base_, rhs.base_); + } + + private: + Nonnull base_; + std::function>(const AstNode&)> + constant_value_; + std::function>(const AstNode&)> + symbolic_identity_; + std::function print_; + std::function static_type_; + std::function value_category_; +}; + +} // namespace Carbon + +#endif // CARBON_EXPLORER_AST_VALUE_NODE_H_ diff --git a/explorer/interpreter/element_path.h b/explorer/interpreter/element_path.h index 4f823b7693f1..26f58213b8db 100644 --- a/explorer/interpreter/element_path.h +++ b/explorer/interpreter/element_path.h @@ -12,7 +12,7 @@ #include "common/ostream.h" #include "explorer/ast/element.h" -#include "explorer/ast/static_scope.h" +#include "explorer/ast/value_node.h" #include "llvm/Support/Compiler.h" namespace Carbon { diff --git a/explorer/interpreter/resolve_names.cpp b/explorer/interpreter/resolve_names.cpp index 2d9fcc6d4490..7e1b50369035 100644 --- a/explorer/interpreter/resolve_names.cpp +++ b/explorer/interpreter/resolve_names.cpp @@ -249,8 +249,7 @@ static auto ResolveNames(Expression& expression, &cast(enclosing_dot_self->base())); } // Introduce `.Self` into scope on the right of the `where` keyword. - StaticScope where_scope; - where_scope.AddParent(&enclosing_scope); + StaticScope where_scope(&enclosing_scope); CARBON_RETURN_IF_ERROR(where_scope.Add(".Self", &where.self_binding())); for (Nonnull clause : where.clauses()) { CARBON_RETURN_IF_ERROR(ResolveNames(*clause, where_scope)); @@ -327,8 +326,7 @@ static auto ResolveNames(Pattern& pattern, StaticScope& enclosing_scope) case PatternKind::GenericBinding: { auto& binding = cast(pattern); // `.Self` is in scope in the context of the type. - StaticScope self_scope; - self_scope.AddParent(&enclosing_scope); + StaticScope self_scope(&enclosing_scope); CARBON_RETURN_IF_ERROR(self_scope.Add(".Self", &binding)); CARBON_RETURN_IF_ERROR(ResolveNames(binding.type(), self_scope)); if (binding.name() != AnonymousName) { @@ -440,8 +438,7 @@ static auto ResolveNames(Statement& statement, StaticScope& enclosing_scope) } case StatementKind::Block: { auto& block = cast(statement); - StaticScope block_scope; - block_scope.AddParent(&enclosing_scope); + StaticScope block_scope(&enclosing_scope); for (Nonnull sub_statement : block.statements()) { CARBON_RETURN_IF_ERROR(ResolveNames(*sub_statement, block_scope)); } @@ -455,8 +452,7 @@ static auto ResolveNames(Statement& statement, StaticScope& enclosing_scope) break; } case StatementKind::For: { - StaticScope statement_scope; - statement_scope.AddParent(&enclosing_scope); + StaticScope statement_scope(&enclosing_scope); auto& for_stmt = cast(statement); CARBON_RETURN_IF_ERROR( ResolveNames(for_stmt.loop_target(), statement_scope)); @@ -470,8 +466,7 @@ static auto ResolveNames(Statement& statement, StaticScope& enclosing_scope) auto& match = cast(statement); CARBON_RETURN_IF_ERROR(ResolveNames(match.expression(), enclosing_scope)); for (Match::Clause& clause : match.clauses()) { - StaticScope clause_scope; - clause_scope.AddParent(&enclosing_scope); + StaticScope clause_scope(&enclosing_scope); CARBON_RETURN_IF_ERROR(ResolveNames(clause.pattern(), clause_scope)); CARBON_RETURN_IF_ERROR(ResolveNames(clause.statement(), clause_scope)); } @@ -482,8 +477,7 @@ static auto ResolveNames(Statement& statement, StaticScope& enclosing_scope) CARBON_RETURN_IF_ERROR( enclosing_scope.Add(continuation.name(), &continuation, StaticScope::NameStatus::DeclaredButNotUsable)); - StaticScope continuation_scope; - continuation_scope.AddParent(&enclosing_scope); + StaticScope continuation_scope(&enclosing_scope); CARBON_RETURN_IF_ERROR(ResolveNames(cast(statement).body(), continuation_scope)); enclosing_scope.MarkUsable(continuation.name()); @@ -528,8 +522,7 @@ static auto ResolveNames(Declaration& declaration, StaticScope& enclosing_scope, case DeclarationKind::InterfaceDeclaration: case DeclarationKind::ConstraintDeclaration: { auto& iface = cast(declaration); - StaticScope iface_scope; - iface_scope.AddParent(&enclosing_scope); + StaticScope iface_scope(&enclosing_scope); enclosing_scope.MarkDeclared(iface.name()); if (iface.params().has_value()) { CARBON_RETURN_IF_ERROR(ResolveNames(**iface.params(), iface_scope)); @@ -544,8 +537,7 @@ static auto ResolveNames(Declaration& declaration, StaticScope& enclosing_scope, } case DeclarationKind::ImplDeclaration: { auto& impl = cast(declaration); - StaticScope impl_scope; - impl_scope.AddParent(&enclosing_scope); + StaticScope impl_scope(&enclosing_scope); for (Nonnull binding : impl.deduced_parameters()) { CARBON_RETURN_IF_ERROR(ResolveNames(binding->type(), impl_scope)); CARBON_RETURN_IF_ERROR(impl_scope.Add(binding->name(), binding)); @@ -574,8 +566,7 @@ static auto ResolveNames(Declaration& declaration, StaticScope& enclosing_scope, case DeclarationKind::DestructorDeclaration: case DeclarationKind::FunctionDeclaration: { auto& function = cast(declaration); - StaticScope function_scope; - function_scope.AddParent(&enclosing_scope); + StaticScope function_scope(&enclosing_scope); const auto name = GetName(function); CARBON_CHECK(name) << "Unexpected missing name for `" << function << "`."; enclosing_scope.MarkDeclared(std::string(*name)); @@ -601,8 +592,7 @@ static auto ResolveNames(Declaration& declaration, StaticScope& enclosing_scope, } case DeclarationKind::ClassDeclaration: { auto& class_decl = cast(declaration); - StaticScope class_scope; - class_scope.AddParent(&enclosing_scope); + StaticScope class_scope(&enclosing_scope); enclosing_scope.MarkDeclared(class_decl.name()); if (class_decl.base_expr().has_value()) { CARBON_RETURN_IF_ERROR( @@ -620,8 +610,7 @@ static auto ResolveNames(Declaration& declaration, StaticScope& enclosing_scope, } case DeclarationKind::MixinDeclaration: { auto& mixin_decl = cast(declaration); - StaticScope mixin_scope; - mixin_scope.AddParent(&enclosing_scope); + StaticScope mixin_scope(&enclosing_scope); enclosing_scope.MarkDeclared(mixin_decl.name()); if (mixin_decl.params().has_value()) { CARBON_RETURN_IF_ERROR( @@ -640,8 +629,7 @@ static auto ResolveNames(Declaration& declaration, StaticScope& enclosing_scope, } case DeclarationKind::ChoiceDeclaration: { auto& choice = cast(declaration); - StaticScope choice_scope; - choice_scope.AddParent(&enclosing_scope); + StaticScope choice_scope(&enclosing_scope); enclosing_scope.MarkDeclared(choice.name()); if (choice.type_params().has_value()) { CARBON_RETURN_IF_ERROR( @@ -685,8 +673,7 @@ static auto ResolveNames(Declaration& declaration, StaticScope& enclosing_scope, } case DeclarationKind::AssociatedConstantDeclaration: { auto& let = cast(declaration); - StaticScope constant_scope; - constant_scope.AddParent(&enclosing_scope); + StaticScope constant_scope(&enclosing_scope); CARBON_RETURN_IF_ERROR(ResolveNames(let.binding(), constant_scope)); break; } diff --git a/explorer/interpreter/resolve_unformed.h b/explorer/interpreter/resolve_unformed.h index de48bff7a856..798fa87efd08 100644 --- a/explorer/interpreter/resolve_unformed.h +++ b/explorer/interpreter/resolve_unformed.h @@ -5,6 +5,9 @@ #ifndef CARBON_EXPLORER_INTERPRETER_RESOLVE_UNFORMED_H_ #define CARBON_EXPLORER_INTERPRETER_RESOLVE_UNFORMED_H_ +#include +#include + #include "explorer/ast/ast.h" #include "explorer/common/nonnull.h" diff --git a/explorer/interpreter/type_checker.h b/explorer/interpreter/type_checker.h index 2b016e890b9f..7cbcac9d4b96 100644 --- a/explorer/interpreter/type_checker.h +++ b/explorer/interpreter/type_checker.h @@ -5,7 +5,12 @@ #ifndef CARBON_EXPLORER_INTERPRETER_TYPE_CHECKER_H_ #define CARBON_EXPLORER_INTERPRETER_TYPE_CHECKER_H_ +#include #include +#include +#include +#include +#include #include "common/ostream.h" #include "explorer/ast/ast.h"