Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix nr2 use declaration import #3499

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 91 additions & 7 deletions gcc/rust/resolve/rust-early-name-resolver-2.0.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
namespace Rust {
namespace Resolver2_0 {

Early::Early (NameResolutionContext &ctx) : DefaultResolver (ctx), dirty (false)
Early::Early (NameResolutionContext &ctx)
: DefaultResolver (ctx), toplevel (TopLevel (ctx)), dirty (false)
{}

void
Expand All @@ -52,16 +53,10 @@ void
Early::go (AST::Crate &crate)
{
// First we go through TopLevel resolution to get all our declared items
auto toplevel = TopLevel (ctx);
toplevel.go (crate);

// We start with resolving the list of imports that `TopLevel` has built for
// us
for (auto &&import : toplevel.get_imports_to_resolve ())
build_import_mapping (std::move (import));

// Once this is done, we finalize their resolution
FinalizeImports (std::move (import_mappings), toplevel, ctx).go (crate);

dirty = toplevel.is_dirty ();
// We now proceed with resolving macros, which can be nested in almost any
Expand Down Expand Up @@ -375,5 +370,94 @@ Early::visit (AST::StructStruct &s)
DefaultResolver::visit (s);
}

void
Early::finalize_simple_import (const Early::ImportPair &mapping)
{
// FIXME: We probably need to store namespace information

auto locus = mapping.import_kind.to_resolve.get_locus ();
auto data = mapping.data;
auto identifier
= mapping.import_kind.to_resolve.get_final_segment ().get_segment_name ();

for (auto &&definition : data.definitions ())
toplevel
.insert_or_error_out (
identifier, locus, definition.first.get_node_id (), definition.second /* TODO: This isn't clear - it would be better if it was called .ns or something */);
}

void
Early::finalize_glob_import (NameResolutionContext &ctx,
const Early::ImportPair &mapping)
{
auto module = Analysis::Mappings::get ().lookup_ast_module (
mapping.data.module ().get_node_id ());
rust_assert (module);

GlobbingVisitor glob_visitor (ctx);
glob_visitor.go (module.value ());
}

void
Early::finalize_rebind_import (const Early::ImportPair &mapping)
{
// We can fetch the value here as `resolve_rebind` will only be called on
// imports of the right kind
auto &path = mapping.import_kind.to_resolve;
auto &rebind = mapping.import_kind.rebind.value ();
auto data = mapping.data;

location_t locus = UNKNOWN_LOCATION;
std::string declared_name;

// FIXME: This needs to be done in `FinalizeImports`
switch (rebind.get_new_bind_type ())
{
case AST::UseTreeRebind::NewBindType::IDENTIFIER:
declared_name = rebind.get_identifier ().as_string ();
locus = rebind.get_identifier ().get_locus ();
break;
case AST::UseTreeRebind::NewBindType::NONE:
declared_name = path.get_final_segment ().as_string ();
locus = path.get_final_segment ().get_locus ();
break;
case AST::UseTreeRebind::NewBindType::WILDCARD:
rust_unreachable ();
break;
}

for (auto &&definition : data.definitions ())
toplevel.insert_or_error_out (
declared_name, locus, definition.first.get_node_id (), definition.second /* TODO: This isn't clear - it would be better if it was called .ns or something */);
}

void
Early::visit (AST::UseDeclaration &decl)
{
auto &imports = toplevel.get_imports_to_resolve ();
auto current_import = imports.find (decl.get_node_id ());
if (current_import != imports.end ())
{
build_import_mapping (*current_import);
}

// Once this is done, we finalize their resolution
for (const auto &mapping : import_mappings.get (decl.get_node_id ()))
switch (mapping.import_kind.kind)
{
case TopLevel::ImportKind::Kind::Glob:
finalize_glob_import (ctx, mapping);
break;
case TopLevel::ImportKind::Kind::Simple:
finalize_simple_import (mapping);
break;
case TopLevel::ImportKind::Kind::Rebind:
finalize_rebind_import (mapping);
break;
}

DefaultResolver::visit (decl);
}

} // namespace Resolver2_0
} // namespace Rust
9 changes: 9 additions & 0 deletions gcc/rust/resolve/rust-early-name-resolver-2.0.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class Early : public DefaultResolver
{
using DefaultResolver::visit;

TopLevel toplevel;
bool dirty;

public:
Expand All @@ -59,6 +60,7 @@ class Early : public DefaultResolver

void visit (AST::Function &) override;
void visit (AST::StructStruct &) override;
void visit (AST::UseDeclaration &) override;

struct ImportData
{
Expand Down Expand Up @@ -246,6 +248,13 @@ class Early : public DefaultResolver
std::vector<Error> macro_resolve_errors;

void collect_error (Error e) { macro_resolve_errors.push_back (e); }

void finalize_simple_import (const Early::ImportPair &mapping);

void finalize_glob_import (NameResolutionContext &ctx,
const Early::ImportPair &mapping);

void finalize_rebind_import (const Early::ImportPair &mapping);
};

} // namespace Resolver2_0
Expand Down
95 changes: 0 additions & 95 deletions gcc/rust/resolve/rust-finalize-imports-2.0.cc
Original file line number Diff line number Diff line change
Expand Up @@ -125,100 +125,5 @@ GlobbingVisitor::visit (AST::UseDeclaration &use)
// Handle cycles ?
}

void
finalize_simple_import (TopLevel &toplevel, const Early::ImportPair &mapping)
{
// FIXME: We probably need to store namespace information

auto locus = mapping.import_kind.to_resolve.get_locus ();
auto data = mapping.data;
auto identifier
= mapping.import_kind.to_resolve.get_final_segment ().get_segment_name ();

for (auto &&definition : data.definitions ())
toplevel
.insert_or_error_out (
identifier, locus, definition.first.get_node_id (), definition.second /* TODO: This isn't clear - it would be better if it was called .ns or something */);
}

void
finalize_glob_import (NameResolutionContext &ctx,
const Early::ImportPair &mapping)
{
auto module = Analysis::Mappings::get ().lookup_ast_module (
mapping.data.module ().get_node_id ());
rust_assert (module);

GlobbingVisitor glob_visitor (ctx);
glob_visitor.go (module.value ());
}

void
finalize_rebind_import (TopLevel &toplevel, const Early::ImportPair &mapping)
{
// We can fetch the value here as `resolve_rebind` will only be called on
// imports of the right kind
auto &path = mapping.import_kind.to_resolve;
auto &rebind = mapping.import_kind.rebind.value ();
auto data = mapping.data;

location_t locus = UNKNOWN_LOCATION;
std::string declared_name;

// FIXME: This needs to be done in `FinalizeImports`
switch (rebind.get_new_bind_type ())
{
case AST::UseTreeRebind::NewBindType::IDENTIFIER:
declared_name = rebind.get_identifier ().as_string ();
locus = rebind.get_identifier ().get_locus ();
break;
case AST::UseTreeRebind::NewBindType::NONE:
declared_name = path.get_final_segment ().as_string ();
locus = path.get_final_segment ().get_locus ();
break;
case AST::UseTreeRebind::NewBindType::WILDCARD:
rust_unreachable ();
break;
}

for (auto &&definition : data.definitions ())
toplevel.insert_or_error_out (
declared_name, locus, definition.first.get_node_id (), definition.second /* TODO: This isn't clear - it would be better if it was called .ns or something */);
}

FinalizeImports::FinalizeImports (Early::ImportMappings &&data,
TopLevel &toplevel,
NameResolutionContext &ctx)
: DefaultResolver (ctx), data (std::move (data)), toplevel (toplevel),
ctx (ctx)
{}

void
FinalizeImports::go (AST::Crate &crate)
{
for (auto &item : crate.items)
item->accept_vis (*this);
}

void
FinalizeImports::visit (AST::UseDeclaration &use)
{
auto import_mappings = data.get (use.get_node_id ());

for (const auto &mapping : import_mappings)
switch (mapping.import_kind.kind)
{
case TopLevel::ImportKind::Kind::Glob:
finalize_glob_import (ctx, mapping);
break;
case TopLevel::ImportKind::Kind::Simple:
finalize_simple_import (toplevel, mapping);
break;
case TopLevel::ImportKind::Kind::Rebind:
finalize_rebind_import (toplevel, mapping);
break;
}
}

} // namespace Resolver2_0
} // namespace Rust
57 changes: 0 additions & 57 deletions gcc/rust/resolve/rust-finalize-imports-2.0.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,62 +49,5 @@ class GlobbingVisitor : public AST::DefaultASTVisitor
NameResolutionContext &ctx;
};

// TODO: Fix documentation
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I rename the file ? This pass technically does not exist anymore.

// How do we do that?
//
// We want to resolve in the EarlyNameResolver, but we want to declare in the
// TopLevel Should the TopLevel declare stubs? How does rustc do it? How to do
// that for globbing? Should we do globbing afterwards once we've declared all
// the Uses*?
//
// Basically, for each use declare it in a separate map - in the
// EarlyNameResolver resolve and fix the ForeverStack? Emptying the maps each
// time?
//
// e.g. TopLevel builds a std::vector<NodeId, SimplePath> use_trees_to_resolve;
// Early goes through and resolves the SimplePath, then replaces the NodeId with
// the resolved one? Do we even need to do that?
//
// rustc just creates an empty definition for the use tree.
//
// What about globbing? std::vector<GlobbulesPath> globules;
// Early goes through and visits the module's path and calls the
// GlobbingVisitor?
//
// the file `imports.rs` goes through and *finalizes* imports. So we can
// probably add a FinalizeImport pass after the TopLevel and the Early.
// - TopLevel takes care of declaring these use trees
// - Early takes care of resolving them to definition points
// - Finalize takes care of mapping the use's definition point to the actual
// definition point
// - We need to work more on that last bit to know exactly what is being
// inserted, but probably it's going to mutate the ForeverStack - is that okay?
// - Oh actually maybe no!
// - TopLevel creates a map of UseTrees with paths to resolve. This should
// probably be an ImportKind enum or whatever
// - Early resolves them, creates a map of SimplePath with the associated
// definition: Map<ImportKind, ImportData>
// - Finalizes visits all UseTrees and inserts the Definitions found for
// each ImportKind - easy!
// - yay!

class FinalizeImports : DefaultResolver
{
public:
FinalizeImports (Early::ImportMappings &&data, TopLevel &toplevel,
NameResolutionContext &ctx);

void go (AST::Crate &crate);

private:
using AST::DefaultASTVisitor::visit;

void visit (AST::UseDeclaration &) override;

Early::ImportMappings data;
TopLevel &toplevel;
NameResolutionContext &ctx;
};

} // namespace Resolver2_0
} // namespace Rust
5 changes: 2 additions & 3 deletions gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,9 @@ class TopLevel : public DefaultResolver
{}
};

std::unordered_map<NodeId, std::vector<ImportKind>> &&
get_imports_to_resolve ()
std::unordered_map<NodeId, std::vector<ImportKind>> &get_imports_to_resolve ()
{
return std::move (imports_to_resolve);
return imports_to_resolve;
}

/**
Expand Down
2 changes: 0 additions & 2 deletions gcc/testsuite/rust/compile/nr2/exclude
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ const_generics_4.rs
feature_rust_attri0.rs
generics9.rs
issue-1483.rs
issue-1786.rs
issue-1901.rs
issue-1981.rs
issue-2043.rs
Expand Down Expand Up @@ -38,7 +37,6 @@ v0-mangle2.rs
while_break_expr.rs
exhaustiveness2.rs
issue-3139-2.rs
issue-3033.rs
issue-2953-2.rs
issue-2905-2.rs
issue-266.rs
Expand Down