blob: d751318ee54a344c6624de147e6fea7427592d86 [file] [log] [blame]
// Copyright (C) 2020-2023 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#ifndef RUST_AST_RESOLVE_TOPLEVEL_H
#define RUST_AST_RESOLVE_TOPLEVEL_H
#include "rust-ast-resolve-base.h"
#include "rust-ast-resolve-type.h"
#include "rust-ast-resolve-implitem.h"
#include "rust-ast-full.h"
#include "rust-name-resolver.h"
#include "rust-session-manager.h"
namespace Rust {
namespace Resolver {
class ResolveTopLevel : public ResolverBase
{
using Rust::Resolver::ResolverBase::visit;
public:
static void go (AST::Item *item, const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix)
{
if (item->is_marked_for_strip ())
return;
ResolveTopLevel resolver (prefix, canonical_prefix);
item->accept_vis (resolver);
NodeId current_module = resolver.resolver->peek_current_module_scope ();
resolver.mappings->insert_child_item_to_parent_module_mapping (
item->get_node_id (), current_module);
}
void visit (AST::Module &module) override
{
auto mod
= CanonicalPath::new_seg (module.get_node_id (), module.get_name ());
auto path = prefix.append (mod);
auto cpath = canonical_prefix.append (mod);
resolver->get_name_scope ().insert (
path, module.get_node_id (), module.get_locus (), false,
Rib::ItemType::Module,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (module.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
NodeId current_module = resolver->peek_current_module_scope ();
mappings->insert_module_child_item (current_module, mod);
mappings->insert_module_child (current_module, module.get_node_id ());
resolver->push_new_module_scope (module.get_node_id ());
for (auto &item : module.get_items ())
ResolveTopLevel::go (item.get (), path, cpath);
resolver->pop_module_scope ();
mappings->insert_canonical_path (module.get_node_id (), cpath);
}
void visit (AST::TypeAlias &alias) override
{
auto talias = CanonicalPath::new_seg (alias.get_node_id (),
alias.get_new_type_name ());
auto path = prefix.append (talias);
auto cpath = canonical_prefix.append (talias);
resolver->get_type_scope ().insert (
path, alias.get_node_id (), alias.get_locus (), false,
Rib::ItemType::Type,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (alias.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
NodeId current_module = resolver->peek_current_module_scope ();
mappings->insert_module_child_item (current_module, talias);
mappings->insert_canonical_path (alias.get_node_id (), cpath);
}
void visit (AST::TupleStruct &struct_decl) override
{
auto decl = CanonicalPath::new_seg (struct_decl.get_node_id (),
struct_decl.get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_type_scope ().insert (
path, struct_decl.get_node_id (), struct_decl.get_locus (), false,
Rib::ItemType::Type,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (struct_decl.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
NodeId current_module = resolver->peek_current_module_scope ();
mappings->insert_module_child_item (current_module, decl);
mappings->insert_canonical_path (struct_decl.get_node_id (), cpath);
}
void visit (AST::Enum &enum_decl) override
{
auto decl = CanonicalPath::new_seg (enum_decl.get_node_id (),
enum_decl.get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_type_scope ().insert (
path, enum_decl.get_node_id (), enum_decl.get_locus (), false,
Rib::ItemType::Type,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (enum_decl.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
for (auto &variant : enum_decl.get_variants ())
ResolveTopLevel::go (variant.get (), path, cpath);
NodeId current_module = resolver->peek_current_module_scope ();
mappings->insert_module_child_item (current_module, decl);
mappings->insert_canonical_path (enum_decl.get_node_id (), cpath);
}
void visit (AST::EnumItem &item) override
{
auto decl
= CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_type_scope ().insert (
path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (item.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
mappings->insert_canonical_path (item.get_node_id (), cpath);
}
void visit (AST::EnumItemTuple &item) override
{
auto decl
= CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_type_scope ().insert (
path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (item.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
mappings->insert_canonical_path (item.get_node_id (), cpath);
}
void visit (AST::EnumItemStruct &item) override
{
auto decl
= CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_type_scope ().insert (
path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (item.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
mappings->insert_canonical_path (item.get_node_id (), cpath);
}
void visit (AST::EnumItemDiscriminant &item) override
{
auto decl
= CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_type_scope ().insert (
path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (item.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
mappings->insert_canonical_path (item.get_node_id (), cpath);
}
void visit (AST::StructStruct &struct_decl) override
{
auto decl = CanonicalPath::new_seg (struct_decl.get_node_id (),
struct_decl.get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_type_scope ().insert (
path, struct_decl.get_node_id (), struct_decl.get_locus (), false,
Rib::ItemType::Type,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (struct_decl.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
NodeId current_module = resolver->peek_current_module_scope ();
mappings->insert_module_child_item (current_module, decl);
mappings->insert_canonical_path (struct_decl.get_node_id (), cpath);
}
void visit (AST::Union &union_decl) override
{
auto decl = CanonicalPath::new_seg (union_decl.get_node_id (),
union_decl.get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_type_scope ().insert (
path, union_decl.get_node_id (), union_decl.get_locus (), false,
Rib::ItemType::Type,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (union_decl.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
NodeId current_module = resolver->peek_current_module_scope ();
mappings->insert_module_child_item (current_module, decl);
mappings->insert_canonical_path (union_decl.get_node_id (), cpath);
}
void visit (AST::StaticItem &var) override
{
auto decl
= CanonicalPath::new_seg (var.get_node_id (), var.get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_name_scope ().insert (
path, var.get_node_id (), var.get_locus (), false, Rib::ItemType::Static,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (var.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
NodeId current_module = resolver->peek_current_module_scope ();
mappings->insert_module_child_item (current_module, decl);
mappings->insert_canonical_path (var.get_node_id (), cpath);
}
void visit (AST::ConstantItem &constant) override
{
auto decl = CanonicalPath::new_seg (constant.get_node_id (),
constant.get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_name_scope ().insert (
path, constant.get_node_id (), constant.get_locus (), false,
Rib::ItemType::Const,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (constant.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
NodeId current_module = resolver->peek_current_module_scope ();
mappings->insert_module_child_item (current_module, decl);
mappings->insert_canonical_path (constant.get_node_id (), cpath);
}
void visit (AST::Function &function) override
{
auto decl = CanonicalPath::new_seg (function.get_node_id (),
function.get_function_name ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_name_scope ().insert (
path, function.get_node_id (), function.get_locus (), false,
Rib::ItemType::Function,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (function.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
NodeId current_module = resolver->peek_current_module_scope ();
mappings->insert_module_child_item (current_module, decl);
mappings->insert_canonical_path (function.get_node_id (), cpath);
}
void visit (AST::InherentImpl &impl_block) override
{
std::string raw_impl_type_path = impl_block.get_type ()->as_string ();
CanonicalPath impl_type
= CanonicalPath::new_seg (impl_block.get_type ()->get_node_id (),
raw_impl_type_path);
CanonicalPath impl_prefix = prefix.append (impl_type);
for (auto &impl_item : impl_block.get_impl_items ())
ResolveToplevelImplItem::go (impl_item.get (), impl_prefix);
}
void visit (AST::TraitImpl &impl_block) override
{
std::string raw_impl_type_path = impl_block.get_type ()->as_string ();
CanonicalPath impl_type_seg
= CanonicalPath::new_seg (impl_block.get_type ()->get_node_id (),
raw_impl_type_path);
std::string raw_trait_type_path = impl_block.get_trait_path ().as_string ();
CanonicalPath trait_type_seg
= CanonicalPath::new_seg (impl_block.get_trait_path ().get_node_id (),
raw_trait_type_path);
CanonicalPath projection
= CanonicalPath::trait_impl_projection_seg (impl_block.get_node_id (),
trait_type_seg,
impl_type_seg);
CanonicalPath impl_prefix = prefix.append (projection);
resolver->get_name_scope ().insert (
impl_prefix, impl_block.get_node_id (), impl_block.get_locus (), false,
Rib::ItemType::TraitImpl,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (impl_block.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
for (auto &impl_item : impl_block.get_impl_items ())
ResolveToplevelImplItem::go (impl_item.get (), impl_prefix);
}
void visit (AST::Trait &trait) override
{
auto decl
= CanonicalPath::new_seg (trait.get_node_id (), trait.get_identifier ());
auto path = prefix.append (decl);
auto cpath = canonical_prefix.append (decl);
resolver->get_type_scope ().insert (
path, trait.get_node_id (), trait.get_locus (), false,
Rib::ItemType::Trait,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (trait.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
for (auto &item : trait.get_trait_items ())
ResolveTopLevelTraitItems::go (item.get (), path, cpath);
NodeId current_module = resolver->peek_current_module_scope ();
mappings->insert_module_child_item (current_module, decl);
mappings->insert_canonical_path (trait.get_node_id (), cpath);
}
void visit (AST::ExternBlock &extern_block) override
{
for (auto &item : extern_block.get_extern_items ())
{
ResolveToplevelExternItem::go (item.get (), prefix);
}
}
void visit (AST::ExternCrate &extern_crate) override
{
if (extern_crate.is_marked_for_strip ())
return;
NodeId resolved_crate = UNKNOWN_NODEID;
if (extern_crate.references_self ())
{
CrateNum crate_num = mappings->get_current_crate ();
bool ok = mappings->crate_num_to_nodeid (crate_num, resolved_crate);
rust_assert (ok);
}
else
{
CrateNum found_crate_num = UNKNOWN_CREATENUM;
bool found
= mappings->lookup_crate_name (extern_crate.get_referenced_crate (),
found_crate_num);
if (!found)
{
rust_error_at (extern_crate.get_locus (), "unknown crate %<%s%>",
extern_crate.get_referenced_crate ().c_str ());
return;
}
bool ok
= mappings->crate_num_to_nodeid (found_crate_num, resolved_crate);
if (!ok)
{
rust_internal_error_at (extern_crate.get_locus (),
"failed to resolve crate to nodeid");
return;
}
}
if (resolved_crate == UNKNOWN_NODEID)
{
rust_error_at (extern_crate.get_locus (), "failed to resolve crate");
return;
}
// mark the node as resolved
resolver->insert_resolved_name (extern_crate.get_node_id (),
resolved_crate);
CanonicalPath decl
= extern_crate.has_as_clause ()
? CanonicalPath::new_seg (extern_crate.get_node_id (),
extern_crate.get_as_clause ())
: CanonicalPath::new_seg (extern_crate.get_node_id (),
extern_crate.get_referenced_crate ());
resolver->get_type_scope ().insert (
decl, resolved_crate, extern_crate.get_locus (), false,
Rib::ItemType::ExternCrate,
[&] (const CanonicalPath &, NodeId, Location locus) -> void {
RichLocation r (extern_crate.get_locus ());
r.add_range (locus);
rust_error_at (r, "redefined multiple times");
});
}
private:
ResolveTopLevel (const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix)
: ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix)
{}
const CanonicalPath &prefix;
const CanonicalPath &canonical_prefix;
};
} // namespace Resolver
} // namespace Rust
#endif // RUST_AST_RESOLVE_TOPLEVEL_H