aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/resolve
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust/resolve')
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-base.cc26
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-base.h10
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-expr.cc42
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-expr.h2
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-item.cc37
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-item.h3
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-pattern.cc57
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-stmt.h3
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-type.cc11
-rw-r--r--gcc/rust/resolve/rust-ast-resolve.cc3
-rw-r--r--gcc/rust/resolve/rust-default-resolver.cc323
-rw-r--r--gcc/rust/resolve/rust-default-resolver.h16
-rw-r--r--gcc/rust/resolve/rust-early-name-resolver-2.0.cc58
-rw-r--r--gcc/rust/resolve/rust-early-name-resolver-2.0.h14
-rw-r--r--gcc/rust/resolve/rust-early-name-resolver.cc2
-rw-r--r--gcc/rust/resolve/rust-early-name-resolver.h2
-rw-r--r--gcc/rust/resolve/rust-finalize-imports-2.0.cc29
-rw-r--r--gcc/rust/resolve/rust-finalize-imports-2.0.h7
-rw-r--r--gcc/rust/resolve/rust-forever-stack.h15
-rw-r--r--gcc/rust/resolve/rust-forever-stack.hxx264
-rw-r--r--gcc/rust/resolve/rust-ice-finalizer.cc10
-rw-r--r--gcc/rust/resolve/rust-ice-finalizer.h6
-rw-r--r--gcc/rust/resolve/rust-late-name-resolver-2.0.cc231
-rw-r--r--gcc/rust/resolve/rust-late-name-resolver-2.0.h13
-rw-r--r--gcc/rust/resolve/rust-name-resolution-context.cc116
-rw-r--r--gcc/rust/resolve/rust-name-resolution-context.h371
-rw-r--r--gcc/rust/resolve/rust-rib.h10
-rw-r--r--gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc165
-rw-r--r--gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h5
29 files changed, 1355 insertions, 496 deletions
diff --git a/gcc/rust/resolve/rust-ast-resolve-base.cc b/gcc/rust/resolve/rust-ast-resolve-base.cc
index b781ce33..3c7b425 100644
--- a/gcc/rust/resolve/rust-ast-resolve-base.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-base.cc
@@ -116,7 +116,7 @@ ResolverBase::visit (AST::MetaItemLitExpr &)
{}
void
-ResolverBase::visit (AST::MetaItemPathLit &)
+ResolverBase::visit (AST::MetaItemPathExpr &)
{}
void
@@ -232,6 +232,14 @@ ResolverBase::visit (AST::BlockExpr &)
{}
void
+ResolverBase::visit (AST::AnonConst &)
+{}
+
+void
+ResolverBase::visit (AST::ConstBlock &)
+{}
+
+void
ResolverBase::visit (AST::ClosureExprInnerTyped &)
{}
@@ -276,6 +284,10 @@ ResolverBase::visit (AST::ReturnExpr &)
{}
void
+ResolverBase::visit (AST::TryExpr &)
+{}
+
+void
ResolverBase::visit (AST::UnsafeBlockExpr &)
{}
@@ -572,6 +584,14 @@ ResolverBase::visit (AST::GroupedPattern &)
{}
void
+ResolverBase::visit (AST::SlicePatternItemsNoRest &)
+{}
+
+void
+ResolverBase::visit (AST::SlicePatternItemsHasRest &)
+{}
+
+void
ResolverBase::visit (AST::SlicePattern &)
{}
@@ -663,5 +683,9 @@ void
ResolverBase::visit (AST::FormatArgs &fmt)
{}
+void
+ResolverBase::visit (AST::OffsetOf &offset_of)
+{}
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h
index 5bb9e4f..89c5c35 100644
--- a/gcc/rust/resolve/rust-ast-resolve-base.h
+++ b/gcc/rust/resolve/rust-ast-resolve-base.h
@@ -21,6 +21,8 @@
#include "rust-ast-visitor.h"
#include "rust-ast.h"
+#include "rust-builtin-ast-nodes.h"
+#include "rust-expr.h"
#include "rust-name-resolver.h"
#include "rust-diagnostics.h"
#include "rust-location.h"
@@ -56,7 +58,7 @@ public:
void visit (AST::AttrInputLiteral &);
void visit (AST::AttrInputMacro &);
void visit (AST::MetaItemLitExpr &);
- void visit (AST::MetaItemPathLit &);
+ void visit (AST::MetaItemPathExpr &);
void visit (AST::BorrowExpr &);
void visit (AST::DereferenceExpr &);
void visit (AST::ErrorPropagationExpr &);
@@ -85,6 +87,8 @@ public:
void visit (AST::FieldAccessExpr &);
void visit (AST::ClosureExprInner &);
void visit (AST::BlockExpr &);
+ void visit (AST::AnonConst &);
+ void visit (AST::ConstBlock &);
void visit (AST::ClosureExprInnerTyped &);
void visit (AST::ContinueExpr &);
void visit (AST::BreakExpr &);
@@ -96,6 +100,7 @@ public:
void visit (AST::RangeToInclExpr &);
void visit (AST::BoxExpr &);
void visit (AST::ReturnExpr &);
+ void visit (AST::TryExpr &);
void visit (AST::UnsafeBlockExpr &);
void visit (AST::LoopExpr &);
void visit (AST::WhileLoopExpr &);
@@ -181,6 +186,8 @@ public:
void visit (AST::TuplePatternItemsRanged &);
void visit (AST::TuplePattern &);
void visit (AST::GroupedPattern &);
+ void visit (AST::SlicePatternItemsNoRest &);
+ void visit (AST::SlicePatternItemsHasRest &);
void visit (AST::SlicePattern &);
void visit (AST::AltPattern &);
@@ -207,6 +214,7 @@ public:
void visit (AST::SelfParam &param);
void visit (AST::FormatArgs &fmt);
+ void visit (AST::OffsetOf &offset_of);
protected:
ResolverBase ()
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.cc b/gcc/rust/resolve/rust-ast-resolve-expr.cc
index 6242235..a410193 100644
--- a/gcc/rust/resolve/rust-ast-resolve-expr.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-expr.cc
@@ -129,8 +129,8 @@ ResolveExpr::visit (AST::IdentifierExpr &expr)
resolve. Emit a funny ICE. We set the finalizer to our custom one,
and use the lower-level emit_diagnostic () instead of the more common
internal_error_no_backtrace () in order to pass our locus. */
- diagnostic_text_finalizer (global_dc) = funny_ice_text_finalizer;
- emit_diagnostic (DK_ICE_NOBT, expr.get_locus (), -1,
+ diagnostics::text_finalizer (global_dc) = funny_ice_text_finalizer;
+ emit_diagnostic (diagnostics::kind::ice_nobt, expr.get_locus (), -1,
"are you trying to break %s? how dare you?",
expr.as_string ().c_str ());
}
@@ -315,6 +315,18 @@ ResolveExpr::visit (AST::BlockExpr &expr)
}
void
+ResolveExpr::visit (AST::AnonConst &expr)
+{
+ ResolveExpr::go (expr.get_inner_expr (), prefix, canonical_prefix);
+}
+
+void
+ResolveExpr::visit (AST::ConstBlock &expr)
+{
+ ResolveExpr::go (expr.get_const_expr (), prefix, canonical_prefix);
+}
+
+void
translate_operand (AST::InlineAsm &expr, const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix)
{
@@ -324,38 +336,46 @@ translate_operand (AST::InlineAsm &expr, const CanonicalPath &prefix,
{
switch (operand.get_register_type ())
{
- case RegisterType::In: {
+ case RegisterType::In:
+ {
auto in = operand.get_in ();
ResolveExpr::go (*in.expr, prefix, canonical_prefix);
break;
}
- case RegisterType::Out: {
+ case RegisterType::Out:
+ {
auto out = operand.get_out ();
ResolveExpr::go (*out.expr, prefix, canonical_prefix);
break;
}
- case RegisterType::InOut: {
+ case RegisterType::InOut:
+ {
auto in_out = operand.get_in_out ();
ResolveExpr::go (*in_out.expr, prefix, canonical_prefix);
break;
}
- case RegisterType::SplitInOut: {
+ case RegisterType::SplitInOut:
+ {
auto split_in_out = operand.get_split_in_out ();
ResolveExpr::go (*split_in_out.in_expr, prefix, canonical_prefix);
ResolveExpr::go (*split_in_out.out_expr, prefix, canonical_prefix);
break;
}
- case RegisterType::Const: {
+ case RegisterType::Const:
+ {
auto anon_const = operand.get_const ().anon_const;
- ResolveExpr::go (*anon_const.expr, prefix, canonical_prefix);
+ ResolveExpr::go (anon_const.get_inner_expr (), prefix,
+ canonical_prefix);
break;
}
- case RegisterType::Sym: {
+ case RegisterType::Sym:
+ {
auto sym = operand.get_sym ();
ResolveExpr::go (*sym.expr, prefix, canonical_prefix);
break;
}
- case RegisterType::Label: {
+ case RegisterType::Label:
+ {
auto label = operand.get_label ();
ResolveExpr::go (*label.expr, prefix, canonical_prefix);
break;
@@ -766,7 +786,7 @@ ResolveExpr::visit (AST::ClosureExprInnerTyped &expr)
resolver->push_closure_context (expr.get_node_id ());
- ResolveExpr::go (expr.get_definition_block (), prefix, canonical_prefix);
+ ResolveExpr::go (expr.get_definition_expr (), prefix, canonical_prefix);
resolver->pop_closure_context ();
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h
index b296d66..aad1605 100644
--- a/gcc/rust/resolve/rust-ast-resolve-expr.h
+++ b/gcc/rust/resolve/rust-ast-resolve-expr.h
@@ -56,6 +56,8 @@ public:
void visit (AST::IfLetExpr &expr) override;
void visit (AST::IfLetExprConseqElse &expr) override;
void visit (AST::BlockExpr &expr) override;
+ void visit (AST::AnonConst &expr) override;
+ void visit (AST::ConstBlock &expr) override;
void visit (AST::InlineAsm &expr) override;
void visit (AST::LlvmInlineAsm &expr) override;
void visit (AST::UnsafeBlockExpr &expr) override;
diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc
index 30f6d43..1d5ebed 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-item.cc
@@ -453,7 +453,8 @@ ResolveItem::visit (AST::ConstantItem &constant)
resolve_visibility (constant.get_visibility ());
ResolveType::go (constant.get_type ());
- ResolveExpr::go (constant.get_expr (), path, cpath);
+ if (constant.has_expr ())
+ ResolveExpr::go (constant.get_expr (), path, cpath);
}
void
@@ -608,10 +609,7 @@ ResolveItem::visit (AST::InherentImpl &impl_block)
}
else
{
- std::string seg_buf = "<impl " + self_cpath.get () + ">";
- CanonicalPath seg
- = CanonicalPath::new_seg (impl_block.get_node_id (), seg_buf);
- cpath = canonical_prefix.append (seg);
+ cpath = canonical_prefix.append (impl_type_seg);
}
// done setup paths
@@ -732,13 +730,7 @@ ResolveItem::visit (AST::TraitImpl &impl_block)
}
else
{
- std::string projection_str = canonical_projection.get ();
- std::string seg_buf
- = "<impl " + projection_str.substr (1, projection_str.size () - 2)
- + ">";
- CanonicalPath seg
- = CanonicalPath::new_seg (impl_block.get_node_id (), seg_buf);
- cpath = canonical_prefix.append (seg);
+ cpath = canonical_prefix.append (canonical_projection);
}
// DONE setup canonical-path
@@ -838,29 +830,32 @@ ResolveItem::resolve_extern_item (AST::ExternalItem &item)
ResolveExternItem::go (item, prefix, canonical_prefix);
}
-static void
-flatten_glob (const AST::UseTreeGlob &glob, std::vector<Import> &imports);
-static void
-flatten_rebind (const AST::UseTreeRebind &glob, std::vector<Import> &imports);
-static void
-flatten_list (const AST::UseTreeList &glob, std::vector<Import> &imports);
+static void flatten_glob (const AST::UseTreeGlob &glob,
+ std::vector<Import> &imports);
+static void flatten_rebind (const AST::UseTreeRebind &glob,
+ std::vector<Import> &imports);
+static void flatten_list (const AST::UseTreeList &glob,
+ std::vector<Import> &imports);
static void
flatten (const AST::UseTree *tree, std::vector<Import> &imports)
{
switch (tree->get_kind ())
{
- case AST::UseTree::Glob: {
+ case AST::UseTree::Glob:
+ {
auto glob = static_cast<const AST::UseTreeGlob *> (tree);
flatten_glob (*glob, imports);
break;
}
- case AST::UseTree::Rebind: {
+ case AST::UseTree::Rebind:
+ {
auto rebind = static_cast<const AST::UseTreeRebind *> (tree);
flatten_rebind (*rebind, imports);
break;
}
- case AST::UseTree::List: {
+ case AST::UseTree::List:
+ {
auto list = static_cast<const AST::UseTreeList *> (tree);
flatten_list (*list, imports);
break;
diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h
index 776dd53..d31f910 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.h
+++ b/gcc/rust/resolve/rust-ast-resolve-item.h
@@ -153,8 +153,7 @@ private:
#if CHECKING_P
namespace selftest {
-extern void
-rust_simple_path_resolve_test (void);
+extern void rust_simple_path_resolve_test (void);
} // namespace selftest
#endif // CHECKING_P
diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.cc b/gcc/rust/resolve/rust-ast-resolve-pattern.cc
index ee84be8..3b80f9f 100644
--- a/gcc/rust/resolve/rust-ast-resolve-pattern.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-pattern.cc
@@ -62,6 +62,11 @@ PatternDeclaration::go (AST::Pattern &pattern, Rib::ItemType type,
void
PatternDeclaration::visit (AST::IdentifierPattern &pattern)
{
+ if (pattern.has_subpattern ())
+ {
+ pattern.get_subpattern ().accept_vis (*this);
+ }
+
Mutability mut = pattern.get_is_mut () ? Mutability::Mut : Mutability::Imm;
add_new_binding (pattern.get_ident (), pattern.get_node_id (),
BindingTypeInfo (mut, pattern.get_is_ref (),
@@ -94,13 +99,15 @@ PatternDeclaration::visit (AST::TupleStructPattern &pattern)
AST::TupleStructItems &items = pattern.get_items ();
switch (items.get_item_type ())
{
- case AST::TupleStructItems::RANGE: {
+ case AST::TupleStructItems::RANGE:
+ {
// TODO
rust_unreachable ();
}
break;
- case AST::TupleStructItems::NO_RANGE: {
+ case AST::TupleStructItems::NO_RANGE:
+ {
auto &items_no_range
= static_cast<AST::TupleStructItemsNoRange &> (items);
@@ -123,7 +130,8 @@ PatternDeclaration::visit (AST::StructPattern &pattern)
{
switch (field->get_item_type ())
{
- case AST::StructPatternField::ItemType::TUPLE_PAT: {
+ case AST::StructPatternField::ItemType::TUPLE_PAT:
+ {
AST::StructPatternFieldTuplePat &tuple
= static_cast<AST::StructPatternFieldTuplePat &> (*field);
@@ -131,7 +139,8 @@ PatternDeclaration::visit (AST::StructPattern &pattern)
}
break;
- case AST::StructPatternField::ItemType::IDENT_PAT: {
+ case AST::StructPatternField::ItemType::IDENT_PAT:
+ {
AST::StructPatternFieldIdentPat &ident
= static_cast<AST::StructPatternFieldIdentPat &> (*field);
@@ -139,7 +148,8 @@ PatternDeclaration::visit (AST::StructPattern &pattern)
}
break;
- case AST::StructPatternField::ItemType::IDENT: {
+ case AST::StructPatternField::ItemType::IDENT:
+ {
auto &ident = static_cast<AST::StructPatternFieldIdent &> (*field);
Mutability mut
@@ -160,7 +170,8 @@ PatternDeclaration::visit (AST::TuplePattern &pattern)
auto &items = pattern.get_items ();
switch (items.get_pattern_type ())
{
- case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE: {
+ case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE:
+ {
auto &ref = static_cast<AST::TuplePatternItemsMultiple &> (
pattern.get_items ());
@@ -169,7 +180,8 @@ PatternDeclaration::visit (AST::TuplePattern &pattern)
}
break;
- case AST::TuplePatternItems::TuplePatternItemType::RANGED: {
+ case AST::TuplePatternItems::TuplePatternItemType::RANGED:
+ {
auto &ref
= static_cast<AST::TuplePatternItemsRanged &> (pattern.get_items ());
@@ -348,14 +360,16 @@ resolve_range_pattern_bound (AST::RangePatternBound &bound)
// Nothing to resolve for a literal.
break;
- case AST::RangePatternBound::RangePatternBoundType::PATH: {
+ case AST::RangePatternBound::RangePatternBoundType::PATH:
+ {
auto &ref = static_cast<AST::RangePatternBoundPath &> (bound);
ResolvePath::go (ref.get_path ());
}
break;
- case AST::RangePatternBound::RangePatternBoundType::QUALPATH: {
+ case AST::RangePatternBound::RangePatternBoundType::QUALPATH:
+ {
auto &ref = static_cast<AST::RangePatternBoundQualPath &> (bound);
ResolvePath::go (ref.get_qualified_path ());
@@ -374,9 +388,30 @@ PatternDeclaration::visit (AST::RangePattern &pattern)
void
PatternDeclaration::visit (AST::SlicePattern &pattern)
{
- for (auto &p : pattern.get_items ())
+ auto &items = pattern.get_items ();
+ switch (items.get_pattern_type ())
{
- p->accept_vis (*this);
+ case AST::SlicePatternItems::SlicePatternItemType::NO_REST:
+ {
+ auto &ref
+ = static_cast<AST::SlicePatternItemsNoRest &> (pattern.get_items ());
+
+ for (auto &p : ref.get_patterns ())
+ p->accept_vis (*this);
+ }
+ break;
+
+ case AST::SlicePatternItems::SlicePatternItemType::HAS_REST:
+ {
+ auto &ref
+ = static_cast<AST::SlicePatternItemsHasRest &> (pattern.get_items ());
+
+ for (auto &p : ref.get_lower_patterns ())
+ p->accept_vis (*this);
+ for (auto &p : ref.get_upper_patterns ())
+ p->accept_vis (*this);
+ }
+ break;
}
}
diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h
index d413a7c..d714511 100644
--- a/gcc/rust/resolve/rust-ast-resolve-stmt.h
+++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h
@@ -67,7 +67,8 @@ public:
});
ResolveType::go (constant.get_type ());
- ResolveExpr::go (constant.get_expr (), prefix, canonical_prefix);
+ if (constant.has_expr ())
+ ResolveExpr::go (constant.get_expr (), prefix, canonical_prefix);
}
void visit (AST::LetStmt &stmt) override
diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc
index 8fd69c3..a040228 100644
--- a/gcc/rust/resolve/rust-ast-resolve-type.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-type.cc
@@ -140,7 +140,7 @@ ResolveType::visit (AST::ImplTraitType &type)
void
ResolveType::visit (AST::ImplTraitTypeOneBound &type)
{
- ResolveTypeBound::go (type.get_trait_bound ());
+ ResolveTypeBound::go (*type.get_trait_bound ().get ());
}
// resolve relative type-paths
@@ -210,7 +210,8 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id)
switch (segment->get_type ())
{
- case AST::TypePathSegment::SegmentType::GENERIC: {
+ case AST::TypePathSegment::SegmentType::GENERIC:
+ {
AST::TypePathSegmentGeneric *s
= static_cast<AST::TypePathSegmentGeneric *> (segment.get ());
if (s->has_generic_args ())
@@ -509,7 +510,8 @@ ResolveTypeToCanonicalPath::visit (AST::TypePath &path)
auto &final_seg = path.get_segments ().back ();
switch (final_seg->get_type ())
{
- case AST::TypePathSegment::SegmentType::GENERIC: {
+ case AST::TypePathSegment::SegmentType::GENERIC:
+ {
AST::TypePathSegmentGeneric *s
= static_cast<AST::TypePathSegmentGeneric *> (final_seg.get ());
@@ -651,7 +653,8 @@ ResolveTypeToCanonicalPath::visit (AST::TraitObjectType &type)
switch (additional_bound->get_bound_type ())
{
- case AST::TypeParamBound::TRAIT: {
+ case AST::TypeParamBound::TRAIT:
+ {
auto bound_path = CanonicalPath::create_empty ();
auto &bound_type_path
diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc
index 3e3c992..2208f70 100644
--- a/gcc/rust/resolve/rust-ast-resolve.cc
+++ b/gcc/rust/resolve/rust-ast-resolve.cc
@@ -24,8 +24,7 @@
#include "rust-ast-resolve-expr.h"
#include "rust-ast-resolve-struct-expr-field.h"
-extern bool
-saw_errors (void);
+extern bool saw_errors (void);
namespace Rust {
namespace Resolver {
diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc
index 480034c..f1c0e5c 100644
--- a/gcc/rust/resolve/rust-default-resolver.cc
+++ b/gcc/rust/resolve/rust-default-resolver.cc
@@ -25,6 +25,21 @@ namespace Rust {
namespace Resolver2_0 {
void
+DefaultResolver::visit (AST::Crate &crate)
+{
+ auto inner_fn = [this, &crate] () { AST::DefaultASTVisitor::visit (crate); };
+
+ auto &mappings = Analysis::Mappings::get ();
+
+ auto crate_num = mappings.lookup_crate_num (crate.get_node_id ());
+ rust_assert (crate_num.has_value ());
+ auto crate_name = mappings.get_crate_name (*crate_num);
+ rust_assert (crate_name.has_value ());
+
+ ctx.canonical_ctx.scope_crate (crate.get_node_id (), *crate_name, inner_fn);
+}
+
+void
DefaultResolver::visit (AST::BlockExpr &expr)
{
// extracting the lambda from the `scoped` call otherwise the code looks like
@@ -38,19 +53,32 @@ DefaultResolver::visit (AST::BlockExpr &expr)
void
DefaultResolver::visit (AST::Module &module)
{
- auto item_fn = [this, &module] () { AST::DefaultASTVisitor::visit (module); };
+ auto item_fn_1
+ = [this, &module] () { AST::DefaultASTVisitor::visit (module); };
+
+ auto item_fn_2 = [this, &module, &item_fn_1] () {
+ ctx.canonical_ctx.scope (module.get_node_id (), module.get_name (),
+ std::move (item_fn_1));
+ };
- ctx.scoped (Rib::Kind::Module, module.get_node_id (), item_fn,
+ ctx.scoped (Rib::Kind::Module, module.get_node_id (), item_fn_2,
module.get_name ());
}
void
DefaultResolver::visit (AST::Function &function)
{
- auto def_fn
+ auto def_fn_1
= [this, &function] () { AST::DefaultASTVisitor::visit (function); };
- ctx.scoped (Rib::Kind::Function, function.get_node_id (), def_fn);
+ auto def_fn_2 = [this, &function, &def_fn_1] () {
+ ctx.canonical_ctx.scope (function.get_node_id (),
+ function.get_function_name (),
+ std::move (def_fn_1));
+ };
+
+ ctx.scoped (Rib::Kind::Function, function.get_node_id (), def_fn_2,
+ function.get_function_name ());
}
void
@@ -61,73 +89,252 @@ DefaultResolver::visit (AST::ForLoopExpr &expr)
}
void
-DefaultResolver::visit (AST::Trait &trait)
+DefaultResolver::visit_if_let_patterns (AST::IfLetExpr &expr)
+{
+ for (auto &pattern : expr.get_patterns ())
+ visit (pattern);
+}
+
+void
+DefaultResolver::visit (AST::IfLetExpr &expr)
{
- auto inner_fn = [this, &trait] () { AST::DefaultASTVisitor::visit (trait); };
+ auto inner_vis = [this, &expr] () {
+ visit_if_let_patterns (expr);
+ visit (expr.get_if_block ());
+ };
+
+ visit_outer_attrs (expr);
+
+ visit (expr.get_value_expr ());
+
+ ctx.scoped (Rib::Kind::Normal, expr.get_node_id (), inner_vis);
+}
+
+void
+DefaultResolver::visit (AST::IfLetExprConseqElse &expr)
+{
+ DefaultResolver::visit (static_cast<AST::IfLetExpr &> (expr));
+ visit (expr.get_else_block ());
+}
- ctx.scoped (Rib::Kind::TraitOrImpl, trait.get_node_id (), inner_fn,
+void
+DefaultResolver::visit (AST::Trait &trait)
+{
+ visit_outer_attrs (trait);
+ visit (trait.get_visibility ());
+ visit_inner_attrs (trait);
+
+ auto inner_fn_1 = [this, &trait] () {
+ for (auto &item : trait.get_trait_items ())
+ visit (item);
+ };
+
+ auto inner_fn_2 = [this, &trait, &inner_fn_1] () {
+ visit (trait.get_implicit_self ());
+ for (auto &generic : trait.get_generic_params ())
+ visit (generic);
+ if (trait.has_where_clause ())
+ visit (trait.get_where_clause ());
+ for (auto &bound : trait.get_type_param_bounds ())
+ visit (bound);
+
+ ctx.scoped (Rib::Kind::TraitOrImpl, trait.get_node_id (), inner_fn_1);
+ };
+
+ auto inner_fn_3 = [this, &trait, &inner_fn_2] () {
+ ctx.canonical_ctx.scope (trait.get_node_id (), trait.get_identifier (),
+ std::move (inner_fn_2));
+ };
+
+ ctx.scoped (Rib::Kind::Generics, trait.get_node_id (), inner_fn_3,
trait.get_identifier () /* FIXME: Is that valid?*/);
}
void
DefaultResolver::visit (AST::InherentImpl &impl)
{
- auto inner_fn = [this, &impl] () { AST::DefaultASTVisitor::visit (impl); };
-
- ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn);
+ visit_outer_attrs (impl);
+ visit (impl.get_visibility ());
+ visit_inner_attrs (impl);
+
+ auto inner_fn_1 = [this, &impl] () {
+ for (auto &item : impl.get_impl_items ())
+ visit (item);
+ };
+
+ auto inner_fn_2 = [this, &impl, &inner_fn_1] () {
+ maybe_insert_big_self (impl);
+ for (auto &generic : impl.get_generic_params ())
+ visit (generic);
+ if (impl.has_where_clause ())
+ visit (impl.get_where_clause ());
+ visit_impl_type (impl.get_type ());
+
+ ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_1);
+ };
+
+ auto inner_fn_3 = [this, &impl, &inner_fn_2] () {
+ ctx.canonical_ctx.scope_impl (impl, std::move (inner_fn_2));
+ };
+
+ ctx.scoped (Rib::Kind::Generics, impl.get_node_id (), inner_fn_3);
}
void
DefaultResolver::visit (AST::TraitImpl &impl)
{
- auto inner_fn = [this, &impl] () { AST::DefaultASTVisitor::visit (impl); };
-
- ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn);
+ visit_outer_attrs (impl);
+ visit (impl.get_visibility ());
+ visit_inner_attrs (impl);
+
+ auto inner_fn_1 = [this, &impl] () {
+ for (auto &item : impl.get_impl_items ())
+ visit (item);
+ };
+
+ auto inner_fn_2 = [this, &impl, &inner_fn_1] () {
+ maybe_insert_big_self (impl);
+ for (auto &generic : impl.get_generic_params ())
+ visit (generic);
+ if (impl.has_where_clause ())
+ visit (impl.get_where_clause ());
+ visit_impl_type (impl.get_type ());
+ visit (impl.get_trait_path ());
+
+ ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_1);
+ };
+
+ auto inner_fn_3 = [this, &impl, &inner_fn_2] () {
+ ctx.canonical_ctx.scope_impl (impl, std::move (inner_fn_2));
+ };
+
+ ctx.scoped (Rib::Kind::Generics, impl.get_node_id (), inner_fn_3);
}
void
DefaultResolver::visit (AST::StructStruct &type)
{
- auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+ auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+
+ auto inner_fn_2 = [this, &type, &inner_fn_1] () {
+ ctx.canonical_ctx.scope (type.get_node_id (), type.get_struct_name (),
+ std::move (inner_fn_1));
+ };
ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (),
- inner_fn, type.get_struct_name ());
+ inner_fn_2, type.get_struct_name ());
}
void
DefaultResolver::visit (AST::TupleStruct &type)
{
- auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+ auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+
+ auto inner_fn_2 = [this, &type, &inner_fn_1] () {
+ ctx.canonical_ctx.scope (type.get_node_id (), type.get_struct_name (),
+ std::move (inner_fn_1));
+ };
ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (),
- inner_fn, type.get_struct_name ());
+ inner_fn_2, type.get_struct_name ());
+}
+
+void
+DefaultResolver::visit (AST::EnumItem &item)
+{
+ auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+
+ ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (),
+ inner_fn);
+}
+
+void
+DefaultResolver::visit (AST::EnumItemTuple &item)
+{
+ auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+
+ ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (),
+ inner_fn);
+}
+
+void
+DefaultResolver::visit (AST::EnumItemStruct &item)
+{
+ auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+
+ ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (),
+ inner_fn);
+}
+
+void
+DefaultResolver::visit (AST::EnumItemDiscriminant &item)
+{
+ auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+
+ ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (),
+ inner_fn);
}
void
DefaultResolver::visit (AST::Enum &type)
{
- auto variant_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+ auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+
+ auto inner_fn_2 = [this, &type, &inner_fn_1] () {
+ ctx.canonical_ctx.scope (type.get_node_id (), type.get_identifier (),
+ std::move (inner_fn_1));
+ };
ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (),
- variant_fn, type.get_identifier ());
+ inner_fn_2, type.get_identifier ());
}
void
DefaultResolver::visit (AST::Union &type)
{
- auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+ auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+
+ auto inner_fn_2 = [this, &type, &inner_fn_1] () {
+ ctx.canonical_ctx.scope (type.get_node_id (), type.get_identifier (),
+ std::move (inner_fn_1));
+ };
ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (),
- inner_fn, type.get_identifier ());
+ inner_fn_2, type.get_identifier ());
}
void
DefaultResolver::visit (AST::TypeAlias &type)
{
- auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+ auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+
+ auto inner_fn_2 = [this, &type, &inner_fn_1] () {
+ ctx.canonical_ctx.scope (type.get_node_id (), type.get_new_type_name (),
+ std::move (inner_fn_1));
+ };
ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (),
- inner_fn, type.get_new_type_name ());
+ inner_fn_2, type.get_new_type_name ());
+}
+
+void
+DefaultResolver::visit_closure_params (AST::ClosureExpr &expr)
+{
+ for (auto &param : expr.get_params ())
+ visit (param);
+}
+
+void
+DefaultResolver::visit (AST::ClosureExpr &expr)
+{
+ auto expr_fn = [this, &expr] () {
+ visit_closure_params (expr);
+ visit (expr.get_definition_expr ());
+ };
+
+ visit_outer_attrs (expr);
+
+ ctx.scoped (Rib::Kind::Normal, expr.get_node_id (), expr_fn);
}
void
@@ -136,7 +343,7 @@ DefaultResolver::visit (AST::ClosureExprInner &expr)
if (expr.is_marked_for_strip ())
return;
- AST::DefaultASTVisitor::visit (expr);
+ visit (static_cast<AST::ClosureExpr &> (expr));
}
void
@@ -145,7 +352,8 @@ DefaultResolver::visit (AST::ClosureExprInnerTyped &expr)
if (expr.is_marked_for_strip ())
return;
- AST::DefaultASTVisitor::visit (expr);
+ visit (static_cast<AST::ClosureExpr &> (expr));
+ visit (expr.get_return_type ());
}
void
@@ -160,23 +368,29 @@ DefaultResolver::visit (AST::MatchExpr &expr)
void
DefaultResolver::visit (AST::ConstantItem &item)
{
- if (item.has_expr ())
- {
- auto expr_vis
- = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+ auto expr_vis_1 = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
- // FIXME: Why do we need a Rib here?
- ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis);
- }
+ auto expr_vis_2 = [this, &item, &expr_vis_1] () {
+ ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (),
+ std::move (expr_vis_1));
+ };
+
+ // FIXME: Why do we need a Rib here?
+ ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis_2);
}
void
DefaultResolver::visit (AST::StaticItem &item)
{
- auto expr_vis = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+ auto expr_vis_1 = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+
+ auto expr_vis_2 = [this, &item, &expr_vis_1] () {
+ ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (),
+ std::move (expr_vis_1));
+ };
// FIXME: Why do we need a Rib here?
- ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis);
+ ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis_2);
}
void
@@ -187,5 +401,46 @@ DefaultResolver::visit (AST::TypeParam &param)
ctx.scoped (Rib::Kind::ForwardTypeParamBan, param.get_node_id (), expr_vis);
}
+void
+DefaultResolver::visit_extern_crate (AST::ExternCrate &extern_crate,
+ AST::Crate &crate, CrateNum num)
+{
+ visit (crate);
+}
+
+void
+DefaultResolver::visit (AST::ExternCrate &crate)
+{
+ auto &mappings = Analysis::Mappings::get ();
+ auto num_opt = mappings.lookup_crate_name (crate.get_referenced_crate ());
+
+ if (!num_opt)
+ {
+ rust_error_at (crate.get_locus (), "unknown crate %qs",
+ crate.get_referenced_crate ().c_str ());
+ return;
+ }
+
+ CrateNum num = *num_opt;
+
+ AST::Crate &referenced_crate = mappings.get_ast_crate (num);
+
+ auto sub_visitor_1
+ = [&, this] () { visit_extern_crate (crate, referenced_crate, num); };
+
+ auto sub_visitor_2 = [&] () {
+ ctx.canonical_ctx.scope_crate (referenced_crate.get_node_id (),
+ crate.get_referenced_crate (),
+ std::move (sub_visitor_1));
+ };
+
+ if (crate.has_as_clause ())
+ ctx.scoped (Rib::Kind::Module, referenced_crate.get_node_id (),
+ sub_visitor_2, crate.get_as_clause ());
+ else
+ ctx.scoped (Rib::Kind::Module, referenced_crate.get_node_id (),
+ sub_visitor_2, crate.get_referenced_crate ());
+}
+
} // namespace Resolver2_0
} // namespace Rust
diff --git a/gcc/rust/resolve/rust-default-resolver.h b/gcc/rust/resolve/rust-default-resolver.h
index 2a987ef..cf0df68 100644
--- a/gcc/rust/resolve/rust-default-resolver.h
+++ b/gcc/rust/resolve/rust-default-resolver.h
@@ -39,6 +39,7 @@ public:
virtual ~DefaultResolver () {}
+ void visit (AST::Crate &) override;
// First, our lexical scope expressions - these visit their sub nodes, always
// these nodes create new scopes and ribs - they are often used to declare new
// variables, such as a for loop's iterator, or a function's arguments
@@ -46,20 +47,35 @@ public:
void visit (AST::Module &) override;
void visit (AST::Function &) override;
void visit (AST::ForLoopExpr &expr) override;
+ virtual void visit_if_let_patterns (AST::IfLetExpr &expr);
+ void visit (AST::IfLetExpr &expr) override;
+ void visit (AST::IfLetExprConseqElse &expr) override;
void visit (AST::Trait &) override;
+ // used to handle Self insertion in TopLevel
+ virtual void maybe_insert_big_self (AST::Impl &) {}
+ virtual void visit_impl_type (AST::Type &type) { visit (type); }
void visit (AST::InherentImpl &) override;
void visit (AST::TraitImpl &) override;
void visit (AST::TypeParam &) override;
+ virtual void visit_extern_crate (AST::ExternCrate &, AST::Crate &, CrateNum);
+ void visit (AST::ExternCrate &) override;
+
// type dec nodes, which visit their fields or variants by default
void visit (AST::StructStruct &) override;
void visit (AST::TupleStruct &) override;
+ void visit (AST::EnumItem &) override;
+ void visit (AST::EnumItemTuple &) override;
+ void visit (AST::EnumItemStruct &) override;
+ void visit (AST::EnumItemDiscriminant &) override;
void visit (AST::Enum &) override;
void visit (AST::Union &) override;
void visit (AST::TypeAlias &) override;
// Visitors that visit their expression node(s)
+ virtual void visit_closure_params (AST::ClosureExpr &);
+ virtual void visit (AST::ClosureExpr &);
void visit (AST::ClosureExprInner &) override;
void visit (AST::ClosureExprInnerTyped &) override;
void visit (AST::MatchExpr &) override;
diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
index 3390f09..4fd1dd2 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
@@ -17,8 +17,11 @@
// <http://www.gnu.org/licenses/>.
#include "rust-early-name-resolver-2.0.h"
-#include "rust-ast-full.h"
+#include "optional.h"
+#include "options.h"
#include "rust-diagnostics.h"
+#include "rust-hir-map.h"
+#include "rust-item.h"
#include "rust-toplevel-name-resolver-2.0.h"
#include "rust-attributes.h"
#include "rust-finalize-imports-2.0.h"
@@ -62,8 +65,9 @@ Early::go (AST::Crate &crate)
// We now proceed with resolving macros, which can be nested in almost any
// items
textual_scope.push ();
- for (auto &item : crate.items)
- item->accept_vis (*this);
+
+ visit (crate);
+
textual_scope.pop ();
}
@@ -74,8 +78,9 @@ Early::resolve_glob_import (NodeId use_dec_id, TopLevel::ImportKind &&glob)
if (!resolved.has_value ())
return false;
- auto result
- = Analysis::Mappings::get ().lookup_ast_module (resolved->get_node_id ());
+ auto result = Analysis::Mappings::get ().lookup_glob_container (
+ resolved->get_node_id ());
+
if (!result)
return false;
@@ -249,7 +254,12 @@ Early::visit (AST::Module &module)
void
Early::visit (AST::MacroInvocation &invoc)
{
- auto path = invoc.get_invoc_data ().get_path ();
+ auto &path = invoc.get_invoc_data ().get_path ();
+
+ // We special case the `offset_of!()` macro if the flag is here, otherwise
+ // we accept whatever `offset_of!()` definition we resolved to.
+ auto resolve_offset_of
+ = flag_assume_builtin_offset_of && (path.as_string () == "offset_of");
if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin)
for (auto &pending_invoc : invoc.get_pending_eager_invocations ())
@@ -272,14 +282,16 @@ Early::visit (AST::MacroInvocation &invoc)
// we won't have changed `definition` from `nullopt` if there are more
// than one segments in our path
if (!definition.has_value ())
- definition = ctx.resolve_path (path.get_segments (), Namespace::Macros);
+ definition = ctx.resolve_path (path, Namespace::Macros);
- // if the definition still does not have a value, then it's an error
+ // if the definition still does not have a value, then it's an error - unless
+ // we should automatically resolve offset_of!() calls
if (!definition.has_value ())
{
- collect_error (Error (invoc.get_locus (), ErrorCode::E0433,
- "could not resolve macro invocation %qs",
- path.as_string ().c_str ()));
+ if (!resolve_offset_of)
+ collect_error (Error (invoc.get_locus (), ErrorCode::E0433,
+ "could not resolve macro invocation %qs",
+ path.as_string ().c_str ()));
return;
}
@@ -314,8 +326,8 @@ Early::visit_attributes (std::vector<AST::Attribute> &attrs)
auto traits = attr.get_traits_to_derive ();
for (auto &trait : traits)
{
- auto definition = ctx.resolve_path (trait.get ().get_segments (),
- Namespace::Macros);
+ auto definition
+ = ctx.resolve_path (trait.get (), Namespace::Macros);
if (!definition.has_value ())
{
// FIXME: Change to proper error message
@@ -337,8 +349,8 @@ Early::visit_attributes (std::vector<AST::Attribute> &attrs)
->lookup_builtin (name)
.is_error ()) // Do not resolve builtins
{
- auto definition = ctx.resolve_path (attr.get_path ().get_segments (),
- Namespace::Macros);
+ auto definition
+ = ctx.resolve_path (attr.get_path (), Namespace::Macros);
if (!definition.has_value ())
{
// FIXME: Change to proper error message
@@ -350,7 +362,8 @@ Early::visit_attributes (std::vector<AST::Attribute> &attrs)
auto pm_def = mappings.lookup_attribute_proc_macro_def (
definition->get_node_id ());
- rust_assert (pm_def.has_value ());
+ if (!pm_def.has_value ())
+ return;
mappings.insert_attribute_proc_macro_invocation (attr.get_path (),
pm_def.value ());
@@ -392,12 +405,12 @@ 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);
+ auto container = Analysis::Mappings::get ().lookup_glob_container (
+ mapping.data.container ().get_node_id ());
+
+ rust_assert (container);
- GlobbingVisitor glob_visitor (ctx);
- glob_visitor.go (module.value ());
+ GlobbingVisitor (ctx).go (container.value ());
}
void
@@ -419,7 +432,8 @@ Early::finalize_rebind_import (const Early::ImportPair &mapping)
declared_name = rebind.get_identifier ().as_string ();
locus = rebind.get_identifier ().get_locus ();
break;
- case AST::UseTreeRebind::NewBindType::NONE: {
+ case AST::UseTreeRebind::NewBindType::NONE:
+ {
const auto &segments = path.get_segments ();
// We don't want to insert `self` with `use module::self`
if (path.get_final_segment ().is_lower_self_seg ())
diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.h b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
index e78bec0..960de0e 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
@@ -83,15 +83,15 @@ public:
return ImportData (Kind::Rebind, std::move (definitions));
}
- static ImportData Glob (Rib::Definition module)
+ static ImportData Glob (Rib::Definition container)
{
- return ImportData (Kind::Glob, module);
+ return ImportData (Kind::Glob, container);
}
- Rib::Definition module () const
+ Rib::Definition container () const
{
rust_assert (kind == Kind::Glob);
- return glob_module;
+ return glob_container;
}
std::vector<std::pair<Rib::Definition, Namespace>> definitions () const
@@ -107,8 +107,8 @@ public:
: kind (kind), resolved_definitions (std::move (definitions))
{}
- ImportData (Kind kind, Rib::Definition module)
- : kind (kind), glob_module (module)
+ ImportData (Kind kind, Rib::Definition container)
+ : kind (kind), glob_container (container)
{}
// TODO: Should this be a union?
@@ -117,7 +117,7 @@ public:
std::vector<std::pair<Rib::Definition, Namespace>> resolved_definitions;
// For Glob
- Rib::Definition glob_module;
+ Rib::Definition glob_container;
};
struct ImportPair
diff --git a/gcc/rust/resolve/rust-early-name-resolver.cc b/gcc/rust/resolve/rust-early-name-resolver.cc
index fc9a26c..7b365ef 100644
--- a/gcc/rust/resolve/rust-early-name-resolver.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver.cc
@@ -205,7 +205,7 @@ EarlyNameResolver::visit (AST::MetaItemLitExpr &)
{}
void
-EarlyNameResolver::visit (AST::MetaItemPathLit &)
+EarlyNameResolver::visit (AST::MetaItemPathExpr &)
{}
void
diff --git a/gcc/rust/resolve/rust-early-name-resolver.h b/gcc/rust/resolve/rust-early-name-resolver.h
index 26fc84d..d3c5225 100644
--- a/gcc/rust/resolve/rust-early-name-resolver.h
+++ b/gcc/rust/resolve/rust-early-name-resolver.h
@@ -142,7 +142,7 @@ private:
virtual void visit (AST::AttrInputLiteral &attr_input);
virtual void visit (AST::AttrInputMacro &attr_input);
virtual void visit (AST::MetaItemLitExpr &meta_item);
- virtual void visit (AST::MetaItemPathLit &meta_item);
+ virtual void visit (AST::MetaItemPathExpr &meta_item);
virtual void visit (AST::StructExprStruct &expr);
virtual void visit (AST::StructExprFieldIdentifier &field);
virtual void visit (AST::StructExprStructBase &expr);
diff --git a/gcc/rust/resolve/rust-finalize-imports-2.0.cc b/gcc/rust/resolve/rust-finalize-imports-2.0.cc
index b0e8651..317acb0 100644
--- a/gcc/rust/resolve/rust-finalize-imports-2.0.cc
+++ b/gcc/rust/resolve/rust-finalize-imports-2.0.cc
@@ -21,19 +21,44 @@
#include "rust-hir-map.h"
#include "rust-name-resolution-context.h"
#include "rust-rib.h"
+#include "rust-system.h"
#include "rust-toplevel-name-resolver-2.0.h"
namespace Rust {
namespace Resolver2_0 {
void
-GlobbingVisitor::go (AST::Module *module)
+GlobbingVisitor::go (AST::Item *container)
{
- for (auto &i : module->get_items ())
+ switch (container->get_item_kind ())
+ {
+ case AST::Item::Kind::Module:
+ visit_module_container (static_cast<AST::Module &> (*container));
+ break;
+ case AST::Item::Kind::Enum:
+ visit_enum_container (static_cast<AST::Enum &> (*container));
+ break;
+ default:
+ rust_unreachable ();
+ }
+}
+
+void
+GlobbingVisitor::visit_module_container (AST::Module &module)
+{
+ for (auto &i : module.get_items ())
visit (i);
}
void
+GlobbingVisitor::visit_enum_container (AST::Enum &item)
+{
+ for (auto &variant : item.get_variants ())
+ ctx.insert_globbed (variant->get_identifier (), variant->get_node_id (),
+ Namespace::Types);
+}
+
+void
GlobbingVisitor::visit (AST::Module &module)
{
if (module.get_visibility ().is_public ())
diff --git a/gcc/rust/resolve/rust-finalize-imports-2.0.h b/gcc/rust/resolve/rust-finalize-imports-2.0.h
index d587a5e..4ae1d6d 100644
--- a/gcc/rust/resolve/rust-finalize-imports-2.0.h
+++ b/gcc/rust/resolve/rust-finalize-imports-2.0.h
@@ -18,6 +18,7 @@
#include "rust-ast.h"
#include "rust-expr.h"
+#include "rust-item.h"
#include "rust-name-resolution-context.h"
#include "rust-toplevel-name-resolver-2.0.h"
#include "rust-early-name-resolver-2.0.h"
@@ -32,7 +33,11 @@ class GlobbingVisitor : public AST::DefaultASTVisitor
public:
GlobbingVisitor (NameResolutionContext &ctx) : ctx (ctx) {}
- void go (AST::Module *module);
+ void go (AST::Item *container);
+
+ void visit_module_container (AST::Module &module);
+ void visit_enum_container (AST::Enum &item);
+
void visit (AST::Module &module) override;
void visit (AST::MacroRulesDefinition &macro) override;
void visit (AST::Function &function) override;
diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h
index 81468e5..75dd873 100644
--- a/gcc/rust/resolve/rust-forever-stack.h
+++ b/gcc/rust/resolve/rust-forever-stack.h
@@ -543,6 +543,13 @@ private:
Node root;
};
+enum class ResolutionMode
+{
+ Normal,
+ FromRoot,
+ FromExtern, // extern prelude
+};
+
template <Namespace N> class ForeverStack
{
public:
@@ -672,14 +679,11 @@ public:
*/
template <typename S>
tl::optional<Rib::Definition> resolve_path (
- const std::vector<S> &segments, bool has_opening_scope_resolution,
+ const std::vector<S> &segments, ResolutionMode mode,
std::function<void (const S &, NodeId)> insert_segment_resolution,
std::vector<Error> &collect_errors);
// FIXME: Documentation
- tl::optional<Resolver::CanonicalPath> to_canonical_path (NodeId id) const;
-
- // FIXME: Documentation
tl::optional<Rib &> to_rib (NodeId rib_id);
tl::optional<const Rib &> to_rib (NodeId rib_id) const;
@@ -739,6 +743,9 @@ private:
tl::optional<Node &> parent; // `None` only if the node is a root
};
+ // private overload which allows specifying a starting point
+ tl::optional<Rib::Definition> get (Node &start, const Identifier &name);
+
/* Should we keep going upon seeing a Rib? */
enum class KeepGoing
{
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx
index 069111ee..1ed87b3 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -291,12 +291,16 @@ ForeverStack<N>::update_cursor (Node &new_cursor)
template <Namespace N>
tl::optional<Rib::Definition>
-ForeverStack<N>::get (const Identifier &name)
+ForeverStack<N>::get (Node &start, const Identifier &name)
{
tl::optional<Rib::Definition> resolved_definition = tl::nullopt;
// TODO: Can we improve the API? have `reverse_iter` return an optional?
- reverse_iter ([&resolved_definition, &name] (Node &current) {
+ reverse_iter (start, [&resolved_definition, &name] (Node &current) {
+ // we can't reference associated types/functions like this
+ if (current.rib.kind == Rib::Kind::TraitOrImpl)
+ return KeepGoing::Yes;
+
auto candidate = current.rib.get (name.as_string ());
return candidate.map_or (
@@ -320,6 +324,13 @@ ForeverStack<N>::get (const Identifier &name)
template <Namespace N>
tl::optional<Rib::Definition>
+ForeverStack<N>::get (const Identifier &name)
+{
+ return get (cursor (), name);
+}
+
+template <Namespace N>
+tl::optional<Rib::Definition>
ForeverStack<N>::get_lang_prelude (const Identifier &name)
{
return lang_prelude.rib.get (name.as_string ());
@@ -542,6 +553,14 @@ ForeverStack<N>::resolve_segments (
bool searched_prelude = false;
while (true)
{
+ if (is_start (iterator, segments)
+ && current_node->rib.kind == Rib::Kind::TraitOrImpl)
+ {
+ // we can't reference associated types/functions like this
+ current_node = &current_node->parent.value ();
+ continue;
+ }
+
// may set the value of child
for (auto &kv : current_node->children)
{
@@ -625,88 +644,158 @@ template <Namespace N>
template <typename S>
tl::optional<Rib::Definition>
ForeverStack<N>::resolve_path (
- const std::vector<S> &segments, bool has_opening_scope_resolution,
+ const std::vector<S> &segments, ResolutionMode mode,
std::function<void (const S &, NodeId)> insert_segment_resolution,
std::vector<Error> &collect_errors)
{
- // TODO: What to do if segments.empty() ?
+ rust_assert (!segments.empty ());
- // handle paths with opening scopes
- std::function<void (void)> cleanup_current = [] () {};
- if (has_opening_scope_resolution)
+ std::reference_wrapper<Node> starting_point = cursor ();
+ switch (mode)
{
- Node *last_current = &cursor_reference.get ();
- if (get_rust_edition () == Edition::E2015)
- cursor_reference = root;
- else
- cursor_reference = extern_prelude;
- cleanup_current
- = [this, last_current] () { cursor_reference = *last_current; };
+ case ResolutionMode::Normal:
+ break; // default
+ case ResolutionMode::FromRoot:
+ starting_point = root;
+ break;
+ case ResolutionMode::FromExtern:
+ starting_point = extern_prelude;
+ break;
+ default:
+ rust_unreachable ();
}
// if there's only one segment, we just use `get`
if (segments.size () == 1)
{
- auto &seg = segments.front ();
- if (auto lang_item = unwrap_segment_get_lang_item (seg))
+ auto &outer_seg = segments.front ();
+ if (auto lang_item = unwrap_segment_get_lang_item (outer_seg))
{
NodeId seg_id = Analysis::Mappings::get ().get_lang_item_node (
lang_item.value ());
- insert_segment_resolution (seg, seg_id);
- cleanup_current ();
+ insert_segment_resolution (outer_seg, seg_id);
// TODO: does NonShadowable matter?
return Rib::Definition::NonShadowable (seg_id);
}
+ auto &seg = unwrap_type_segment (outer_seg);
+
tl::optional<Rib::Definition> res
- = get (unwrap_type_segment (segments.back ()).as_string ());
+ = get (starting_point.get (), seg.as_string ());
if (!res)
- res = get_lang_prelude (
- unwrap_type_segment (segments.back ()).as_string ());
+ res = get_lang_prelude (seg.as_string ());
+
+ if (N == Namespace::Types && !res)
+ {
+ if (seg.is_crate_path_seg ())
+ {
+ insert_segment_resolution (outer_seg, root.id);
+ // TODO: does NonShadowable matter?
+ return Rib::Definition::NonShadowable (root.id);
+ }
+ else if (seg.is_lower_self_seg ())
+ {
+ NodeId id = find_closest_module (starting_point.get ()).id;
+ insert_segment_resolution (outer_seg, id);
+ // TODO: does NonShadowable matter?
+ return Rib::Definition::NonShadowable (id);
+ }
+ else if (seg.is_super_path_seg ())
+ {
+ Node &closest_module
+ = find_closest_module (starting_point.get ());
+ if (closest_module.is_root ())
+ {
+ rust_error_at (seg.get_locus (), ErrorCode::E0433,
+ "too many leading %<super%> keywords");
+ return tl::nullopt;
+ }
+
+ NodeId id
+ = find_closest_module (closest_module.parent.value ()).id;
+ insert_segment_resolution (outer_seg, id);
+ // TODO: does NonShadowable matter?
+ return Rib::Definition::NonShadowable (id);
+ }
+ else
+ {
+ // HACK: check for a module after we check the language prelude
+ for (auto &kv :
+ find_closest_module (starting_point.get ()).children)
+ {
+ auto &link = kv.first;
+
+ if (link.path.map_or (
+ [&seg] (Identifier path) {
+ auto &path_str = path.as_string ();
+ return path_str == seg.as_string ();
+ },
+ false))
+ {
+ insert_segment_resolution (outer_seg, kv.second.id);
+ return Rib::Definition::NonShadowable (kv.second.id);
+ }
+ }
+ }
+ }
if (res && !res->is_ambiguous ())
- insert_segment_resolution (segments.back (), res->get_node_id ());
- cleanup_current ();
+ insert_segment_resolution (outer_seg, res->get_node_id ());
return res;
}
- std::reference_wrapper<Node> starting_point = cursor ();
+ return find_starting_point (segments, starting_point,
+ insert_segment_resolution, collect_errors)
+ .and_then (
+ [this, &segments, &starting_point, &insert_segment_resolution,
+ &collect_errors] (typename std::vector<S>::const_iterator iterator) {
+ return resolve_segments (starting_point.get (), segments, iterator,
+ insert_segment_resolution, collect_errors);
+ })
+ .and_then ([this, &segments, &insert_segment_resolution] (
+ Node &final_node) -> tl::optional<Rib::Definition> {
+ // leave resolution within impl blocks to type checker
+ if (final_node.rib.kind == Rib::Kind::TraitOrImpl)
+ return tl::nullopt;
+
+ auto &seg = unwrap_type_segment (segments.back ());
+ std::string seg_name = seg.as_string ();
+
+ // assuming this can't be a lang item segment
+ tl::optional<Rib::Definition> res
+ = resolve_final_segment (final_node, seg_name,
+ seg.is_lower_self_seg ());
+ // Ok we didn't find it in the rib, Lets try the prelude...
+ if (!res)
+ res = get_lang_prelude (seg_name);
- auto res
- = find_starting_point (segments, starting_point, insert_segment_resolution,
- collect_errors)
- .and_then (
- [this, &segments, &starting_point, &insert_segment_resolution,
- &collect_errors] (typename std::vector<S>::const_iterator iterator) {
- return resolve_segments (starting_point.get (), segments, iterator,
- insert_segment_resolution, collect_errors);
- })
- .and_then ([this, &segments, &insert_segment_resolution] (
- Node &final_node) -> tl::optional<Rib::Definition> {
- // leave resolution within impl blocks to type checker
- if (final_node.rib.kind == Rib::Kind::TraitOrImpl)
- return tl::nullopt;
-
- auto &seg = unwrap_type_segment (segments.back ());
- std::string seg_name = seg.as_string ();
-
- // assuming this can't be a lang item segment
- tl::optional<Rib::Definition> res
- = resolve_final_segment (final_node, seg_name,
- seg.is_lower_self_seg ());
- // Ok we didn't find it in the rib, Lets try the prelude...
- if (!res)
- res = get_lang_prelude (seg_name);
-
- if (res && !res->is_ambiguous ())
- insert_segment_resolution (segments.back (), res->get_node_id ());
-
- return res;
- });
- cleanup_current ();
- return res;
+ if (N == Namespace::Types && !res)
+ {
+ // HACK: check for a module after we check the language prelude
+ for (auto &kv : final_node.children)
+ {
+ auto &link = kv.first;
+
+ if (link.path.map_or (
+ [&seg_name] (Identifier path) {
+ auto &path_str = path.as_string ();
+ return path_str == seg_name;
+ },
+ false))
+ {
+ insert_segment_resolution (segments.back (), kv.second.id);
+ return Rib::Definition::NonShadowable (kv.second.id);
+ }
+ }
+ }
+
+ if (res && !res->is_ambiguous ())
+ insert_segment_resolution (segments.back (), res->get_node_id ());
+
+ return res;
+ });
}
template <Namespace N>
@@ -771,67 +860,6 @@ ForeverStack<N>::dfs (const ForeverStack<N>::Node &starting_point,
}
template <Namespace N>
-tl::optional<Resolver::CanonicalPath>
-ForeverStack<N>::to_canonical_path (NodeId id) const
-{
- // find the id in the current forever stack, starting from the root,
- // performing either a BFS or DFS once the Node containing the ID is found, go
- // back up to the root (parent().parent().parent()...) accumulate link
- // segments reverse them that's your canonical path
-
- return dfs (root, id).map ([this, id] (ConstDfsResult tuple) {
- auto containing_node = tuple.first;
- auto name = tuple.second;
-
- auto segments = std::vector<Resolver::CanonicalPath> ();
-
- reverse_iter (containing_node, [&segments] (const Node &current) {
- if (current.is_root ())
- return KeepGoing::No;
-
- auto children = current.parent.value ().children;
- const Link *outer_link = nullptr;
-
- for (auto &kv : children)
- {
- auto &link = kv.first;
- auto &child = kv.second;
-
- if (current.id == child.id)
- {
- outer_link = &link;
- break;
- }
- }
-
- rust_assert (outer_link);
-
- outer_link->path.map ([&segments, outer_link] (Identifier path) {
- segments.emplace (segments.begin (),
- Resolver::CanonicalPath::new_seg (outer_link->id,
- path.as_string ()));
- });
-
- return KeepGoing::Yes;
- });
-
- auto &mappings = Analysis::Mappings::get ();
- CrateNum crate_num = mappings.lookup_crate_num (root.id).value ();
- auto path = Resolver::CanonicalPath::new_seg (
- root.id, mappings.get_crate_name (crate_num).value ());
- path.set_crate_num (crate_num);
-
- for (const auto &segment : segments)
- path = path.append (segment);
-
- // Finally, append the name
- path = path.append (Resolver::CanonicalPath::new_seg (id, name));
-
- return path;
- });
-}
-
-template <Namespace N>
tl::optional<Rib &>
ForeverStack<N>::dfs_rib (ForeverStack<N>::Node &starting_point, NodeId to_find)
{
diff --git a/gcc/rust/resolve/rust-ice-finalizer.cc b/gcc/rust/resolve/rust-ice-finalizer.cc
index bd4763f..79a06c3 100644
--- a/gcc/rust/resolve/rust-ice-finalizer.cc
+++ b/gcc/rust/resolve/rust-ice-finalizer.cc
@@ -22,12 +22,12 @@ namespace Rust {
namespace Resolver {
void ATTRIBUTE_NORETURN
-funny_ice_text_finalizer (diagnostic_text_output_format &text_output,
- const diagnostic_info *diagnostic,
- diagnostic_t diag_kind)
+funny_ice_text_finalizer (diagnostics::text_sink &text_output,
+ const diagnostics::diagnostic_info *diagnostic,
+ enum diagnostics::kind diag_kind)
{
- gcc_assert (diag_kind == DK_ICE_NOBT);
- default_diagnostic_text_finalizer (text_output, diagnostic, diag_kind);
+ gcc_assert (diag_kind == diagnostics::kind::ice_nobt);
+ diagnostics::default_text_finalizer (text_output, diagnostic, diag_kind);
fnotice (stderr, "You have broken GCC Rust. This is a feature.\n");
exit (ICE_EXIT_CODE);
}
diff --git a/gcc/rust/resolve/rust-ice-finalizer.h b/gcc/rust/resolve/rust-ice-finalizer.h
index 85ab88f..5120176 100644
--- a/gcc/rust/resolve/rust-ice-finalizer.h
+++ b/gcc/rust/resolve/rust-ice-finalizer.h
@@ -55,9 +55,9 @@ namespace Resolver {
the default bug reporting instructions, as there is no bug to report. */
void ATTRIBUTE_NORETURN
-funny_ice_text_finalizer (diagnostic_text_output_format &text_output,
- const diagnostic_info *diagnostic,
- diagnostic_t diag_kind);
+funny_ice_text_finalizer (diagnostics::text_sink &text_output,
+ const diagnostics::diagnostic_info *diagnostic,
+ enum diagnostics::kind diag_kind);
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
index 6ec0422..e39ca15 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
@@ -19,6 +19,7 @@
#include "optional.h"
#include "rust-ast-full.h"
#include "rust-diagnostics.h"
+#include "rust-expr.h"
#include "rust-hir-map.h"
#include "rust-late-name-resolver-2.0.h"
#include "rust-default-resolver.h"
@@ -33,7 +34,9 @@
namespace Rust {
namespace Resolver2_0 {
-Late::Late (NameResolutionContext &ctx) : DefaultResolver (ctx) {}
+Late::Late (NameResolutionContext &ctx)
+ : DefaultResolver (ctx), funny_error (false), block_big_self (false)
+{}
static NodeId
next_node_id ()
@@ -114,8 +117,7 @@ Late::go (AST::Crate &crate)
{
setup_builtin_types ();
- for (auto &item : crate.items)
- item->accept_vis (*this);
+ visit (crate);
}
void
@@ -140,24 +142,21 @@ Late::visit (AST::ForLoopExpr &expr)
ctx.bindings.exit ();
visit (expr.get_iterator_expr ());
- visit (expr.get_loop_label ());
+
+ if (expr.has_loop_label ())
+ visit (expr.get_loop_label ());
+
visit (expr.get_loop_block ());
}
void
-Late::visit (AST::IfLetExpr &expr)
+Late::visit_if_let_patterns (AST::IfLetExpr &expr)
{
- visit_outer_attrs (expr);
+ ctx.bindings.enter (BindingSource::IfLet);
- ctx.bindings.enter (BindingSource::Let);
-
- for (auto &pattern : expr.get_patterns ())
- visit (pattern);
+ DefaultResolver::visit_if_let_patterns (expr);
ctx.bindings.exit ();
-
- visit (expr.get_value_expr ());
- visit (expr.get_if_block ());
}
void
@@ -214,45 +213,80 @@ Late::visit (AST::LetStmt &let)
}
void
-Late::visit (AST::IdentifierPattern &identifier)
+Late::visit (AST::WhileLetLoopExpr &while_let)
+{
+ DefaultASTVisitor::visit_outer_attrs (while_let);
+
+ if (while_let.has_loop_label ())
+ visit (while_let.get_loop_label ());
+
+ // visit expression before pattern
+ // this makes variable shadowing work properly
+ visit (while_let.get_scrutinee_expr ());
+
+ ctx.bindings.enter (BindingSource::WhileLet);
+
+ for (auto &pattern : while_let.get_patterns ())
+ visit (pattern);
+
+ ctx.bindings.exit ();
+
+ visit (while_let.get_loop_block ());
+}
+
+static void
+visit_identifier_as_pattern (NameResolutionContext &ctx,
+ const Identifier &ident, location_t locus,
+ NodeId node_id, bool is_ref, bool is_mut)
{
// do we insert in labels or in values
// but values does not allow shadowing... since functions cannot shadow
// do we insert functions in labels as well?
- if (ctx.bindings.peek ().is_and_bound (identifier.get_ident ()))
+ if (ctx.bindings.peek ().is_and_bound (ident))
{
if (ctx.bindings.peek ().get_source () == BindingSource::Param)
rust_error_at (
- identifier.get_locus (), ErrorCode::E0415,
+ locus, ErrorCode::E0415,
"identifier %qs is bound more than once in the same parameter list",
- identifier.as_string ().c_str ());
+ ident.as_string ().c_str ());
else
rust_error_at (
- identifier.get_locus (), ErrorCode::E0416,
+ locus, ErrorCode::E0416,
"identifier %qs is bound more than once in the same pattern",
- identifier.as_string ().c_str ());
+ ident.as_string ().c_str ());
return;
}
- ctx.bindings.peek ().insert_ident (identifier.get_ident ());
+ ctx.bindings.peek ().insert_ident (ident.as_string (), locus, is_ref, is_mut);
- if (ctx.bindings.peek ().is_or_bound (identifier.get_ident ()))
+ if (ctx.bindings.peek ().is_or_bound (ident))
{
- // FIXME: map usage instead
- std::ignore = ctx.values.insert_shadowable (identifier.get_ident (),
- identifier.get_node_id ());
+ auto res = ctx.values.get (ident);
+ rust_assert (res.has_value () && !res->is_ambiguous ());
+ ctx.map_usage (Usage (node_id), Definition (res->get_node_id ()));
}
else
{
// We do want to ignore duplicated data because some situations rely on
// it.
- std::ignore = ctx.values.insert_shadowable (identifier.get_ident (),
- identifier.get_node_id ());
+ std::ignore = ctx.values.insert_shadowable (ident, node_id);
}
}
void
+Late::visit (AST::IdentifierPattern &identifier)
+{
+ DefaultResolver::visit (identifier);
+
+ visit_identifier_as_pattern (ctx, identifier.get_ident (),
+ identifier.get_locus (),
+ identifier.get_node_id (),
+ identifier.get_is_ref (),
+ identifier.get_is_mut ());
+}
+
+void
Late::visit (AST::AltPattern &pattern)
{
ctx.bindings.peek ().push (Binding::Kind::Or);
@@ -279,9 +313,9 @@ Late::visit_function_params (AST::Function &function)
void
Late::visit (AST::StructPatternFieldIdent &field)
{
- // We do want to ignore duplicated data because some situations rely on it.
- std::ignore = ctx.values.insert_shadowable (field.get_identifier (),
- field.get_node_id ());
+ visit_identifier_as_pattern (ctx, field.get_identifier (), field.get_locus (),
+ field.get_node_id (), field.is_ref (),
+ field.is_mut ());
}
void
@@ -375,8 +409,9 @@ Late::visit (AST::IdentifierExpr &expr)
}
else if (funny_error)
{
- diagnostic_text_finalizer (global_dc) = Resolver::funny_ice_text_finalizer;
- emit_diagnostic (DK_ICE_NOBT, expr.get_locus (), -1,
+ diagnostics::text_finalizer (global_dc)
+ = Resolver::funny_ice_text_finalizer;
+ emit_diagnostic (diagnostics::kind::ice_nobt, expr.get_locus (), -1,
"are you trying to break %s? how dare you?",
expr.as_string ().c_str ());
}
@@ -477,6 +512,16 @@ Late::visit (AST::PathInExpression &expr)
}
void
+Late::visit_impl_type (AST::Type &type)
+{
+ // TODO: does this have to handle reentrancy?
+ rust_assert (!block_big_self);
+ block_big_self = true;
+ visit (type);
+ block_big_self = false;
+}
+
+void
Late::visit (AST::TypePath &type)
{
// should we add type path resolution in `ForeverStack` directly? Since it's
@@ -486,6 +531,16 @@ Late::visit (AST::TypePath &type)
DefaultResolver::visit (type);
+ // prevent "impl Self {}" and similar
+ if (type.get_segments ().size () == 1
+ && !type.get_segments ().front ()->is_lang_item ()
+ && type.get_segments ().front ()->is_big_self_seg () && block_big_self)
+ {
+ rust_error_at (type.get_locus (),
+ "%<Self%> is not valid in the self type of an impl block");
+ return;
+ }
+
// this *should* mostly work
// TODO: make sure typepath-like path resolution (?) is working
auto resolved = ctx.resolve_path (type, Namespace::Types);
@@ -493,15 +548,16 @@ Late::visit (AST::TypePath &type)
if (!resolved.has_value ())
{
if (!ctx.lookup (type.get_segments ().front ()->get_node_id ()))
- rust_error_at (type.get_locus (), "could not resolve type path %qs",
- type.as_string ().c_str ());
+ rust_error_at (type.get_locus (), ErrorCode::E0412,
+ "could not resolve type path %qs",
+ type.make_debug_string ().c_str ());
return;
}
if (resolved->is_ambiguous ())
{
rust_error_at (type.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
- type.as_string ().c_str ());
+ type.make_debug_string ().c_str ());
return;
}
@@ -518,6 +574,62 @@ Late::visit (AST::TypePath &type)
}
void
+Late::visit (AST::Visibility &vis)
+{
+ if (!vis.has_path ())
+ return;
+
+ AST::SimplePath &path = vis.get_path ();
+
+ rust_assert (path.get_segments ().size ());
+ auto &first_seg = path.get_segments ()[0];
+
+ auto mode = ResolutionMode::Normal;
+
+ if (path.has_opening_scope_resolution ())
+ {
+ if (get_rust_edition () == Edition::E2015)
+ mode = ResolutionMode::FromRoot;
+ else
+ mode = ResolutionMode::FromExtern;
+ }
+ else if (!first_seg.is_crate_path_seg () && !first_seg.is_super_path_seg ()
+ && !first_seg.is_lower_self_seg ())
+ {
+ if (get_rust_edition () == Edition::E2015)
+ {
+ mode = ResolutionMode::FromRoot;
+ }
+ else
+ {
+ rust_error_at (path.get_locus (),
+ "relative paths are not supported in visibilities in "
+ "2018 edition or later");
+ return;
+ }
+ }
+
+ auto res = ctx.resolve_path (path.get_segments (), mode, Namespace::Types);
+
+ if (!res.has_value ())
+ {
+ rust_error_at (path.get_locus (), ErrorCode::E0433,
+ "could not resolve path %qs", path.as_string ().c_str ());
+ return;
+ }
+
+ // TODO: is this possible?
+ if (res->is_ambiguous ())
+ {
+ rust_error_at (path.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
+ path.as_string ().c_str ());
+ return;
+ }
+
+ ctx.map_usage (Usage (path.get_node_id ()), Definition (res->get_node_id ()));
+}
+
+void
Late::visit (AST::Trait &trait)
{
// kind of weird how this is done
@@ -531,13 +643,6 @@ Late::visit (AST::Trait &trait)
}
void
-Late::visit (AST::StructStruct &s)
-{
- auto s_vis = [this, &s] () { AST::DefaultASTVisitor::visit (s); };
- ctx.scoped (Rib::Kind::Item, s.get_node_id (), s_vis);
-}
-
-void
Late::visit (AST::StructExprStruct &s)
{
visit_outer_attrs (s);
@@ -613,51 +718,27 @@ Late::visit (AST::GenericArg &arg)
DefaultResolver::visit (arg);
}
-template <class Closure>
-static void
-add_captures (Closure &closure, NameResolutionContext &ctx)
-{
- auto vals = ctx.values.peek ().get_values ();
- for (auto &val : vals)
- {
- ctx.mappings.add_capture (closure.get_node_id (),
- val.second.get_node_id ());
- }
-}
-
void
-Late::visit (AST::ClosureExprInner &closure)
+Late::visit_closure_params (AST::ClosureExpr &closure)
{
- add_captures (closure, ctx);
-
- visit_outer_attrs (closure);
-
ctx.bindings.enter (BindingSource::Param);
- for (auto &param : closure.get_params ())
- visit (param);
+ DefaultResolver::visit_closure_params (closure);
ctx.bindings.exit ();
-
- visit (closure.get_definition_expr ());
}
void
-Late::visit (AST::ClosureExprInnerTyped &closure)
+Late::visit (AST::ClosureExpr &expr)
{
- add_captures (closure, ctx);
-
- visit_outer_attrs (closure);
-
- ctx.bindings.enter (BindingSource::Param);
-
- for (auto &param : closure.get_params ())
- visit (param);
-
- ctx.bindings.exit ();
+ // add captures
+ auto vals = ctx.values.peek ().get_values ();
+ for (auto &val : vals)
+ {
+ ctx.mappings.add_capture (expr.get_node_id (), val.second.get_node_id ());
+ }
- visit (closure.get_return_type ());
- visit (closure.get_definition_block ());
+ DefaultResolver::visit (expr);
}
} // namespace Resolver2_0
diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
index 171d9bf..95540e3 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
@@ -42,6 +42,7 @@ public:
// some more label declarations
void visit (AST::LetStmt &) override;
+ void visit (AST::WhileLetLoopExpr &) override;
// TODO: Do we need this?
// void visit (AST::Method &) override;
void visit (AST::IdentifierPattern &) override;
@@ -50,7 +51,7 @@ public:
void visit (AST::SelfParam &) override;
void visit (AST::MatchArm &) override;
void visit (AST::ForLoopExpr &) override;
- void visit (AST::IfLetExpr &) override;
+ void visit_if_let_patterns (AST::IfLetExpr &) override;
// resolutions
void visit (AST::IdentifierExpr &) override;
@@ -59,16 +60,17 @@ public:
void visit (AST::ContinueExpr &) override;
void visit (AST::LoopLabel &) override;
void visit (AST::PathInExpression &) override;
+ void visit_impl_type (AST::Type &) override;
void visit (AST::TypePath &) override;
+ void visit (AST::Visibility &) override;
void visit (AST::Trait &) override;
void visit (AST::StructExprStruct &) override;
void visit (AST::StructExprStructBase &) override;
void visit (AST::StructExprStructFields &) override;
- void visit (AST::StructStruct &) override;
void visit (AST::GenericArgs &) override;
void visit (AST::GenericArg &);
- void visit (AST::ClosureExprInner &) override;
- void visit (AST::ClosureExprInnerTyped &) override;
+ void visit_closure_params (AST::ClosureExpr &) override;
+ void visit (AST::ClosureExpr &) override;
private:
void resolve_label (AST::Lifetime &lifetime);
@@ -77,6 +79,9 @@ private:
void setup_builtin_types ();
bool funny_error;
+
+ /* used to prevent "impl Self {}", "impl (Self, i32) {}", etc */
+ bool block_big_self;
};
// TODO: Add missing mappings and data structures
diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc b/gcc/rust/resolve/rust-name-resolution-context.cc
index f098e48..1b84f1d 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.cc
+++ b/gcc/rust/resolve/rust-name-resolution-context.cc
@@ -33,7 +33,8 @@ BindingLayer::bind_test (Identifier ident, Binding::Kind kind)
{
for (auto &bind : bindings)
{
- if (bind.set.find (ident) != bind.set.cend () && bind.kind == kind)
+ if (bind.idents.find (ident.as_string ()) != bind.idents.cend ()
+ && bind.kind == kind)
{
return true;
}
@@ -60,20 +61,66 @@ BindingLayer::is_or_bound (Identifier ident)
}
void
-BindingLayer::insert_ident (Identifier ident)
+BindingLayer::insert_ident (std::string ident, location_t locus, bool is_ref,
+ bool is_mut)
{
- bindings.back ().set.insert (ident);
+ bindings.back ().idents.emplace (
+ std::move (ident), std::make_pair (locus, IdentifierMode (is_ref, is_mut)));
}
void
BindingLayer::merge ()
{
- auto last_binding = bindings.back ();
+ auto last_binding = std::move (bindings.back ());
bindings.pop_back ();
- for (auto &value : last_binding.set)
+
+ if (bindings.back ().has_expected_bindings)
+ {
+ for (auto &value : bindings.back ().idents)
+ {
+ auto ident = value.first;
+ if (last_binding.idents.find (ident) == last_binding.idents.end ())
+ {
+ location_t locus = value.second.first;
+ rust_error_at (locus, ErrorCode::E0408,
+ "variable %qs is not bound in all patterns",
+ ident.c_str ());
+ }
+ }
+ }
+
+ for (auto &value : last_binding.idents)
{
- bindings.back ().set.insert (value);
+ auto res = bindings.back ().idents.emplace (value);
+ if (res.second)
+ {
+ if (bindings.back ().has_expected_bindings)
+ {
+ auto &ident = value.first;
+ location_t locus = value.second.first;
+ rust_error_at (locus, ErrorCode::E0408,
+ "variable %qs is not bound in all patterns",
+ ident.c_str ());
+ }
+ }
+ else
+ {
+ auto this_mode = value.second.second;
+ auto other_mode = res.first->second.second;
+ if (this_mode != other_mode)
+ {
+ auto &ident = value.first;
+ location_t locus = value.second.first;
+ rust_error_at (locus, ErrorCode::E0409,
+ "variable %qs is bound inconsistently across "
+ "pattern alternatives",
+ ident.c_str ());
+ }
+ }
}
+
+ if (bindings.back ().kind == Binding::Kind::Or)
+ bindings.back ().has_expected_bindings = true;
}
BindingSource
@@ -82,8 +129,63 @@ BindingLayer::get_source () const
return source;
}
+Resolver::CanonicalPath
+CanonicalPathRecordCrateRoot::as_path (const NameResolutionContext &)
+{
+ auto ret = Resolver::CanonicalPath::new_seg (node_id, seg);
+ ret.set_crate_num (crate_num);
+ return ret;
+}
+
+Resolver::CanonicalPath
+CanonicalPathRecordNormal::as_path (const NameResolutionContext &ctx)
+{
+ auto parent_path = get_parent ().as_path (ctx);
+ return parent_path.append (Resolver::CanonicalPath::new_seg (node_id, seg));
+}
+
+Resolver::CanonicalPath
+CanonicalPathRecordLookup::as_path (const NameResolutionContext &ctx)
+{
+ if (!cache)
+ {
+ auto res = ctx.lookup (lookup_id).and_then (
+ [&ctx] (NodeId id) { return ctx.canonical_ctx.get_record_opt (id); });
+
+ if (!res)
+ {
+ // HACK: use a dummy value
+ // this should bring us roughly to parity with nr1.0
+ // since nr1.0 doesn't seem to handle canonical paths for generics
+ // quite right anyways
+ return Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, "XXX");
+ }
+
+ cache = res.value ();
+ }
+ return cache->as_path (ctx);
+}
+
+Resolver::CanonicalPath
+CanonicalPathRecordImpl::as_path (const NameResolutionContext &ctx)
+{
+ auto parent_path = get_parent ().as_path (ctx);
+ return parent_path.append (
+ Resolver::CanonicalPath::inherent_impl_seg (impl_id,
+ type_record.as_path (ctx)));
+}
+
+Resolver::CanonicalPath
+CanonicalPathRecordTraitImpl::as_path (const NameResolutionContext &ctx)
+{
+ auto parent_path = get_parent ().as_path (ctx);
+ return parent_path.append (
+ Resolver::CanonicalPath::trait_impl_projection_seg (
+ impl_id, trait_path_record.as_path (ctx), type_record.as_path (ctx)));
+}
+
NameResolutionContext::NameResolutionContext ()
- : mappings (Analysis::Mappings::get ())
+ : mappings (Analysis::Mappings::get ()), canonical_ctx (*this)
{}
tl::expected<NodeId, DuplicateNameError>
diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h
index 19ba750..558b3ca 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -24,6 +24,7 @@
#include "rust-hir-map.h"
#include "rust-rib.h"
#include "rust-stacked-contexts.h"
+#include "rust-item.h"
namespace Rust {
namespace Resolver2_0 {
@@ -157,6 +158,22 @@ public:
NodeId id;
};
+struct IdentifierMode
+{
+ bool is_ref;
+ bool is_mut;
+
+ IdentifierMode (bool is_ref, bool is_mut) : is_ref (is_ref), is_mut (is_mut)
+ {}
+
+ bool operator== (const IdentifierMode &other)
+ {
+ return other.is_ref == is_ref && other.is_mut == is_mut;
+ }
+
+ bool operator!= (const IdentifierMode &other) { return !(*this == other); }
+};
+
struct Binding
{
enum class Kind
@@ -165,9 +182,12 @@ struct Binding
Or,
} kind;
- std::unordered_set<Identifier> set;
+ // used to check the correctness of or-bindings
+ bool has_expected_bindings;
- Binding (Binding::Kind kind) : kind (kind) {}
+ std::unordered_map<std::string, std::pair<location_t, IdentifierMode>> idents;
+
+ Binding (Binding::Kind kind) : kind (kind), has_expected_bindings (false) {}
};
/**
@@ -177,6 +197,8 @@ enum class BindingSource
{
Match,
Let,
+ IfLet,
+ WhileLet,
For,
/* Closure param or function param */
Param
@@ -206,13 +228,256 @@ public:
*/
bool is_or_bound (Identifier ident);
- void insert_ident (Identifier ident);
+ void insert_ident (std::string ident, location_t locus, bool is_ref,
+ bool is_mut);
void merge ();
BindingSource get_source () const;
};
+class NameResolutionContext;
+/*
+ * Used to handle canonical paths
+ * Similar to ForeverStack, but namespace independent and more specialized
+ */
+class CanonicalPathRecord
+{
+public:
+ virtual Resolver::CanonicalPath as_path (const NameResolutionContext &) = 0;
+
+ virtual bool is_root () const = 0;
+
+ virtual ~CanonicalPathRecord () = default;
+};
+
+class CanonicalPathRecordWithParent : public CanonicalPathRecord
+{
+public:
+ CanonicalPathRecordWithParent (CanonicalPathRecord &parent) : parent (&parent)
+ {}
+
+ CanonicalPathRecord &get_parent () { return *parent; }
+
+ bool is_root () const override final { return false; }
+
+private:
+ CanonicalPathRecord *parent;
+};
+
+class CanonicalPathRecordCrateRoot : public CanonicalPathRecord
+{
+public:
+ CanonicalPathRecordCrateRoot (NodeId node_id, std::string seg)
+ : node_id (node_id), seg (std::move (seg))
+ {
+ rust_assert (Analysis::Mappings::get ().node_is_crate (node_id));
+ crate_num = Analysis::Mappings::get ().lookup_crate_num (node_id).value ();
+ }
+
+ Resolver::CanonicalPath as_path (const NameResolutionContext &) override;
+
+ bool is_root () const override final { return true; }
+
+private:
+ NodeId node_id;
+ CrateNum crate_num;
+ std::string seg;
+};
+
+class CanonicalPathRecordNormal : public CanonicalPathRecordWithParent
+{
+public:
+ CanonicalPathRecordNormal (CanonicalPathRecord &parent, NodeId node_id,
+ std::string seg)
+ : CanonicalPathRecordWithParent (parent), node_id (node_id),
+ seg (std::move (seg))
+ {
+ rust_assert (!Analysis::Mappings::get ().node_is_crate (node_id));
+ }
+
+ Resolver::CanonicalPath as_path (const NameResolutionContext &) override;
+
+private:
+ NodeId node_id;
+ std::string seg;
+};
+
+class CanonicalPathRecordLookup : public CanonicalPathRecord
+{
+public:
+ CanonicalPathRecordLookup (NodeId lookup_id)
+ : lookup_id (lookup_id), cache (nullptr)
+ {}
+
+ Resolver::CanonicalPath as_path (const NameResolutionContext &) override;
+
+ bool is_root () const override final { return true; }
+
+private:
+ NodeId lookup_id;
+ CanonicalPathRecord *cache;
+};
+
+class CanonicalPathRecordImpl : public CanonicalPathRecordWithParent
+{
+public:
+ CanonicalPathRecordImpl (CanonicalPathRecord &parent, NodeId impl_id,
+ NodeId type_id)
+ : CanonicalPathRecordWithParent (parent), impl_id (impl_id),
+ type_record (type_id)
+ {}
+
+ Resolver::CanonicalPath as_path (const NameResolutionContext &) override;
+
+private:
+ NodeId impl_id;
+ CanonicalPathRecordLookup type_record;
+};
+
+class CanonicalPathRecordTraitImpl : public CanonicalPathRecordWithParent
+{
+public:
+ CanonicalPathRecordTraitImpl (CanonicalPathRecord &parent, NodeId impl_id,
+ NodeId type_id, NodeId trait_path_id)
+ : CanonicalPathRecordWithParent (parent), impl_id (impl_id),
+ type_record (type_id), trait_path_record (trait_path_id)
+ {}
+
+ Resolver::CanonicalPath as_path (const NameResolutionContext &) override;
+
+private:
+ NodeId impl_id;
+ CanonicalPathRecordLookup type_record;
+ CanonicalPathRecordLookup trait_path_record;
+};
+
+class CanonicalPathCtx
+{
+public:
+ CanonicalPathCtx (const NameResolutionContext &ctx)
+ : current_record (nullptr), nr_ctx (&ctx)
+ {}
+
+ Resolver::CanonicalPath get_path (NodeId id) const
+ {
+ return get_record (id).as_path (*nr_ctx);
+ }
+
+ CanonicalPathRecord &get_record (NodeId id) const
+ {
+ auto it = records.find (id);
+ rust_assert (it != records.end ());
+ return *it->second;
+ }
+
+ tl::optional<CanonicalPathRecord *> get_record_opt (NodeId id) const
+ {
+ auto it = records.find (id);
+ if (it == records.end ())
+ return tl::nullopt;
+ else
+ return it->second.get ();
+ }
+
+ void insert_record (NodeId id, const Identifier &ident)
+ {
+ insert_record (id, ident.as_string ());
+ }
+
+ void insert_record (NodeId id, std::string seg)
+ {
+ rust_assert (current_record != nullptr);
+
+ auto it = records.find (id);
+ if (it == records.end ())
+ {
+ auto record = new CanonicalPathRecordNormal (*current_record, id,
+ std::move (seg));
+ bool ok
+ = records.emplace (id, std::unique_ptr<CanonicalPathRecord> (record))
+ .second;
+ rust_assert (ok);
+ }
+ }
+
+ template <typename F> void scope (NodeId id, const Identifier &ident, F &&f)
+ {
+ scope (id, ident.as_string (), std::forward<F> (f));
+ }
+
+ template <typename F> void scope (NodeId id, std::string seg, F &&f)
+ {
+ rust_assert (current_record != nullptr);
+
+ scope_inner (id, std::forward<F> (f), [this, id, &seg] () {
+ return new CanonicalPathRecordNormal (*current_record, id,
+ std::move (seg));
+ });
+ }
+
+ template <typename F> void scope_impl (AST::InherentImpl &impl, F &&f)
+ {
+ rust_assert (current_record != nullptr);
+
+ NodeId id = impl.get_node_id ();
+ scope_inner (id, std::forward<F> (f), [this, id, &impl] () {
+ return new CanonicalPathRecordImpl (*current_record, id,
+ impl.get_type ().get_node_id ());
+ });
+ }
+
+ template <typename F> void scope_impl (AST::TraitImpl &impl, F &&f)
+ {
+ rust_assert (current_record != nullptr);
+
+ NodeId id = impl.get_node_id ();
+ scope_inner (id, std::forward<F> (f), [this, id, &impl] () {
+ return new CanonicalPathRecordTraitImpl (
+ *current_record, id, impl.get_type ().get_node_id (),
+ impl.get_trait_path ().get_node_id ());
+ });
+ }
+
+ template <typename F>
+ void scope_crate (NodeId node_id, std::string crate_name, F &&f)
+ {
+ scope_inner (node_id, std::forward<F> (f), [node_id, &crate_name] () {
+ return new CanonicalPathRecordCrateRoot (node_id, std::move (crate_name));
+ });
+ }
+
+private:
+ template <typename FCreate, typename FCallback>
+ void scope_inner (NodeId id, FCallback &&f_callback, FCreate &&f_create)
+ {
+ auto it = records.find (id);
+ if (it == records.end ())
+ {
+ CanonicalPathRecord *record = std::forward<FCreate> (f_create) ();
+ it = records.emplace (id, std::unique_ptr<CanonicalPathRecord> (record))
+ .first;
+ }
+
+ rust_assert (it->second->is_root ()
+ || &static_cast<CanonicalPathRecordWithParent &> (*it->second)
+ .get_parent ()
+ == current_record);
+
+ CanonicalPathRecord *stash = it->second.get ();
+ std::swap (stash, current_record);
+
+ std::forward<FCallback> (f_callback) ();
+
+ std::swap (stash, current_record);
+ }
+
+ std::unordered_map<NodeId, std::unique_ptr<CanonicalPathRecord>> records;
+ CanonicalPathRecord *current_record;
+
+ const NameResolutionContext *nr_ctx;
+};
+
// Now our resolver, which keeps track of all the `ForeverStack`s we could want
class NameResolutionContext
{
@@ -271,16 +536,22 @@ public:
Analysis::Mappings &mappings;
StackedContexts<BindingLayer> bindings;
+ CanonicalPathCtx canonical_ctx;
+
// TODO: Rename
// TODO: Use newtype pattern for Usage and Definition
void map_usage (Usage usage, Definition definition);
tl::optional<NodeId> lookup (NodeId usage) const;
+ Resolver::CanonicalPath to_canonical_path (NodeId id) const
+ {
+ return canonical_ctx.get_path (id);
+ }
+
template <typename S>
tl::optional<Rib::Definition>
- resolve_path (const std::vector<S> &segments,
- bool has_opening_scope_resolution,
+ resolve_path (const std::vector<S> &segments, ResolutionMode mode,
std::vector<Error> &collect_errors, Namespace ns)
{
std::function<void (const S &, NodeId)> insert_segment_resolution
@@ -292,17 +563,17 @@ public:
switch (ns)
{
case Namespace::Values:
- return values.resolve_path (segments, has_opening_scope_resolution,
- insert_segment_resolution, collect_errors);
+ return values.resolve_path (segments, mode, insert_segment_resolution,
+ collect_errors);
case Namespace::Types:
- return types.resolve_path (segments, has_opening_scope_resolution,
- insert_segment_resolution, collect_errors);
+ return types.resolve_path (segments, mode, insert_segment_resolution,
+ collect_errors);
case Namespace::Macros:
- return macros.resolve_path (segments, has_opening_scope_resolution,
- insert_segment_resolution, collect_errors);
+ return macros.resolve_path (segments, mode, insert_segment_resolution,
+ collect_errors);
case Namespace::Labels:
- return labels.resolve_path (segments, has_opening_scope_resolution,
- insert_segment_resolution, collect_errors);
+ return labels.resolve_path (segments, mode, insert_segment_resolution,
+ collect_errors);
default:
rust_unreachable ();
}
@@ -310,8 +581,7 @@ public:
template <typename S, typename... Args>
tl::optional<Rib::Definition>
- resolve_path (const std::vector<S> &segments,
- bool has_opening_scope_resolution,
+ resolve_path (const std::vector<S> &segments, ResolutionMode mode,
tl::optional<std::vector<Error> &> collect_errors,
Namespace ns_first, Args... ns_args)
{
@@ -320,8 +590,7 @@ public:
for (auto ns : namespaces)
{
std::vector<Error> collect_errors_inner;
- if (auto ret = resolve_path (segments, has_opening_scope_resolution,
- collect_errors_inner, ns))
+ if (auto ret = resolve_path (segments, mode, collect_errors_inner, ns))
return ret;
if (!collect_errors_inner.empty ())
{
@@ -343,52 +612,68 @@ public:
return tl::nullopt;
}
- template <typename... Args>
+ template <typename S, typename... Args>
tl::optional<Rib::Definition>
- resolve_path (const AST::SimplePath &path,
+ resolve_path (const std::vector<S> &path_segments,
+ bool has_opening_scope_resolution,
tl::optional<std::vector<Error> &> collect_errors,
Namespace ns_first, Args... ns_args)
{
- return resolve_path (path.get_segments (),
- path.has_opening_scope_resolution (), collect_errors,
- ns_first, ns_args...);
+ auto mode = ResolutionMode::Normal;
+ if (has_opening_scope_resolution)
+ {
+ if (get_rust_edition () == Edition::E2015)
+ mode = ResolutionMode::FromRoot;
+ else
+ mode = ResolutionMode::FromExtern;
+ }
+ return resolve_path (path_segments, mode, collect_errors, ns_first,
+ ns_args...);
}
- template <typename... Args>
+ template <typename S, typename... Args>
tl::optional<Rib::Definition>
- resolve_path (const AST::PathInExpression &path,
- tl::optional<std::vector<Error> &> collect_errors,
- Namespace ns_first, Args... ns_args)
+ resolve_path (const std::vector<S> &path_segments,
+ bool has_opening_scope_resolution, Namespace ns_first,
+ Args... ns_args)
{
- return resolve_path (path.get_segments (), path.opening_scope_resolution (),
- collect_errors, ns_first, ns_args...);
+ return resolve_path (path_segments, has_opening_scope_resolution,
+ tl::nullopt, ns_first, ns_args...);
}
- template <typename... Args>
+ template <typename S, typename... Args>
tl::optional<Rib::Definition>
- resolve_path (const AST::TypePath &path,
- tl::optional<std::vector<Error> &> collect_errors,
+ resolve_path (const std::vector<S> &path_segments, ResolutionMode mode,
Namespace ns_first, Args... ns_args)
{
+ return resolve_path (path_segments, mode, tl::nullopt, ns_first,
+ ns_args...);
+ }
+
+ template <typename... Args>
+ tl::optional<Rib::Definition> resolve_path (const AST::SimplePath &path,
+ Args &&...args)
+ {
return resolve_path (path.get_segments (),
- path.has_opening_scope_resolution_op (),
- collect_errors, ns_first, ns_args...);
+ path.has_opening_scope_resolution (),
+ std::forward<Args> (args)...);
}
- template <typename P, typename... Args>
- tl::optional<Rib::Definition> resolve_path (const P &path, Namespace ns_first,
- Args... ns_args)
+ template <typename... Args>
+ tl::optional<Rib::Definition> resolve_path (const AST::PathInExpression &path,
+ Args &&...args)
{
- return resolve_path (path, tl::nullopt, ns_first, ns_args...);
+ return resolve_path (path.get_segments (), path.opening_scope_resolution (),
+ std::forward<Args> (args)...);
}
- template <typename P, typename... Args>
- tl::optional<Rib::Definition>
- resolve_path (const P &path_segments, bool has_opening_scope_resolution,
- Namespace ns_first, Args... ns_args)
+ template <typename... Args>
+ tl::optional<Rib::Definition> resolve_path (const AST::TypePath &path,
+ Args &&...args)
{
- return resolve_path (path_segments, has_opening_scope_resolution,
- tl::nullopt, ns_first, ns_args...);
+ return resolve_path (path.get_segments (),
+ path.has_opening_scope_resolution_op (),
+ std::forward<Args> (args)...);
}
private:
diff --git a/gcc/rust/resolve/rust-rib.h b/gcc/rust/resolve/rust-rib.h
index c498328..140c991 100644
--- a/gcc/rust/resolve/rust-rib.h
+++ b/gcc/rust/resolve/rust-rib.h
@@ -188,6 +188,8 @@ public:
* restriction that you cannot `use` items from the Prelude
*/
Prelude,
+ /* Generic rib, used to store generics */
+ Generics,
} kind;
static std::string kind_to_string (Rib::Kind kind)
@@ -214,9 +216,13 @@ public:
return "Forward type param ban";
case Rib::Kind::ConstParamType:
return "Const Param Type";
- default:
- rust_unreachable ();
+ case Kind::Prelude:
+ return "Prelude";
+ case Kind::Generics:
+ return "Generics";
}
+
+ rust_unreachable ();
}
Rib (Kind kind);
diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
index 2f036fe..0930f96 100644
--- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
@@ -95,41 +95,17 @@ TopLevel::go (AST::Crate &crate)
// times in a row in a fixed-point fashion, so it would make the code
// responsible for this ugly and perfom a lot of error checking.
- for (auto &item : crate.items)
- item->accept_vis (*this);
+ visit (crate);
}
void
TopLevel::visit (AST::Module &module)
{
- insert_or_error_out (module.get_name (), module, Namespace::Types);
-
- // Parse the module's items if they haven't been expanded and the file
- // should be parsed (i.e isn't hidden behind an untrue or impossible cfg
- // directive
- // TODO: make sure this is right
- // TODO: avoid loading items if cfg attributes are present?
- // might not be needed if this runs after early resolution?
- // This was copied from the old early resolver method
- // 'accumulate_escaped_macros'
- if (module.get_kind () == AST::Module::UNLOADED)
- {
- module.load_items ();
-
- // If the module was previously unloaded, then we don't want to visit it
- // this time around as the CfgStrip hasn't run on its inner items yet.
- // Skip it for now, mark the visitor as dirty and try again
-
- dirty = true;
-
- return;
- }
-
DefaultResolver::visit (module);
- if (Analysis::Mappings::get ().lookup_ast_module (module.get_node_id ())
+ if (Analysis::Mappings::get ().lookup_glob_container (module.get_node_id ())
== tl::nullopt)
- Analysis::Mappings::get ().insert_ast_module (&module);
+ Analysis::Mappings::get ().insert_glob_container (&module);
}
void
@@ -141,33 +117,10 @@ TopLevel::visit (AST::Trait &trait)
}
void
-TopLevel::visit (AST::InherentImpl &impl)
-{
- auto inner_fn = [this, &impl] () {
- insert_or_error_out (Identifier ("Self", impl.get_type ().get_locus ()),
- impl.get_type (), Namespace::Types);
-
- // We do want to visit with the default visitor instead of default resolver
- // because we don't want to insert the scope twice.
- AST::DefaultASTVisitor::visit (impl);
- };
-
- ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn);
-}
-
-void
-TopLevel::visit (AST::TraitImpl &impl)
+TopLevel::maybe_insert_big_self (AST::Impl &impl)
{
- auto inner_fn = [this, &impl] () {
- insert_or_error_out (Identifier ("Self", impl.get_type ().get_locus ()),
- impl.get_type (), Namespace::Types);
-
- // We do want to visit using the default visitor instead of default resolver
- // because we don't want to insert the scope twice.
- AST::DefaultASTVisitor::visit (impl);
- };
-
- ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn);
+ insert_or_error_out (Identifier ("Self", impl.get_type ().get_locus ()),
+ impl.get_type (), Namespace::Types);
}
void
@@ -197,19 +150,10 @@ insert_macros (std::vector<PROC_MACRO> &macros, NameResolutionContext &ctx)
}
void
-TopLevel::visit (AST::ExternCrate &crate)
+TopLevel::visit_extern_crate (AST::ExternCrate &extern_crate, AST::Crate &crate,
+ CrateNum num)
{
auto &mappings = Analysis::Mappings::get ();
- auto num_opt = mappings.lookup_crate_name (crate.get_referenced_crate ());
-
- if (!num_opt)
- {
- rust_error_at (crate.get_locus (), "unknown crate %qs",
- crate.get_referenced_crate ().c_str ());
- return;
- }
-
- CrateNum num = *num_opt;
auto attribute_macros = mappings.lookup_attribute_proc_macros (num);
@@ -217,34 +161,27 @@ TopLevel::visit (AST::ExternCrate &crate)
auto derive_macros = mappings.lookup_derive_proc_macros (num);
- auto sub_visitor = [&] () {
- // TODO: Find a way to keep this part clean without the double dispatch.
- if (derive_macros.has_value ())
- {
- insert_macros (derive_macros.value (), ctx);
- for (auto &macro : derive_macros.value ())
- mappings.insert_derive_proc_macro_def (macro);
- }
- if (attribute_macros.has_value ())
- {
- insert_macros (attribute_macros.value (), ctx);
- for (auto &macro : attribute_macros.value ())
- mappings.insert_attribute_proc_macro_def (macro);
- }
- if (bang_macros.has_value ())
- {
- insert_macros (bang_macros.value (), ctx);
- for (auto &macro : bang_macros.value ())
- mappings.insert_bang_proc_macro_def (macro);
- }
- };
+ // TODO: Find a way to keep this part clean without the double dispatch.
+ if (derive_macros.has_value ())
+ {
+ insert_macros (derive_macros.value (), ctx);
+ for (auto &macro : derive_macros.value ())
+ mappings.insert_derive_proc_macro_def (macro);
+ }
+ if (attribute_macros.has_value ())
+ {
+ insert_macros (attribute_macros.value (), ctx);
+ for (auto &macro : attribute_macros.value ())
+ mappings.insert_attribute_proc_macro_def (macro);
+ }
+ if (bang_macros.has_value ())
+ {
+ insert_macros (bang_macros.value (), ctx);
+ for (auto &macro : bang_macros.value ())
+ mappings.insert_bang_proc_macro_def (macro);
+ }
- if (crate.has_as_clause ())
- ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor,
- crate.get_as_clause ());
- else
- ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor,
- crate.get_referenced_crate ());
+ visit (crate);
}
static bool
@@ -321,14 +258,7 @@ TopLevel::visit (AST::ExternalStaticItem &static_item)
void
TopLevel::visit (AST::StructStruct &struct_item)
{
- auto generic_vis = [this, &struct_item] () {
- for (auto &g : struct_item.get_generic_params ())
- {
- g->accept_vis (*this);
- }
- };
-
- ctx.scoped (Rib::Kind::Item, struct_item.get_node_id (), generic_vis);
+ DefaultResolver::visit (struct_item);
insert_or_error_out (struct_item.get_struct_name (), struct_item,
Namespace::Types);
@@ -374,24 +304,32 @@ void
TopLevel::visit (AST::EnumItem &variant)
{
insert_enum_variant_or_error_out (variant.get_identifier (), variant);
+
+ DefaultResolver::visit (variant);
}
void
TopLevel::visit (AST::EnumItemTuple &variant)
{
insert_enum_variant_or_error_out (variant.get_identifier (), variant);
+
+ DefaultResolver::visit (variant);
}
void
TopLevel::visit (AST::EnumItemStruct &variant)
{
insert_enum_variant_or_error_out (variant.get_identifier (), variant);
+
+ DefaultResolver::visit (variant);
}
void
TopLevel::visit (AST::EnumItemDiscriminant &variant)
{
insert_or_error_out (variant.get_identifier (), variant, Namespace::Types);
+
+ DefaultResolver::visit (variant);
}
void
@@ -401,6 +339,13 @@ TopLevel::visit (AST::Enum &enum_item)
Namespace::Types);
DefaultResolver::visit (enum_item);
+
+ // Since enums can be containers for imports, we need to insert them like we
+ // do for modules
+ if (Analysis::Mappings::get ().lookup_glob_container (
+ enum_item.get_node_id ())
+ == tl::nullopt)
+ Analysis::Mappings::get ().insert_glob_container (&enum_item);
}
void
@@ -430,21 +375,18 @@ TopLevel::visit (AST::TypeAlias &type_item)
DefaultResolver::visit (type_item);
}
-static void
-flatten_rebind (
+static void flatten_rebind (
const AST::UseTreeRebind &glob,
std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths);
-static void
-flatten_list (
+static void flatten_list (
const AST::UseTreeList &glob, std::vector<AST::SimplePath> &paths,
std::vector<AST::SimplePath> &glob_paths,
std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths,
NameResolutionContext &ctx);
-static void
-flatten_glob (const AST::UseTreeGlob &glob,
- std::vector<AST::SimplePath> &glob_paths,
- NameResolutionContext &ctx);
+static void flatten_glob (const AST::UseTreeGlob &glob,
+ std::vector<AST::SimplePath> &glob_paths,
+ NameResolutionContext &ctx);
static void
flatten (
@@ -455,17 +397,20 @@ flatten (
{
switch (tree->get_kind ())
{
- case AST::UseTree::Rebind: {
+ case AST::UseTree::Rebind:
+ {
auto rebind = static_cast<const AST::UseTreeRebind *> (tree);
flatten_rebind (*rebind, rebind_paths);
break;
}
- case AST::UseTree::List: {
+ case AST::UseTree::List:
+ {
auto list = static_cast<const AST::UseTreeList *> (tree);
flatten_list (*list, paths, glob_paths, rebind_paths, ctx);
break;
}
- case AST::UseTree::Glob: {
+ case AST::UseTree::Glob:
+ {
auto glob = static_cast<const AST::UseTreeGlob *> (tree);
flatten_glob (*glob, glob_paths, ctx);
break;
diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
index 3ff37ed..8d3da92 100644
--- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
@@ -160,8 +160,7 @@ private:
void visit (AST::Module &module) override;
void visit (AST::Trait &trait) override;
- void visit (AST::InherentImpl &impl) override;
- void visit (AST::TraitImpl &impl) override;
+ void maybe_insert_big_self (AST::Impl &impl) override;
void visit (AST::TraitItemType &trait_item) override;
void visit (AST::MacroRulesDefinition &macro) override;
void visit (AST::Function &function) override;
@@ -177,7 +176,7 @@ private:
void visit (AST::Union &union_item) override;
void visit (AST::ConstantItem &const_item) override;
void visit (AST::TypeAlias &type_item) override;
- void visit (AST::ExternCrate &crate) override;
+ void visit_extern_crate (AST::ExternCrate &, AST::Crate &, CrateNum) override;
void visit (AST::TypeParam &type_param) override;
void visit (AST::ConstGenericParam &const_param) override;