diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2022-06-14 07:17:11 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-14 07:17:11 +0000 |
commit | 1c679d7f42834a72956d6fb39c8d298dd6dc4b4e (patch) | |
tree | dce1ca0dd917ef4ea09bfa4809908bbe4dbe5dae /gcc/rust/resolve | |
parent | 25974baf19caf2b38c3755ce00a3065c62472053 (diff) | |
parent | 7ca7362602d4e827ecbc39d5cfdf56df9044633b (diff) | |
download | gcc-1c679d7f42834a72956d6fb39c8d298dd6dc4b4e.zip gcc-1c679d7f42834a72956d6fb39c8d298dd6dc4b4e.tar.gz gcc-1c679d7f42834a72956d6fb39c8d298dd6dc4b4e.tar.bz2 |
Merge #1307
1307: Handle super and crate in path resolution r=CohenArthur a=philberty
This patch completely reimplements our name resolution process for Paths in
general. This patch gets rid of the old Resolver::Definition structures
which were used so that we can map patterns back to LetStmts and establish
an hierarchy of nodes. This was not nessecary and complicated name/type
resolution.
TypePaths and PathInExpression are similar but have a slightl tweak in the
order they lookup the relevant scopes for types. But overall work the same.
There are several cases of paths you must consider in type resolution:
- i32 (simple type path)
- Self::A (associated type reference)
- mod::foo::impl_item() (reference to impl item)
- super::foo (reference to item)
- crate::foo
- T::bound()
In name resolution we cannot always fully resolve a path but have to rely
on the type-resolution to fully resolve a path as it may require careful
thought. For example a path like:
mod::foo::item()
might be for a generic foo<T>(), which might have two specialized impl
blocks so the best the name resolution can do is resolve mod::foo then
leave it up to the type resolution to figure out which item this is. We
might have i32 which is just a simple lookup.
Apart from that this patch introduces a module parent child hierachy so
that on paths such as super::foo we resolve super to be our parent module
scope then foo can be resolved with the lookup in the items for that
module.
More over this patch gets rid of some but not all of the awkward name
canonicalization to try and patch paths directly. More cleanup is still
needed here to make the name resolution step easier to read. This was
notable in the Qualified path handling where we can now rely on the type
resolver to setup the associated types properly rather than the name
resolver requiring us to resolve this directly.
Fixes #1251 #1230
Addresses #1227 #1153
Co-authored-by: Philip Herron <philip.herron@embecosm.com>
Diffstat (limited to 'gcc/rust/resolve')
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-base.h | 6 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-expr.cc | 13 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-implitem.h | 30 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-item.cc | 8 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-path.cc | 533 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-path.h | 14 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-pattern.cc | 4 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-pattern.h | 11 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-stmt.h | 6 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-toplevel.h | 55 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-type.cc | 186 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-type.h | 94 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve.cc | 47 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-name-resolver.cc | 54 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-name-resolver.h | 67 |
15 files changed, 594 insertions, 534 deletions
diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h index 9c1f0a1..17d05c3 100644 --- a/gcc/rust/resolve/rust-ast-resolve-base.h +++ b/gcc/rust/resolve/rust-ast-resolve-base.h @@ -199,10 +199,9 @@ public: void visit (AST::BareFunctionType &); protected: - ResolverBase (NodeId parent, NodeId current_module = UNKNOWN_NODEID) + ResolverBase (NodeId parent) : resolver (Resolver::get ()), mappings (Analysis::Mappings::get ()), - resolved_node (UNKNOWN_NODEID), parent (parent), - current_module (current_module), locus (Location ()) + resolved_node (UNKNOWN_NODEID), parent (parent), locus (Location ()) {} bool resolved () const { return resolved_node != UNKNOWN_NODEID; } @@ -216,7 +215,6 @@ protected: Analysis::Mappings *mappings; NodeId resolved_node; NodeId parent; - NodeId current_module; Location locus; }; diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.cc b/gcc/rust/resolve/rust-ast-resolve-expr.cc index 4bf35ef..0ae1847 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.cc +++ b/gcc/rust/resolve/rust-ast-resolve-expr.cc @@ -113,16 +113,12 @@ ResolveExpr::visit (AST::IdentifierExpr &expr) &resolved_node)) { resolver->insert_resolved_name (expr.get_node_id (), resolved_node); - resolver->insert_new_definition (expr.get_node_id (), - Definition{expr.get_node_id (), parent}); } else if (resolver->get_type_scope ().lookup ( CanonicalPath::new_seg (expr.get_node_id (), expr.as_string ()), &resolved_node)) { resolver->insert_resolved_type (expr.get_node_id (), resolved_node); - resolver->insert_new_definition (expr.get_node_id (), - Definition{expr.get_node_id (), parent}); } else { @@ -352,9 +348,6 @@ ResolveExpr::visit (AST::LoopExpr &expr) rust_error_at (label.get_locus (), "label redefined multiple times"); rust_error_at (locus, "was defined here"); }); - resolver->insert_new_definition (label_lifetime_node_id, - Definition{label_lifetime_node_id, - label.get_node_id ()}); } resolve_expr (expr.get_loop_block ().get (), expr.get_node_id ()); } @@ -412,9 +405,6 @@ ResolveExpr::visit (AST::WhileLoopExpr &expr) rust_error_at (label.get_locus (), "label redefined multiple times"); rust_error_at (locus, "was defined here"); }); - resolver->insert_new_definition (label_lifetime_node_id, - Definition{label_lifetime_node_id, - label.get_node_id ()}); } resolve_expr (expr.get_predicate_expr ().get (), expr.get_node_id ()); resolve_expr (expr.get_loop_block ().get (), expr.get_node_id ()); @@ -443,9 +433,6 @@ ResolveExpr::visit (AST::ForLoopExpr &expr) rust_error_at (label.get_locus (), "label redefined multiple times"); rust_error_at (locus, "was defined here"); }); - resolver->insert_new_definition (label_lifetime_node_id, - Definition{label_lifetime_node_id, - label.get_node_id ()}); } // this needs a new rib to contain the pattern diff --git a/gcc/rust/resolve/rust-ast-resolve-implitem.h b/gcc/rust/resolve/rust-ast-resolve-implitem.h index f17b222..ba184e4 100644 --- a/gcc/rust/resolve/rust-ast-resolve-implitem.h +++ b/gcc/rust/resolve/rust-ast-resolve-implitem.h @@ -76,9 +76,6 @@ public: r.add_range (locus); rust_error_at (r, "redefined multiple times"); }); - resolver->insert_new_definition (constant.get_node_id (), - Definition{constant.get_node_id (), - constant.get_node_id ()}); } void visit (AST::Function &function) override @@ -93,9 +90,6 @@ public: r.add_range (locus); rust_error_at (r, "redefined multiple times"); }); - resolver->insert_new_definition (function.get_node_id (), - Definition{function.get_node_id (), - function.get_node_id ()}); } void visit (AST::Method &method) override @@ -110,9 +104,6 @@ public: r.add_range (locus); rust_error_at (r, "redefined multiple times"); }); - resolver->insert_new_definition (method.get_node_id (), - Definition{method.get_node_id (), - method.get_node_id ()}); } private: @@ -150,9 +141,6 @@ public: r.add_range (locus); rust_error_at (r, "redefined multiple times"); }); - resolver->insert_new_definition (function.get_node_id (), - Definition{function.get_node_id (), - function.get_node_id ()}); mappings->insert_canonical_path (mappings->get_current_crate (), function.get_node_id (), cpath); @@ -171,9 +159,6 @@ public: r.add_range (locus); rust_error_at (r, "redefined multiple times"); }); - resolver->insert_new_definition (method.get_node_id (), - Definition{method.get_node_id (), - method.get_node_id ()}); mappings->insert_canonical_path (mappings->get_current_crate (), method.get_node_id (), cpath); @@ -192,9 +177,6 @@ public: r.add_range (locus); rust_error_at (r, "redefined multiple times"); }); - resolver->insert_new_definition (constant.get_node_id (), - Definition{constant.get_node_id (), - constant.get_node_id ()}); mappings->insert_canonical_path (mappings->get_current_crate (), constant.get_node_id (), cpath); @@ -253,9 +235,9 @@ public: r.add_range (locus); rust_error_at (r, "redefined multiple times"); }); - resolver->insert_new_definition (function.get_node_id (), - Definition{function.get_node_id (), - function.get_node_id ()}); + + NodeId current_module = resolver->peek_current_module_scope (); + mappings->insert_module_child_item (current_module, decl); } void visit (AST::ExternalStaticItem &item) override @@ -271,9 +253,9 @@ public: r.add_range (locus); rust_error_at (r, "redefined multiple times"); }); - resolver->insert_new_definition (item.get_node_id (), - Definition{item.get_node_id (), - item.get_node_id ()}); + + NodeId current_module = resolver->peek_current_module_scope (); + mappings->insert_module_child_item (current_module, decl); } private: diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc index 603037e..9f550ad 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.cc +++ b/gcc/rust/resolve/rust-ast-resolve-item.cc @@ -253,12 +253,14 @@ ResolveItem::visit (AST::Module &module) // FIXME: Should we reinsert a child here? Any reason we ResolveTopLevel::go // in ResolveTopLevel::visit (AST::Module) as well as here? for (auto &item : module.get_items ()) - ResolveTopLevel::go (item.get (), CanonicalPath::create_empty (), cpath, - module.get_node_id ()); + ResolveTopLevel::go (item.get (), CanonicalPath::create_empty (), cpath); + resolver->push_new_module_scope (module.get_node_id ()); for (auto &item : module.get_items ()) ResolveItem::go (item.get (), path, cpath); + resolver->pop_module_scope (); + resolver->get_name_scope ().pop (); resolver->get_type_scope ().pop (); resolver->get_label_scope ().pop (); @@ -526,6 +528,7 @@ ResolveItem::visit (AST::Function &function) auto decl = ResolveFunctionItemToCanonicalPath::resolve (function); auto path = prefix.append (decl); auto cpath = canonical_prefix.append (decl); + mappings->insert_canonical_path (mappings->get_current_crate (), function.get_node_id (), cpath); @@ -786,6 +789,7 @@ ResolveItem::visit (AST::TraitImpl &impl_block) resolver->get_name_scope ().pop (); return; } + rust_assert (!canonical_impl_type.is_empty ()); // setup paths bool canonicalize_type_args = !impl_block.has_generics (); diff --git a/gcc/rust/resolve/rust-ast-resolve-path.cc b/gcc/rust/resolve/rust-ast-resolve-path.cc index c7597a2..dbf2df7 100644 --- a/gcc/rust/resolve/rust-ast-resolve-path.cc +++ b/gcc/rust/resolve/rust-ast-resolve-path.cc @@ -47,301 +47,326 @@ ResolvePath::go (AST::SimplePath *expr, NodeId parent) void ResolvePath::resolve_path (AST::PathInExpression *expr) { - // resolve root segment first then apply segments in turn - std::vector<AST::PathExprSegment> &segs = expr->get_segments (); - AST::PathExprSegment &root_segment = segs.at (0); - AST::PathIdentSegment &root_ident_seg = root_segment.get_ident_segment (); + NodeId resolved_node_id = UNKNOWN_NODEID; + NodeId module_scope_id = resolver->peek_current_module_scope (); + NodeId previous_resolved_node_id = module_scope_id; + for (size_t i = 0; i < expr->get_segments ().size (); i++) + { + auto &segment = expr->get_segments ().at (i); + const AST::PathIdentSegment &ident_seg = segment.get_ident_segment (); + bool is_first_segment = i == 0; + resolved_node_id = UNKNOWN_NODEID; - bool segment_is_type = false; - CanonicalPath root_seg_path - = CanonicalPath::new_seg (root_segment.get_node_id (), - root_ident_seg.as_string ()); + NodeId crate_scope_id = resolver->peek_crate_module_scope (); + if (segment.is_crate_path_seg ()) + { + // what is the current crate scope node id? + module_scope_id = crate_scope_id; + previous_resolved_node_id = module_scope_id; + resolver->insert_resolved_name (segment.get_node_id (), + module_scope_id); + continue; + } + else if (segment.is_super_path_seg ()) + { + if (module_scope_id == crate_scope_id) + { + rust_error_at (segment.get_locus (), + "cannot use %<super%> at the crate scope"); + return; + } + + module_scope_id = resolver->peek_parent_module_scope (); + previous_resolved_node_id = module_scope_id; + resolver->insert_resolved_name (segment.get_node_id (), + module_scope_id); + continue; + } - // name scope first - if (resolver->get_name_scope ().lookup (root_seg_path, &resolved_node)) - { - segment_is_type = false; - resolver->insert_resolved_name (root_segment.get_node_id (), - resolved_node); - resolver->insert_new_definition (root_segment.get_node_id (), - Definition{expr->get_node_id (), - parent}); - } - // check the type scope - else if (resolver->get_type_scope ().lookup (root_seg_path, &resolved_node)) - { - segment_is_type = true; - resolver->insert_resolved_type (root_segment.get_node_id (), - resolved_node); - resolver->insert_new_definition (root_segment.get_node_id (), - Definition{expr->get_node_id (), - parent}); - } - else - { - rust_error_at (expr->get_locus (), - "Cannot find path %<%s%> in this scope", - root_segment.as_string ().c_str ()); - return; - } + // resolve any generic args + if (segment.has_generic_args ()) + { + bool ok = ResolveTypeToCanonicalPath::type_resolve_generic_args ( + segment.get_generic_args ()); + if (!ok) + { + rust_error_at (segment.get_locus (), + "failed to resolve generic arguments"); + return; + } + } - if (root_segment.has_generic_args ()) - { - bool ok = ResolveTypeToCanonicalPath::type_resolve_generic_args ( - root_segment.get_generic_args ()); - if (!ok) + // logic is awkward here there are a few cases + // + // T::Default + // mod::foo::impl_item + // super::super::module::item + // self + // self::foo + // self::foo::baz + // + // T::Default we can only resolve the T and cant do anything about Default + // its dependant on associated types + // + // mod::foo::impl_item + // we can resolve mod::foo but nothing about impl_item but we need to + // _always resolve generic arguments + // + // self is a simple single lookup + // + // we have module_scope_id for the next module_scope to lookup + // resolved_node_id is the thing we have resolve this segment to + // + // new algo? + // we can only use module resolution when the previous segment is either + // unknown or equal to this module_scope_id + // + // can only use old resolution when previous segment is unkown + + if (previous_resolved_node_id == module_scope_id) { - rust_error_at (root_segment.get_locus (), - "failed to resolve generic arguments"); - return; + Optional<CanonicalPath &> resolved_child + = mappings->lookup_module_child (module_scope_id, + ident_seg.as_string ()); + if (resolved_child.is_some ()) + { + NodeId resolved_node = resolved_child->get_node_id (); + if (resolver->get_name_scope ().decl_was_declared_here ( + resolved_node)) + { + resolved_node_id = resolved_node; + resolver->insert_resolved_name (segment.get_node_id (), + resolved_node); + } + else if (resolver->get_type_scope ().decl_was_declared_here ( + resolved_node)) + { + resolved_node_id = resolved_node; + resolver->insert_resolved_type (segment.get_node_id (), + resolved_node); + } + else + { + rust_error_at (segment.get_locus (), + "Cannot find path %<%s%> in this scope", + segment.as_string ().c_str ()); + return; + } + } + } + + if (resolved_node_id == UNKNOWN_NODEID && is_first_segment) + { + // name scope first + NodeId resolved_node = UNKNOWN_NODEID; + const CanonicalPath path + = CanonicalPath::new_seg (segment.get_node_id (), + ident_seg.as_string ()); + if (resolver->get_name_scope ().lookup (path, &resolved_node)) + { + resolver->insert_resolved_name (segment.get_node_id (), + resolved_node); + } + // check the type scope + else if (resolver->get_type_scope ().lookup (path, &resolved_node)) + { + resolver->insert_resolved_type (segment.get_node_id (), + resolved_node); + } + else + { + rust_error_at (segment.get_locus (), + "Cannot find path %<%s%> in this scope", + segment.as_string ().c_str ()); + return; + } + + resolved_node_id = resolved_node; + } + + if (resolved_node_id != UNKNOWN_NODEID) + { + if (mappings->node_is_module (resolved_node_id)) + { + module_scope_id = resolved_node_id; + } + previous_resolved_node_id = resolved_node_id; } } - bool is_single_segment = segs.size () == 1; - if (is_single_segment) + resolved_node = resolved_node_id; + if (resolved_node_id != UNKNOWN_NODEID) { - if (segment_is_type) - resolver->insert_resolved_type (expr->get_node_id (), resolved_node); + // name scope first + if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id)) + { + resolver->insert_resolved_name (expr->get_node_id (), + resolved_node_id); + } + // check the type scope + else if (resolver->get_type_scope ().decl_was_declared_here ( + resolved_node_id)) + { + resolver->insert_resolved_type (expr->get_node_id (), + resolved_node_id); + } else - resolver->insert_resolved_name (expr->get_node_id (), resolved_node); - - resolver->insert_new_definition (expr->get_node_id (), - Definition{expr->get_node_id (), - parent}); - return; + { + gcc_unreachable (); + } } - - resolve_segments (root_seg_path, 1, expr->get_segments (), - expr->get_node_id (), expr->get_locus ()); } void ResolvePath::resolve_path (AST::QualifiedPathInExpression *expr) { AST::QualifiedPathType &root_segment = expr->get_qualified_path_type (); - - bool canonicalize_type_with_generics = false; ResolveType::go (&root_segment.get_as_type_path (), - root_segment.get_node_id (), - canonicalize_type_with_generics); - - ResolveType::go (root_segment.get_type ().get (), root_segment.get_node_id (), - canonicalize_type_with_generics); - - bool type_resolve_generic_args = true; - CanonicalPath impl_type_seg - = ResolveTypeToCanonicalPath::resolve (*root_segment.get_type ().get (), - canonicalize_type_with_generics, - type_resolve_generic_args); - - CanonicalPath trait_type_seg - = ResolveTypeToCanonicalPath::resolve (root_segment.get_as_type_path (), - canonicalize_type_with_generics, - type_resolve_generic_args); - CanonicalPath root_seg_path - = TraitImplProjection::resolve (root_segment.get_node_id (), trait_type_seg, - impl_type_seg); - bool segment_is_type = false; + root_segment.get_node_id ()); + ResolveType::go (root_segment.get_type ().get (), + root_segment.get_node_id ()); - // name scope first - if (resolver->get_name_scope ().lookup (root_seg_path, &resolved_node)) + for (auto &segment : expr->get_segments ()) { - segment_is_type = false; - resolver->insert_resolved_name (root_segment.get_node_id (), - resolved_node); - resolver->insert_new_definition (root_segment.get_node_id (), - Definition{expr->get_node_id (), - parent}); - } - // check the type scope - else if (resolver->get_type_scope ().lookup (root_seg_path, &resolved_node)) - { - segment_is_type = true; - resolver->insert_resolved_type (root_segment.get_node_id (), - resolved_node); - resolver->insert_new_definition (root_segment.get_node_id (), - Definition{expr->get_node_id (), - parent}); - } - else - { - rust_error_at (expr->get_locus (), - "Cannot find path %<%s%> in this scope", - root_segment.as_string ().c_str ()); - return; - } - - bool is_single_segment = expr->get_segments ().empty (); - if (is_single_segment) - { - if (segment_is_type) - resolver->insert_resolved_type (expr->get_node_id (), resolved_node); - else - resolver->insert_resolved_name (expr->get_node_id (), resolved_node); - - resolver->insert_new_definition (expr->get_node_id (), - Definition{expr->get_node_id (), - parent}); - return; + // we cant actually do anything with the segment itself since this is all + // the job of the type system to figure it out but we can resolve any + // generic arguments used + if (segment.has_generic_args ()) + { + bool ok = ResolveTypeToCanonicalPath::type_resolve_generic_args ( + segment.get_generic_args ()); + if (!ok) + { + rust_error_at (segment.get_locus (), + "failed to resolve generic arguments"); + return; + } + } } - - resolve_segments (root_seg_path, 0, expr->get_segments (), - expr->get_node_id (), expr->get_locus ()); } void -ResolvePath::resolve_segments (CanonicalPath prefix, size_t offs, - std::vector<AST::PathExprSegment> &segs, - NodeId expr_node_id, Location expr_locus) +ResolvePath::resolve_path (AST::SimplePath *expr) { - // we can attempt to resolve this path fully - CanonicalPath path = prefix; - bool segment_is_type = false; - for (size_t i = offs; i < segs.size (); i++) - { - AST::PathExprSegment &seg = segs.at (i); - auto s = ResolvePathSegmentToCanonicalPath::resolve (seg); - path = path.append (s); + NodeId crate_scope_id = resolver->peek_crate_module_scope (); + NodeId module_scope_id = resolver->peek_current_module_scope (); - // reset state - segment_is_type = false; - resolved_node = UNKNOWN_NODEID; + NodeId resolved_node_id = UNKNOWN_NODEID; + for (size_t i = 0; i < expr->get_segments ().size (); i++) + { + auto &segment = expr->get_segments ().at (i); + bool is_first_segment = i == 0; + resolved_node_id = UNKNOWN_NODEID; - if (resolver->get_name_scope ().lookup (path, &resolved_node)) + if (segment.is_crate_path_seg ()) { - resolver->insert_resolved_name (seg.get_node_id (), resolved_node); - resolver->insert_new_definition (seg.get_node_id (), - Definition{expr_node_id, parent}); + // what is the current crate scope node id? + module_scope_id = crate_scope_id; + resolver->insert_resolved_name (segment.get_node_id (), + module_scope_id); + continue; } - // check the type scope - else if (resolver->get_type_scope ().lookup (path, &resolved_node)) + else if (segment.is_super_path_seg ()) { - segment_is_type = true; - resolver->insert_resolved_type (seg.get_node_id (), resolved_node); - resolver->insert_new_definition (seg.get_node_id (), - Definition{expr_node_id, parent}); + if (module_scope_id == crate_scope_id) + { + rust_error_at (segment.get_locus (), + "cannot use %<super%> at the crate scope"); + return; + } + + module_scope_id = resolver->peek_parent_module_scope (); + resolver->insert_resolved_name (segment.get_node_id (), + module_scope_id); + continue; } - else - { - // attempt to fully resolve the path which is allowed to fail given - // the following scenario - // - // https://github.com/Rust-GCC/gccrs/issues/355 Paths are - // resolved fully here, there are limitations though imagine: - // - // struct Foo<A> (A); - // - // impl Foo<isize> { - // fn test() -> ... - // - // impl Foo<f32> { - // fn test() -> ... - // - // fn main() { - // let a:i32 = Foo::test(); - // - // there are multiple paths that test can resolve to Foo::<?>::test - // here so we cannot resolve this case - // - // canonical names: - // - // struct Foo<A> -> Foo - // impl Foo<isize>::fn test -> Foo::isize::test - // impl Foo<f32>::fn test -> Foo::f32::test - // - // Since there is the case we have the following paths for test: - // - // Foo::isize::test - // Foo::f32::test - // vs - // Foo::test - // - // but the lookup was simply Foo::test we must rely on type resolution - // to figure this type out in a similar fashion to method resolution - // with a probe phase - // nothing more we can do we need the type resolver to try and resolve - // this - return; + Optional<CanonicalPath &> resolved_child + = mappings->lookup_module_child (module_scope_id, + segment.get_segment_name ()); + if (resolved_child.is_some ()) + { + NodeId resolved_node = resolved_child->get_node_id (); + if (resolver->get_name_scope ().decl_was_declared_here ( + resolved_node)) + { + resolved_node_id = resolved_node; + resolver->insert_resolved_name (segment.get_node_id (), + resolved_node); + } + else if (resolver->get_type_scope ().decl_was_declared_here ( + resolved_node)) + { + resolved_node_id = resolved_node; + resolver->insert_resolved_type (segment.get_node_id (), + resolved_node); + } + else + { + rust_error_at (segment.get_locus (), + "Cannot find path %<%s%> in this scope", + segment.as_string ().c_str ()); + return; + } } - } - - // its fully resolved lets mark it as such - if (resolved_node != UNKNOWN_NODEID) - { - if (segment_is_type) - resolver->insert_resolved_type (expr_node_id, resolved_node); - else - resolver->insert_resolved_name (expr_node_id, resolved_node); - - resolver->insert_new_definition (expr_node_id, - Definition{expr_node_id, parent}); - } -} - -static bool -lookup_and_insert_segment (Resolver *resolver, CanonicalPath path, - NodeId segment_id, NodeId *to_resolve, bool &is_type) -{ - if (resolver->get_name_scope ().lookup (path, to_resolve)) - { - resolver->insert_resolved_name (segment_id, *to_resolve); - } - else if (resolver->get_type_scope ().lookup (path, to_resolve)) - { - is_type = true; - resolver->insert_resolved_type (segment_id, *to_resolve); - } - else - { - return false; - } - return true; -} - -void -ResolvePath::resolve_path (AST::SimplePath *simple_path) -{ - // resolve root segment first then apply segments in turn - auto expr_node_id = simple_path->get_node_id (); - auto is_type = false; - - auto path = CanonicalPath::create_empty (); - for (const auto &seg : simple_path->get_segments ()) - { - auto s = ResolveSimplePathSegmentToCanonicalPath::resolve (seg); - path = path.append (s); - - // Reset state - resolved_node = UNKNOWN_NODEID; - is_type = false; + if (resolved_node_id == UNKNOWN_NODEID && is_first_segment) + { + // name scope first + NodeId resolved_node = UNKNOWN_NODEID; + const CanonicalPath path + = CanonicalPath::new_seg (segment.get_node_id (), + segment.get_segment_name ()); + if (resolver->get_name_scope ().lookup (path, &resolved_node)) + { + resolved_node_id = resolved_node; + resolver->insert_resolved_name (segment.get_node_id (), + resolved_node); + } + // check the type scope + else if (resolver->get_type_scope ().lookup (path, &resolved_node)) + { + resolved_node_id = resolved_node; + resolver->insert_resolved_type (segment.get_node_id (), + resolved_node); + } + } - if (!lookup_and_insert_segment (resolver, path, seg.get_node_id (), - &resolved_node, is_type)) + if (resolved_node_id == UNKNOWN_NODEID) { - rust_error_at (seg.get_locus (), - "cannot find simple path segment %qs", - seg.as_string ().c_str ()); + rust_error_at (segment.get_locus (), + "cannot find simple path segment %<%s%> in this scope", + segment.as_string ().c_str ()); return; } + + if (mappings->node_is_module (resolved_node_id)) + { + module_scope_id = resolved_node_id; + } } - if (resolved_node == UNKNOWN_NODEID) + resolved_node = resolved_node_id; + if (resolved_node_id != UNKNOWN_NODEID) { - rust_error_at (simple_path->get_locus (), - "could not resolve simple path %qs", - simple_path->as_string ().c_str ()); - return; + // name scope first + if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id)) + { + resolver->insert_resolved_name (expr->get_node_id (), + resolved_node_id); + } + // check the type scope + else if (resolver->get_type_scope ().decl_was_declared_here ( + resolved_node_id)) + { + resolver->insert_resolved_type (expr->get_node_id (), + resolved_node_id); + } + else + { + gcc_unreachable (); + } } - - if (is_type) - resolver->insert_resolved_type (expr_node_id, resolved_node); - else - resolver->insert_resolved_name (expr_node_id, resolved_node); - - resolver->insert_new_definition (expr_node_id, - Definition{expr_node_id, parent}); } } // namespace Resolver diff --git a/gcc/rust/resolve/rust-ast-resolve-path.h b/gcc/rust/resolve/rust-ast-resolve-path.h index cbfe967..fc8785f 100644 --- a/gcc/rust/resolve/rust-ast-resolve-path.h +++ b/gcc/rust/resolve/rust-ast-resolve-path.h @@ -40,26 +40,12 @@ private: void resolve_path (AST::QualifiedPathInExpression *expr); void resolve_path (AST::SimplePath *expr); - void resolve_segments (CanonicalPath prefix, size_t offs, - std::vector<AST::PathExprSegment> &segs, - NodeId expr_node_id, Location expr_locus); - void resolve_simple_path_segments (CanonicalPath prefix, size_t offs, const std::vector<AST::SimplePathSegment> &segs, NodeId expr_node_id, Location expr_locus); }; -class ResolveSimplePathSegmentToCanonicalPath -{ -public: - static CanonicalPath resolve (const AST::SimplePathSegment &seg) - { - // FIXME: Since this is so simple, maybe it can simply be a tiny function? - return CanonicalPath::new_seg (seg.get_node_id (), seg.get_segment_name ()); - } -}; - } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.cc b/gcc/rust/resolve/rust-ast-resolve-pattern.cc index dc2cca4..1947212 100644 --- a/gcc/rust/resolve/rust-ast-resolve-pattern.cc +++ b/gcc/rust/resolve/rust-ast-resolve-pattern.cc @@ -87,9 +87,7 @@ PatternDeclaration::visit (AST::StructPattern &pattern) CanonicalPath::new_seg (ident.get_node_id (), ident.get_identifier ()), ident.get_node_id (), ident.get_locus ()); - resolver->insert_new_definition (ident.get_node_id (), - Definition{ident.get_node_id (), - ident.get_node_id ()}); + resolver->mark_decl_mutability (ident.get_node_id (), ident.is_mut ()); } diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.h b/gcc/rust/resolve/rust-ast-resolve-pattern.h index dfb05d3..b899754 100644 --- a/gcc/rust/resolve/rust-ast-resolve-pattern.h +++ b/gcc/rust/resolve/rust-ast-resolve-pattern.h @@ -48,9 +48,6 @@ public: &resolved_node)) { resolver->insert_resolved_name (pattern.get_node_id (), resolved_node); - resolver->insert_new_definition (pattern.get_node_id (), - Definition{pattern.get_node_id (), - parent}); } } @@ -76,9 +73,7 @@ public: resolver->get_name_scope ().insert ( CanonicalPath::new_seg (pattern.get_node_id (), pattern.get_ident ()), pattern.get_node_id (), pattern.get_locus ()); - resolver->insert_new_definition (pattern.get_node_id (), - Definition{pattern.get_node_id (), - parent}); + resolver->mark_decl_mutability (pattern.get_node_id (), pattern.get_is_mut ()); } @@ -88,9 +83,7 @@ public: resolver->get_name_scope ().insert ( CanonicalPath::new_seg (pattern.get_node_id (), "_"), pattern.get_node_id (), pattern.get_locus ()); - resolver->insert_new_definition (pattern.get_node_id (), - Definition{pattern.get_node_id (), - parent}); + resolver->mark_decl_mutability (pattern.get_node_id (), false); } diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h index c8d42bc..3556b68 100644 --- a/gcc/rust/resolve/rust-ast-resolve-stmt.h +++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h @@ -71,9 +71,6 @@ public: r.add_range (locus); rust_error_at (r, "redefined multiple times"); }); - resolver->insert_new_definition (constant.get_node_id (), - Definition{constant.get_node_id (), - constant.get_node_id ()}); ResolveType::go (constant.get_type ().get (), constant.get_node_id ()); ResolveExpr::go (constant.get_expr ().get (), constant.get_node_id (), @@ -361,9 +358,6 @@ public: r.add_range (locus); rust_error_at (r, "redefined multiple times"); }); - resolver->insert_new_definition (function.get_node_id (), - Definition{function.get_node_id (), - function.get_node_id ()}); NodeId scope_node_id = function.get_node_id (); resolver->get_name_scope ().push (scope_node_id); diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h index 8d4e12b..78b786a 100644 --- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h +++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h @@ -34,13 +34,15 @@ class ResolveTopLevel : public ResolverBase public: static void go (AST::Item *item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix, NodeId current_module) + const CanonicalPath &canonical_prefix) { if (item->is_marked_for_strip ()) return; - ResolveTopLevel resolver (prefix, canonical_prefix, current_module); + ResolveTopLevel resolver (prefix, canonical_prefix); item->accept_vis (resolver); + + NodeId current_module = resolver.resolver->peek_current_module_scope (); resolver.mappings->insert_child_item_to_parent_module_mapping ( item->get_node_id (), current_module); }; @@ -60,15 +62,15 @@ public: rust_error_at (r, "redefined multiple times"); }); - resolver->insert_new_definition (module.get_node_id (), - Definition{module.get_node_id (), - module.get_node_id ()}); - + NodeId current_module = resolver->peek_current_module_scope (); mappings->insert_module_child_item (current_module, mod); mappings->insert_module_child (current_module, module.get_node_id ()); + resolver->push_new_module_scope (module.get_node_id ()); for (auto &item : module.get_items ()) - ResolveTopLevel::go (item.get (), path, cpath, module.get_node_id ()); + ResolveTopLevel::go (item.get (), path, cpath); + + resolver->pop_module_scope (); mappings->insert_canonical_path (mappings->get_current_crate (), module.get_node_id (), cpath); @@ -89,6 +91,7 @@ public: rust_error_at (r, "redefined multiple times"); }); + NodeId current_module = resolver->peek_current_module_scope (); mappings->insert_module_child_item (current_module, talias); mappings->insert_canonical_path (mappings->get_current_crate (), alias.get_node_id (), cpath); @@ -109,6 +112,7 @@ public: rust_error_at (r, "redefined multiple times"); }); + NodeId current_module = resolver->peek_current_module_scope (); mappings->insert_module_child_item (current_module, decl); mappings->insert_canonical_path (mappings->get_current_crate (), struct_decl.get_node_id (), cpath); @@ -130,8 +134,9 @@ public: }); for (auto &variant : enum_decl.get_variants ()) - ResolveTopLevel::go (variant.get (), path, cpath, current_module); + ResolveTopLevel::go (variant.get (), path, cpath); + NodeId current_module = resolver->peek_current_module_scope (); mappings->insert_module_child_item (current_module, decl); mappings->insert_canonical_path (mappings->get_current_crate (), enum_decl.get_node_id (), cpath); @@ -152,7 +157,6 @@ public: rust_error_at (r, "redefined multiple times"); }); - mappings->insert_module_child_item (current_module, decl); mappings->insert_canonical_path (mappings->get_current_crate (), item.get_node_id (), cpath); } @@ -229,6 +233,7 @@ public: rust_error_at (r, "redefined multiple times"); }); + NodeId current_module = resolver->peek_current_module_scope (); mappings->insert_module_child_item (current_module, decl); mappings->insert_canonical_path (mappings->get_current_crate (), struct_decl.get_node_id (), cpath); @@ -249,6 +254,7 @@ public: rust_error_at (r, "redefined multiple times"); }); + NodeId current_module = resolver->peek_current_module_scope (); mappings->insert_module_child_item (current_module, decl); mappings->insert_canonical_path (mappings->get_current_crate (), union_decl.get_node_id (), cpath); @@ -268,11 +274,10 @@ public: r.add_range (locus); rust_error_at (r, "redefined multiple times"); }); - resolver->insert_new_definition (var.get_node_id (), - Definition{var.get_node_id (), - var.get_node_id ()}); + resolver->mark_decl_mutability (var.get_node_id (), var.is_mutable ()); + NodeId current_module = resolver->peek_current_module_scope (); mappings->insert_module_child_item (current_module, decl); mappings->insert_canonical_path (mappings->get_current_crate (), var.get_node_id (), cpath); @@ -291,10 +296,8 @@ public: r.add_range (locus); rust_error_at (r, "redefined multiple times"); }); - resolver->insert_new_definition (constant.get_node_id (), - Definition{constant.get_node_id (), - constant.get_node_id ()}); + NodeId current_module = resolver->peek_current_module_scope (); mappings->insert_module_child_item (current_module, decl); mappings->insert_canonical_path (mappings->get_current_crate (), constant.get_node_id (), cpath); @@ -313,18 +316,8 @@ public: r.add_range (locus); rust_error_at (r, "redefined multiple times"); }); - resolver->insert_new_definition (function.get_node_id (), - Definition{function.get_node_id (), - function.get_node_id ()}); - - // if this does not get a reference it will be determined to be unused - // lets give it a fake reference to itself - if (function.get_function_name ().compare ("main") == 0) - { - resolver->insert_resolved_name (function.get_node_id (), - function.get_node_id ()); - } + NodeId current_module = resolver->peek_current_module_scope (); mappings->insert_module_child_item (current_module, decl); mappings->insert_canonical_path (mappings->get_current_crate (), function.get_node_id (), cpath); @@ -373,11 +366,6 @@ public: r.add_range (locus); rust_error_at (r, "redefined multiple times"); }); - resolver->insert_new_definition (impl_block.get_node_id (), - Definition{impl_block.get_node_id (), - impl_block.get_node_id ()}); - resolver->insert_resolved_name (impl_block.get_node_id (), - impl_block.get_node_id ()); for (auto &impl_item : impl_block.get_impl_items ()) ResolveToplevelImplItem::go (impl_item.get (), impl_prefix); @@ -403,6 +391,7 @@ public: for (auto &item : trait.get_trait_items ()) ResolveTopLevelTraitItems::go (item.get (), path, cpath); + NodeId current_module = resolver->peek_current_module_scope (); mappings->insert_module_child_item (current_module, decl); mappings->insert_canonical_path (mappings->get_current_crate (), trait.get_node_id (), cpath); @@ -418,8 +407,8 @@ public: private: ResolveTopLevel (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix, NodeId current_module) - : ResolverBase (UNKNOWN_NODEID, current_module), prefix (prefix), + const CanonicalPath &canonical_prefix) + : ResolverBase (UNKNOWN_NODEID), prefix (prefix), canonical_prefix (canonical_prefix) {} diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc index 2b5c684..ce9c0d1 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.cc +++ b/gcc/rust/resolve/rust-ast-resolve-type.cc @@ -133,15 +133,12 @@ ResolveType::visit (AST::ArrayType &type) void ResolveType::visit (AST::TraitObjectTypeOneBound &type) { - NodeId bound_resolved_id - = ResolveTypeBound::go (&type.get_trait_bound (), type.get_node_id ()); - ok = bound_resolved_id != UNKNOWN_NODEID; + ResolveTypeBound::go (&type.get_trait_bound (), type.get_node_id ()); } void ResolveType::visit (AST::TraitObjectType &type) { - ok = true; for (auto &bound : type.get_type_param_bounds ()) { /* NodeId bound_resolved_id = */ @@ -270,30 +267,183 @@ ResolveRelativeTypePath::ResolveRelativeTypePath (CanonicalPath qualified_path) } bool -ResolveRelativeTypePath::go (AST::QualifiedPathInType &path) +ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id) { - // resolve the type and trait path - auto &qualified_path = path.get_qualified_path_type (); CanonicalPath result = CanonicalPath::create_empty (); - if (!resolve_qual_seg (qualified_path, result)) - return false; + ResolveRelativeTypePath o (result); + auto &resolver = o.resolver; + auto &mappings = o.mappings; - // resolve the associated impl if available but it can also be from a trait - // and this is allowed to fail - auto resolver = Resolver::get (); - NodeId projection_resolved_id = UNKNOWN_NODEID; - if (resolver->get_name_scope ().lookup (result, &projection_resolved_id)) + NodeId module_scope_id = resolver->peek_current_module_scope (); + NodeId previous_resolved_node_id = module_scope_id; + for (size_t i = 0; i < path.get_segments ().size (); i++) { - // mark the resolution for this - resolver->insert_resolved_name (qualified_path.get_node_id (), - projection_resolved_id); + auto &segment = path.get_segments ().at (i); + const AST::PathIdentSegment &ident_seg = segment->get_ident_segment (); + bool is_first_segment = i == 0; + resolved_node_id = UNKNOWN_NODEID; + + NodeId crate_scope_id = resolver->peek_crate_module_scope (); + if (segment->is_crate_path_seg ()) + { + // what is the current crate scope node id? + module_scope_id = crate_scope_id; + previous_resolved_node_id = module_scope_id; + resolver->insert_resolved_name (segment->get_node_id (), + module_scope_id); + + continue; + } + else if (segment->is_super_path_seg ()) + { + if (module_scope_id == crate_scope_id) + { + rust_error_at (segment->get_locus (), + "cannot use super at the crate scope"); + return false; + } + + module_scope_id = resolver->peek_parent_module_scope (); + previous_resolved_node_id = module_scope_id; + resolver->insert_resolved_name (segment->get_node_id (), + module_scope_id); + continue; + } + + switch (segment->get_type ()) + { + case AST::TypePathSegment::SegmentType::GENERIC: { + AST::TypePathSegmentGeneric *s + = static_cast<AST::TypePathSegmentGeneric *> (segment.get ()); + if (s->has_generic_args ()) + { + for (auto > : s->get_generic_args ().get_type_args ()) + { + ResolveType::go (gt.get (), UNKNOWN_NODEID); + } + } + } + break; + + case AST::TypePathSegment::SegmentType::REG: + // nothing to do + break; + + case AST::TypePathSegment::SegmentType::FUNCTION: + gcc_unreachable (); + break; + } + + if (previous_resolved_node_id == module_scope_id + && path.get_segments ().size () > 1) + { + Optional<CanonicalPath &> resolved_child + = mappings->lookup_module_child (module_scope_id, + ident_seg.as_string ()); + if (resolved_child.is_some ()) + { + NodeId resolved_node = resolved_child->get_node_id (); + if (resolver->get_name_scope ().decl_was_declared_here ( + resolved_node)) + { + resolved_node_id = resolved_node; + resolver->insert_resolved_name (segment->get_node_id (), + resolved_node); + } + else if (resolver->get_type_scope ().decl_was_declared_here ( + resolved_node)) + { + resolved_node_id = resolved_node; + resolver->insert_resolved_type (segment->get_node_id (), + resolved_node); + } + else + { + rust_error_at (segment->get_locus (), + "Cannot find path %<%s%> in this scope", + segment->as_string ().c_str ()); + return false; + } + } + } + + if (resolved_node_id == UNKNOWN_NODEID && is_first_segment) + { + // name scope first + NodeId resolved_node = UNKNOWN_NODEID; + const CanonicalPath path + = CanonicalPath::new_seg (segment->get_node_id (), + ident_seg.as_string ()); + if (resolver->get_type_scope ().lookup (path, &resolved_node)) + { + resolver->insert_resolved_type (segment->get_node_id (), + resolved_node); + } + else if (resolver->get_name_scope ().lookup (path, &resolved_node)) + { + resolver->insert_resolved_name (segment->get_node_id (), + resolved_node); + } + else + { + rust_error_at (segment->get_locus (), + "failed to resolve TypePath: %s in this scope", + segment->as_string ().c_str ()); + return false; + } + + resolved_node_id = resolved_node; + } + + if (resolved_node_id != UNKNOWN_NODEID) + { + if (mappings->node_is_module (resolved_node_id)) + { + module_scope_id = resolved_node_id; + } + previous_resolved_node_id = resolved_node_id; + } } + if (resolved_node_id != UNKNOWN_NODEID) + { + // name scope first + if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id)) + { + resolver->insert_resolved_name (path.get_node_id (), + resolved_node_id); + } + // check the type scope + else if (resolver->get_type_scope ().decl_was_declared_here ( + resolved_node_id)) + { + resolver->insert_resolved_type (path.get_node_id (), + resolved_node_id); + } + else + { + gcc_unreachable (); + } + } + + return true; +} + +bool +ResolveRelativeTypePath::go (AST::QualifiedPathInType &path) +{ + CanonicalPath result = CanonicalPath::create_empty (); + ResolveRelativeTypePath o (result); + + // resolve the type and trait path + auto &qualified_path = path.get_qualified_path_type (); + if (!o.resolve_qual_seg (qualified_path, result)) + return false; + // qualified types are similar to other paths in that we cannot guarantee // that we can resolve the path at name resolution. We must look up // associated types and type information to figure this out properly - ResolveRelativeTypePath o (result); std::unique_ptr<AST::TypePathSegment> &associated = path.get_associated_segment (); diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h index d10cec2..cc117ec 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ b/gcc/rust/resolve/rust-ast-resolve-type.h @@ -190,13 +190,13 @@ class ResolveRelativeTypePath : public ResolveTypeToCanonicalPath using ResolveTypeToCanonicalPath::visit; public: + static bool go (AST::TypePath &path, NodeId &resolved_node_id); static bool go (AST::QualifiedPathInType &path); private: ResolveRelativeTypePath (CanonicalPath qualified_path); - static bool resolve_qual_seg (AST::QualifiedPathType &seg, - CanonicalPath &result); + bool resolve_qual_seg (AST::QualifiedPathType &seg, CanonicalPath &result); }; class ResolveType : public ResolverBase @@ -211,7 +211,6 @@ public: ResolveType resolver (parent, canonicalize_type_with_generics, canonical_path); type->accept_vis (resolver); - return resolver.resolved_node; }; @@ -226,7 +225,6 @@ public: void visit (AST::TupleType &tuple) override { - ok = true; if (tuple.is_unit_type ()) { resolved_node = resolver->get_unit_type_node_id (); @@ -239,87 +237,16 @@ public: void visit (AST::TypePath &path) override { - auto rel_canonical_path - = ResolveTypeToCanonicalPath::resolve (path, - canonicalize_type_with_generics, - true); - if (rel_canonical_path.is_empty ()) - { - rust_error_at (path.get_locus (), - "Failed to resolve canonical path for TypePath"); - return; - } - - // lets try and resolve in one go else leave it up to the type resolver to - // figure outer - - if (resolver->get_type_scope ().lookup (rel_canonical_path, &resolved_node)) - { - resolver->insert_resolved_type (path.get_node_id (), resolved_node); - resolver->insert_new_definition (path.get_node_id (), - Definition{path.get_node_id (), - parent}); - - if (canonical_path != nullptr) - { - const CanonicalPath *cpath = nullptr; - bool ok - = mappings->lookup_canonical_path (mappings->get_current_crate (), - resolved_node, &cpath); - if (!ok) - { - *canonical_path = rel_canonical_path; - } - else - { - *canonical_path = *cpath; - } - } - - return; - } - - // lets resolve as many segments as we can and leave it up to the type - // resolver otherwise - size_t nprocessed = 0; - rel_canonical_path.iterate ([&] (const CanonicalPath &seg) -> bool { - resolved_node = UNKNOWN_NODEID; - - if (!resolver->get_type_scope ().lookup (seg, &resolved_node)) - return false; - - resolver->insert_resolved_type (seg.get_node_id (), resolved_node); - resolver->insert_new_definition (seg.get_node_id (), - Definition{path.get_node_id (), parent}); - nprocessed++; - return true; - }); - - if (nprocessed == 0) + if (ResolveRelativeTypePath::go (path, resolved_node)) { - rust_error_at (path.get_locus (), "failed to resolve TypePath: %s", - path.as_string ().c_str ()); - return; - } - - // its ok if this fails since the type resolver sometimes will need to - // investigate the bounds of a type for the associated type for example see: - // https://github.com/Rust-GCC/gccrs/issues/746 - if (nprocessed == rel_canonical_path.size ()) - { - resolver->insert_resolved_type (path.get_node_id (), resolved_node); - resolver->insert_new_definition (path.get_node_id (), - Definition{path.get_node_id (), - parent}); + if (canonical_path == nullptr) + return; - if (canonical_path != nullptr) + const CanonicalPath *type_path = nullptr; + if (mappings->lookup_canonical_path (mappings->get_current_crate (), + resolved_node, &type_path)) { - const CanonicalPath *cpath = nullptr; - bool ok - = mappings->lookup_canonical_path (mappings->get_current_crate (), - resolved_node, &cpath); - rust_assert (ok); - *canonical_path = *cpath; + *canonical_path = *type_path; } } } @@ -350,11 +277,10 @@ private: CanonicalPath *canonical_path) : ResolverBase (parent), canonicalize_type_with_generics (canonicalize_type_with_generics), - ok (false), canonical_path (canonical_path) + canonical_path (canonical_path) {} bool canonicalize_type_with_generics; - bool ok; CanonicalPath *canonical_path; }; diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index 945ff28..169237a 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -81,20 +81,34 @@ NameResolution::go (AST::Crate &crate) = CanonicalPath::new_seg (scope_node_id, crate_name); crate_prefix.set_crate_num (cnum); + // setup a dummy crate node + resolver->get_name_scope ().insert ( + CanonicalPath::new_seg (crate.get_node_id (), "__$$crate__"), + crate.get_node_id (), Location ()); + + // setup the root scope + resolver->push_new_module_scope (scope_node_id); + // first gather the top-level namespace names then we drill down so this // allows for resolving forward declarations since an impl block might have // a Self type Foo which is defined after the impl block for example. for (auto it = crate.items.begin (); it != crate.items.end (); it++) ResolveTopLevel::go (it->get (), CanonicalPath::create_empty (), - crate_prefix, scope_node_id); + crate_prefix); // FIXME remove this if (saw_errors ()) - return; + { + resolver->pop_module_scope (); + return; + } // next we can drill down into the items and their scopes for (auto it = crate.items.begin (); it != crate.items.end (); it++) ResolveItem::go (it->get (), CanonicalPath::create_empty (), crate_prefix); + + // done + resolver->pop_module_scope (); } // rust-ast-resolve-struct-expr-field.h @@ -158,19 +172,21 @@ ResolveRelativeTypePath::resolve_qual_seg (AST::QualifiedPathType &seg, seg.as_string ().c_str ()); return false; } - bool include_generic_args_in_path = false; - NodeId type_resolved_node - = ResolveType::go (seg.get_type ().get (), seg.get_node_id ()); + auto type = seg.get_type ().get (); + NodeId type_resolved_node = ResolveType::go (type, seg.get_node_id ()); if (type_resolved_node == UNKNOWN_NODEID) return false; - CanonicalPath impl_type_seg - = ResolveTypeToCanonicalPath::resolve (*seg.get_type ().get (), - include_generic_args_in_path); + const CanonicalPath *impl_type_seg = nullptr; + bool ok + = mappings->lookup_canonical_path (mappings->get_current_crate (), + type_resolved_node, &impl_type_seg); + rust_assert (ok); + if (!seg.has_as_clause ()) { - result = result.append (impl_type_seg); + result = result.append (*impl_type_seg); return true; } @@ -179,12 +195,15 @@ ResolveRelativeTypePath::resolve_qual_seg (AST::QualifiedPathType &seg, if (trait_resolved_node == UNKNOWN_NODEID) return false; - CanonicalPath trait_type_seg - = ResolveTypeToCanonicalPath::resolve (seg.get_as_type_path (), - include_generic_args_in_path); + const CanonicalPath *trait_type_seg = nullptr; + ok = mappings->lookup_canonical_path (mappings->get_current_crate (), + trait_resolved_node, &trait_type_seg); + rust_assert (ok); + CanonicalPath projection - = TraitImplProjection::resolve (seg.get_node_id (), trait_type_seg, - impl_type_seg); + = TraitImplProjection::resolve (seg.get_node_id (), *trait_type_seg, + *impl_type_seg); + result = result.append (projection); return true; } diff --git a/gcc/rust/resolve/rust-name-resolver.cc b/gcc/rust/resolve/rust-name-resolver.cc index fc1f361..fcf7190 100644 --- a/gcc/rust/resolve/rust-name-resolver.cc +++ b/gcc/rust/resolve/rust-name-resolver.cc @@ -34,6 +34,12 @@ _R.push_back (builtin_type); \ tyctx->insert_builtin (_TY->get_ref (), builtin_type->get_node_id (), \ _TY); \ + mappings->insert_node_to_hir (mappings->get_current_crate (), \ + builtin_type->get_node_id (), \ + _TY->get_ref ()); \ + mappings->insert_canonical_path ( \ + mappings->get_current_crate (), builtin_type->get_node_id (), \ + CanonicalPath::new_seg (builtin_type->get_node_id (), _X)); \ } \ while (0) @@ -165,6 +171,16 @@ Scope::iterate (std::function<bool (Rib *)> cb) } } +void +Scope::iterate (std::function<bool (const Rib *)> cb) const +{ + for (auto it = stack.rbegin (); it != stack.rend (); ++it) + { + if (!cb (*it)) + return; + } +} + Rib * Scope::peek () { @@ -200,6 +216,21 @@ Scope::append_reference_for_def (NodeId refId, NodeId defId) rust_assert (ok); } +bool +Scope::decl_was_declared_here (NodeId def) const +{ + bool found = false; + iterate ([&] (const Rib *r) -> bool { + if (r->decl_was_declared_here (def)) + { + found = true; + return false; + } + return true; + }); + return found; +} + Resolver::Resolver () : mappings (Analysis::Mappings::get ()), tyctx (TypeCheckContext::get ()), name_scope (Scope (mappings->get_current_crate ())), @@ -371,29 +402,6 @@ Resolver::generate_builtins () } void -Resolver::insert_new_definition (NodeId id, Definition def) -{ - auto it = name_definitions.find (id); - if (it != name_definitions.end ()) - { - rust_assert (it->second.is_equal (def)); - return; - } - name_definitions[id] = def; -} - -bool -Resolver::lookup_definition (NodeId id, Definition *def) -{ - auto it = name_definitions.find (id); - if (it == name_definitions.end ()) - return false; - - *def = it->second; - return true; -} - -void Resolver::insert_resolved_name (NodeId refId, NodeId defId) { resolved_names[refId] = defId; diff --git a/gcc/rust/resolve/rust-name-resolver.h b/gcc/rust/resolve/rust-name-resolver.h index ab7cb55..6b611b2 100644 --- a/gcc/rust/resolve/rust-name-resolver.h +++ b/gcc/rust/resolve/rust-name-resolver.h @@ -73,11 +73,13 @@ public: bool lookup (const CanonicalPath &ident, NodeId *id); void iterate (std::function<bool (Rib *)> cb); + void iterate (std::function<bool (const Rib *)> cb) const; Rib *peek (); void push (NodeId id); Rib *pop (); + bool decl_was_declared_here (NodeId def) const; void append_reference_for_def (NodeId refId, NodeId defId); CrateNum get_crate_num () const { return crate_num; } @@ -87,32 +89,6 @@ private: std::vector<Rib *> stack; }; -// This can map simple NodeIds for names to their parent node -// for example: -// -// var x = y + 1; -// -// say y has node id=1 and the plus_expression has id=2 -// then the Definition will have -// Definition { node=1, parent=2 } -// this will be used later to gather the ribs for the type inferences context -// -// if parent is UNKNOWN_NODEID then this is a root declaration -// say the var_decl hasa node_id=4; -// the parent could be a BLOCK_Expr node_id but lets make it UNKNOWN_NODE_ID -// so we know when it terminates -struct Definition -{ - NodeId node; - NodeId parent; - // add kind ? - - bool is_equal (const Definition &other) - { - return node == other.node && parent == other.parent; - } -}; - class Resolver { public: @@ -136,9 +112,6 @@ public: bool find_label_rib (NodeId id, Rib **rib); bool find_macro_rib (NodeId id, Rib **rib); - void insert_new_definition (NodeId id, Definition def); - bool lookup_definition (NodeId id, Definition *def); - void insert_resolved_name (NodeId refId, NodeId defId); bool lookup_resolved_name (NodeId refId, NodeId *defId); @@ -166,6 +139,35 @@ public: void set_unit_type_node_id (NodeId id) { unit_ty_node_id = id; } NodeId get_unit_type_node_id () { return unit_ty_node_id; } + void push_new_module_scope (NodeId module_id) + { + current_module_stack.push_back (module_id); + } + + void pop_module_scope () + { + rust_assert (!current_module_stack.empty ()); + current_module_stack.pop_back (); + } + + NodeId peek_current_module_scope () const + { + rust_assert (!current_module_stack.empty ()); + return current_module_stack.back (); + } + + NodeId peek_crate_module_scope () const + { + rust_assert (!current_module_stack.empty ()); + return current_module_stack.front (); + } + + NodeId peek_parent_module_scope () const + { + rust_assert (current_module_stack.size () > 1); + return current_module_stack.at (current_module_stack.size () - 2); + } + private: Resolver (); @@ -190,10 +192,6 @@ private: std::map<NodeId, Rib *> label_ribs; std::map<NodeId, Rib *> macro_ribs; - // map any Node to its Definition - // ie any name or type usage - std::map<NodeId, Definition> name_definitions; - // Rust uses DefIds to namespace these under a crate_num // but then it uses the def_collector to assign local_defids // to each ast node as well. not sure if this is going to fit @@ -211,6 +209,9 @@ private: std::map<NodeId, bool> decl_mutability; // map of resolved names and set of assignments to the decl std::map<NodeId, std::set<NodeId>> assignment_to_decl; + + // keep track of the current module scope ids + std::vector<NodeId> current_module_stack; }; } // namespace Resolver |