diff options
author | Philip Herron <philip.herron@embecosm.com> | 2022-06-03 15:12:00 +0100 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2022-06-10 17:09:34 +0100 |
commit | 7ca7362602d4e827ecbc39d5cfdf56df9044633b (patch) | |
tree | 7e149ddc7c9ffb0f72bcd4be2459abc7d1ee688a /gcc | |
parent | fc3ef6c4b1fad0d88a65043df8102437416b1df3 (diff) | |
download | gcc-7ca7362602d4e827ecbc39d5cfdf56df9044633b.zip gcc-7ca7362602d4e827ecbc39d5cfdf56df9044633b.tar.gz gcc-7ca7362602d4e827ecbc39d5cfdf56df9044633b.tar.bz2 |
This patch implements complex Path resolution
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 impl 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
Diffstat (limited to 'gcc')
37 files changed, 895 insertions, 812 deletions
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 69ad6eb..8f5657f 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -350,8 +350,16 @@ public: Location get_locus () const { return locus; } NodeId get_node_id () const { return node_id; } const std::string &get_segment_name () const { return segment_name; } - - // TODO: visitor pattern? + bool is_super_path_seg () const + { + return as_string ().compare ("super") == 0; + } + bool is_crate_path_seg () const + { + return as_string ().compare ("crate") == 0; + } + bool is_lower_self () const { return as_string ().compare ("self") == 0; } + bool is_big_self () const { return as_string ().compare ("Self") == 0; } }; // A simple path without generic or type arguments diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index 593f979..45d08bf 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -38,12 +38,6 @@ public: : segment_name (std::move (segment_name)), locus (locus) {} - /* TODO: insert check in constructor for this? Or is this a semantic error - * best handled then? */ - - /* TODO: does this require visitor? pretty sure this isn't polymorphic, but - * not entirely sure */ - // Creates an error PathIdentSegment. static PathIdentSegment create_error () { @@ -54,6 +48,11 @@ public: bool is_error () const { return segment_name.empty (); } std::string as_string () const { return segment_name; } + + bool is_super_segment () const { return as_string ().compare ("super") == 0; } + bool is_crate_segment () const { return as_string ().compare ("crate") == 0; } + bool is_lower_self () const { return as_string ().compare ("self") == 0; } + bool is_big_self () const { return as_string ().compare ("Self") == 0; } }; // A binding of an identifier to a type used in generic arguments in paths @@ -264,8 +263,23 @@ public: } PathIdentSegment &get_ident_segment () { return segment_name; } + const PathIdentSegment &get_ident_segment () const { return segment_name; } NodeId get_node_id () const { return node_id; } + + bool is_super_path_seg () const + { + return !has_generic_args () && get_ident_segment ().is_super_segment (); + } + + bool is_crate_path_seg () const + { + return !has_generic_args () && get_ident_segment ().is_crate_segment (); + } + bool is_lower_self_seg () const + { + return !has_generic_args () && get_ident_segment ().is_lower_self (); + } }; // AST node representing a pattern that involves a "path" - abstract base class @@ -397,6 +411,15 @@ protected: * ident-only segment) */ class TypePathSegment { +public: + enum SegmentType + { + REG, + GENERIC, + FUNCTION + }; + +private: PathIdentSegment ident_segment; Location locus; @@ -415,6 +438,8 @@ protected: public: virtual ~TypePathSegment () {} + virtual SegmentType get_type () const { return SegmentType::REG; } + // Unique pointer custom clone function std::unique_ptr<TypePathSegment> clone_type_path_segment () const { @@ -456,9 +481,20 @@ public: return has_separating_scope_resolution; } - PathIdentSegment get_ident_segment () { return ident_segment; }; + PathIdentSegment &get_ident_segment () { return ident_segment; }; + const PathIdentSegment &get_ident_segment () const { return ident_segment; }; NodeId get_node_id () const { return node_id; } + + bool is_crate_path_seg () const + { + return get_ident_segment ().is_crate_segment (); + } + bool is_super_path_seg () const + { + return get_ident_segment ().is_super_segment (); + } + bool is_big_self_seg () const { return get_ident_segment ().is_big_self (); } }; // Segment used in type path with generic args @@ -467,6 +503,8 @@ class TypePathSegmentGeneric : public TypePathSegment GenericArgs generic_args; public: + SegmentType get_type () const override { return SegmentType::GENERIC; } + bool has_generic_args () const { return generic_args.has_generic_args (); } bool is_ident_only () const override { return false; } @@ -620,6 +658,8 @@ class TypePathSegmentFunction : public TypePathSegment TypePathFunction function_path; public: + SegmentType get_type () const override { return SegmentType::FUNCTION; } + // Constructor with PathIdentSegment and TypePathFn TypePathSegmentFunction (PathIdentSegment ident_segment, bool has_separating_scope_resolution, diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc index 3de80d9..8fa3fa1 100644 --- a/gcc/rust/backend/rust-compile-base.cc +++ b/gcc/rust/backend/rust-compile-base.cc @@ -333,39 +333,33 @@ std::vector<Bvariable *> HIRCompileBase::compile_locals_for_block (Context *ctx, Resolver::Rib &rib, tree fndecl) { + CrateNum crate = ctx->get_mappings ()->get_current_crate (); + std::vector<Bvariable *> locals; for (auto it : rib.get_declarations ()) { - auto node_id = it.first; - - Resolver::Definition d; - bool ok = ctx->get_resolver ()->lookup_definition (node_id, &d); - rust_assert (ok); - - HIR::Stmt *decl = nullptr; - if (!ctx->get_mappings ()->resolve_nodeid_to_stmt (d.parent, &decl)) - { - // might be an extern block see fix for - // https://github.com/Rust-GCC/gccrs/issues/976 - continue; - } - - // if its a function we extract this out side of this fn context - // and it is not a local to this function - bool is_item = ctx->get_mappings ()->lookup_hir_item ( - decl->get_mappings ().get_crate_num (), - decl->get_mappings ().get_hirid ()) - != nullptr; - if (is_item) - { - HIR::Item *item = static_cast<HIR::Item *> (decl); - CompileItem::compile (item, ctx); - } - - Bvariable *compiled = CompileVarDecl::compile (fndecl, decl, ctx); + NodeId node_id = it.first; + HirId ref = UNKNOWN_HIRID; + if (!ctx->get_mappings ()->lookup_node_to_hir (crate, node_id, &ref)) + continue; + + // we only care about local patterns + HIR::Pattern *pattern + = ctx->get_mappings ()->lookup_hir_pattern (crate, ref); + if (pattern == nullptr) + continue; + + // lookup the type + TyTy::BaseType *tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (ref, &tyty)) + continue; + + // compile the local + tree type = TyTyResolveCompile::compile (ctx, tyty); + Bvariable *compiled + = CompileVarDecl::compile (fndecl, type, pattern, ctx); locals.push_back (compiled); - }; - + } return locals; } @@ -482,7 +476,9 @@ HIRCompileBase::compile_function ( compiled_param_type, param_locus); param_vars.push_back (compiled_param_var); - ctx->insert_var_decl (referenced_param.get_mappings ().get_hirid (), + + const HIR::Pattern ¶m_pattern = *referenced_param.get_param_name (); + ctx->insert_var_decl (param_pattern.get_pattern_mappings ().get_hirid (), compiled_param_var); } diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index b7dad12..b153451 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -1432,16 +1432,6 @@ CompileExpr::visit (HIR::IdentifierExpr &expr) NodeId ref_node_id = UNKNOWN_NODEID; if (ctx->get_resolver ()->lookup_resolved_name (ast_node_id, &ref_node_id)) { - // these ref_node_ids will resolve to a pattern declaration but we are - // interested in the definition that this refers to get the parent id - Resolver::Definition def; - if (!ctx->get_resolver ()->lookup_definition (ref_node_id, &def)) - { - rust_error_at (expr.get_locus (), - "unknown reference for resolved name"); - return; - } - ref_node_id = def.parent; is_value = true; } else if (!ctx->get_resolver ()->lookup_resolved_type (ast_node_id, diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 593e1f9..3b729c7 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -512,8 +512,8 @@ public: void visit (HIR::FieldAccessExpr &expr) override { - tree receiver_ref - = CompileExpr::Compile (expr.get_receiver_expr ().get (), ctx); + HIR::Expr *receiver_expr = expr.get_receiver_expr ().get (); + tree receiver_ref = CompileExpr::Compile (receiver_expr, ctx); // resolve the receiver back to ADT type TyTy::BaseType *receiver = nullptr; diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index 4423912..2cf81e0 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -53,22 +53,12 @@ ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment, // need to look up the reference for this identifier NodeId ref_node_id = UNKNOWN_NODEID; - if (ctx->get_resolver ()->lookup_resolved_name (mappings.get_nodeid (), - &ref_node_id)) + if (!ctx->get_resolver ()->lookup_resolved_name (mappings.get_nodeid (), + &ref_node_id)) { - Resolver::Definition def; - if (!ctx->get_resolver ()->lookup_definition (ref_node_id, &def)) - { - rust_error_at (expr_locus, "unknown reference for resolved name"); - return error_mark_node; - } - ref_node_id = def.parent; - } + // this can fail because it might be a Constructor for something + // in that case the caller should attempt ResolvePathType::Compile - // this can fail because it might be a Constructor for something - // in that case the caller should attempt ResolvePathType::Compile - if (ref_node_id == UNKNOWN_NODEID) - { // it might be an enum data-less enum variant if (lookup->get_kind () != TyTy::TypeKind::ADT) return error_mark_node; diff --git a/gcc/rust/backend/rust-compile-stmt.h b/gcc/rust/backend/rust-compile-stmt.h index 5f17777..aa17a4a 100644 --- a/gcc/rust/backend/rust-compile-stmt.h +++ b/gcc/rust/backend/rust-compile-stmt.h @@ -51,9 +51,11 @@ public: if (!stmt.has_init_expr ()) return; + const HIR::Pattern &stmt_pattern = *stmt.get_pattern (); + HirId stmt_id = stmt_pattern.get_pattern_mappings ().get_hirid (); + TyTy::BaseType *ty = nullptr; - if (!ctx->get_tyctx ()->lookup_type (stmt.get_mappings ().get_hirid (), - &ty)) + if (!ctx->get_tyctx ()->lookup_type (stmt_id, &ty)) { // FIXME this should be an assertion instead rust_fatal_error (stmt.get_locus (), @@ -62,7 +64,7 @@ public: } Bvariable *var = nullptr; - if (!ctx->lookup_var_decl (stmt.get_mappings ().get_hirid (), &var)) + if (!ctx->lookup_var_decl (stmt_id, &var)) { // FIXME this should be an assertion instead and use error mark node rust_fatal_error (stmt.get_locus (), diff --git a/gcc/rust/backend/rust-compile-var-decl.h b/gcc/rust/backend/rust-compile-var-decl.h index 2dab39e..e2ee05b 100644 --- a/gcc/rust/backend/rust-compile-var-decl.h +++ b/gcc/rust/backend/rust-compile-var-decl.h @@ -25,36 +25,19 @@ namespace Rust { namespace Compile { -class CompileVarDecl : public HIRCompileBase, - public HIR::HIRPatternVisitor, - public HIR::HIRStmtVisitor +class CompileVarDecl : public HIRCompileBase, public HIR::HIRPatternVisitor { using HIR::HIRPatternVisitor::visit; - using HIR::HIRStmtVisitor::visit; public: - static ::Bvariable *compile (tree fndecl, HIR::Stmt *stmt, Context *ctx) + static ::Bvariable *compile (tree fndecl, tree translated_type, + HIR::Pattern *pattern, Context *ctx) { - CompileVarDecl compiler (ctx, fndecl); - stmt->accept_vis (compiler); - ctx->insert_var_decl (stmt->get_mappings ().get_hirid (), - compiler.compiled_variable); + CompileVarDecl compiler (ctx, fndecl, translated_type); + pattern->accept_vis (compiler); return compiler.compiled_variable; } - void visit (HIR::LetStmt &stmt) override - { - locus = stmt.get_locus (); - TyTy::BaseType *resolved_type = nullptr; - bool ok = ctx->get_tyctx ()->lookup_type (stmt.get_mappings ().get_hirid (), - &resolved_type); - rust_assert (ok); - - translated_type = TyTyResolveCompile::compile (ctx, resolved_type); - stmt.get_pattern ()->accept_vis ( - static_cast<HIR::HIRPatternVisitor &> (*this)); - } - void visit (HIR::IdentifierPattern &pattern) override { if (!pattern.is_mut ()) @@ -63,7 +46,10 @@ public: compiled_variable = ctx->get_backend ()->local_variable (fndecl, pattern.get_identifier (), translated_type, NULL /*decl_var*/, - locus); + pattern.get_locus ()); + + HirId stmt_id = pattern.get_pattern_mappings ().get_hirid (); + ctx->insert_var_decl (stmt_id, compiled_variable); } void visit (HIR::WildcardPattern &pattern) override @@ -72,7 +58,11 @@ public: compiled_variable = ctx->get_backend ()->local_variable (fndecl, "_", translated_type, - NULL /*decl_var*/, locus); + NULL /*decl_var*/, + pattern.get_locus ()); + + HirId stmt_id = pattern.get_pattern_mappings ().get_hirid (); + ctx->insert_var_decl (stmt_id, compiled_variable); } // Empty visit for unused Pattern HIR nodes. @@ -87,41 +77,15 @@ public: void visit (HIR::TuplePattern &) override {} void visit (HIR::TupleStructPattern &) override {} - // Empty visit for unused Stmt HIR nodes. - void visit (HIR::EnumItemTuple &) override {} - void visit (HIR::EnumItemStruct &) override {} - void visit (HIR::EnumItem &item) override {} - void visit (HIR::TupleStruct &tuple_struct) override {} - void visit (HIR::EnumItemDiscriminant &) override {} - void visit (HIR::TypePathSegmentFunction &segment) override {} - void visit (HIR::TypePath &path) override {} - void visit (HIR::QualifiedPathInType &path) override {} - void visit (HIR::Module &module) override {} - void visit (HIR::ExternCrate &crate) override {} - void visit (HIR::UseDeclaration &use_decl) override {} - void visit (HIR::Function &function) override {} - void visit (HIR::TypeAlias &type_alias) override {} - void visit (HIR::StructStruct &struct_item) override {} - void visit (HIR::Enum &enum_item) override {} - void visit (HIR::Union &union_item) override {} - void visit (HIR::ConstantItem &const_item) override {} - void visit (HIR::StaticItem &static_item) override {} - void visit (HIR::Trait &trait) override {} - void visit (HIR::ImplBlock &impl) override {} - void visit (HIR::ExternBlock &block) override {} - void visit (HIR::EmptyStmt &stmt) override {} - void visit (HIR::ExprStmtWithoutBlock &stmt) override {} - void visit (HIR::ExprStmtWithBlock &stmt) override {} - private: - CompileVarDecl (Context *ctx, tree fndecl) - : HIRCompileBase (ctx), fndecl (fndecl), translated_type (error_mark_node), + CompileVarDecl (Context *ctx, tree fndecl, tree translated_type) + : HIRCompileBase (ctx), fndecl (fndecl), translated_type (translated_type), compiled_variable (ctx->get_backend ()->error_variable ()) {} tree fndecl; tree translated_type; - Location locus; + Bvariable *compiled_variable; }; diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc index b3b0ee8..0072d30 100644 --- a/gcc/rust/hir/rust-ast-lower.cc +++ b/gcc/rust/hir/rust-ast-lower.cc @@ -79,7 +79,7 @@ ASTLowering::go () auto mappings = Analysis::Mappings::get (); auto crate_num = mappings->get_current_crate (); - Analysis::NodeMapping mapping (crate_num, UNKNOWN_NODEID, + Analysis::NodeMapping mapping (crate_num, astCrate.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); diff --git a/gcc/rust/lint/rust-lint-marklive.cc b/gcc/rust/lint/rust-lint-marklive.cc index 3776aea..2b01abc 100644 --- a/gcc/rust/lint/rust-lint-marklive.cc +++ b/gcc/rust/lint/rust-lint-marklive.cc @@ -179,16 +179,10 @@ MarkLive::visit_path_segment (HIR::PathExprSegment seg) // // We should mark them alive all and ignoring other kind of segments. // If the segment we dont care then just return false is fine - if (resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) + if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) { - Resolver::Definition def; - bool ok = resolver->lookup_definition (ref_node_id, &def); - rust_assert (ok); - ref_node_id = def.parent; - } - else if (!resolver->lookup_resolved_type (ast_node_id, &ref_node_id)) - { - return false; + if (!resolver->lookup_resolved_type (ast_node_id, &ref_node_id)) + return false; } HirId ref; bool ok = mappings->lookup_node_to_hir (seg.get_mappings ().get_crate_num (), @@ -300,16 +294,7 @@ MarkLive::mark_hir_id (HirId id) void MarkLive::find_ref_node_id (NodeId ast_node_id, NodeId &ref_node_id) { - if (resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) - { - // these ref_node_ids will resolve to a pattern declaration but we are - // interested in the definition that this refers to get the parent id - Resolver::Definition def; - bool ok = resolver->lookup_definition (ref_node_id, &def); - rust_assert (ok); - ref_node_id = def.parent; - } - else + if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) { bool ok = resolver->lookup_resolved_type (ast_node_id, &ref_node_id); rust_assert (ok); diff --git a/gcc/rust/privacy/rust-visibility-resolver.cc b/gcc/rust/privacy/rust-visibility-resolver.cc index 421dff0..fdae5aa 100644 --- a/gcc/rust/privacy/rust-visibility-resolver.cc +++ b/gcc/rust/privacy/rust-visibility-resolver.cc @@ -71,12 +71,6 @@ VisibilityResolver::resolve_module_path (const HIR::SimplePath &restriction, // TODO: For the hint, can we point to the original item's definition if // present? - Resolver::Definition def; - rust_assert (resolver.lookup_definition (ref_node_id, &def)); - - // FIXME: Is that what we want? - ref_node_id = def.parent; - HirId ref; rust_assert ( mappings.lookup_node_to_hir (restriction.get_mappings ().get_crate_num (), 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 198c9c0..9f550ad 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.cc +++ b/gcc/rust/resolve/rust-ast-resolve-item.cc @@ -528,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); @@ -788,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 7a1458e..78b786a 100644 --- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h +++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h @@ -62,10 +62,6 @@ 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 ()); @@ -278,9 +274,7 @@ 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 (); @@ -302,9 +296,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 ()}); NodeId current_module = resolver->peek_current_module_scope (); mappings->insert_module_child_item (current_module, decl); @@ -325,17 +316,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 ()}); - - // 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); @@ -386,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); 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 8465162..169237a 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -81,6 +81,11 @@ 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); @@ -167,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; } @@ -188,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 23a9d82..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); @@ -183,6 +156,18 @@ public: 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 (); @@ -207,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 diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 0b0e5af..5706375 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -737,6 +737,9 @@ Session::parse_file (const char *filename) if (saw_errors ()) return; + // add the mappings to it + mappings->insert_hir_crate (&hir); + // type resolve Resolver::TypeResolution::Resolve (hir); if (options.dump_option_enabled (CompileOptions::TYPE_RESOLUTION_DUMP)) diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 8427cc9..e84f5e8 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -423,35 +423,14 @@ public: // then lookup the reference_node_id NodeId ref_node_id = UNKNOWN_NODEID; - if (resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) + if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) { - // these ref_node_ids will resolve to a pattern declaration but we are - // interested in the definition that this refers to get the parent id - Definition def; - if (!resolver->lookup_definition (ref_node_id, &def)) - { - // FIXME - // this is an internal error - rust_error_at (expr.get_locus (), - "unknown reference for resolved name"); - return; - } - ref_node_id = def.parent; - } - else if (!resolver->lookup_resolved_type (ast_node_id, &ref_node_id)) - { - // FIXME - // this is an internal error - rust_error_at (expr.get_locus (), - "Failed to lookup type reference for node: %s", - expr.as_string ().c_str ()); - return; + resolver->lookup_resolved_type (ast_node_id, &ref_node_id); } if (ref_node_id == UNKNOWN_NODEID) { - // FIXME - // this is an internal error + // FIXME this needs to go away and just return error node rust_error_at (expr.get_locus (), "unresolved node: %s", expr.as_string ().c_str ()); return; diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc index 3823c57..a059611 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-path.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc @@ -67,6 +67,36 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr) // inherit the bound root->inherit_bounds ({specified_bound}); + // setup the associated types + const TraitReference *specified_bound_ref = specified_bound.get (); + auto candidates = TypeBoundsProbe::Probe (root); + AssociatedImplTrait *associated_impl_trait = nullptr; + for (auto &probed_bound : candidates) + { + const TraitReference *bound_trait_ref = probed_bound.first; + const HIR::ImplBlock *associated_impl = probed_bound.second; + + HirId impl_block_id = associated_impl->get_mappings ().get_hirid (); + AssociatedImplTrait *associated = nullptr; + bool found_impl_trait + = context->lookup_associated_trait_impl (impl_block_id, &associated); + if (found_impl_trait) + { + bool found_trait = specified_bound_ref->is_equal (*bound_trait_ref); + bool found_self = associated->get_self ()->can_eq (root, false); + if (found_trait && found_self) + { + associated_impl_trait = associated; + break; + } + } + } + + if (associated_impl_trait != nullptr) + { + associated_impl_trait->setup_associated_types (root, specified_bound); + } + // lookup the associated item from the specified bound HIR::PathExprSegment &item_seg = expr.get_segments ().at (0); HIR::PathIdentSegment item_seg_identifier = item_seg.get_segment (); @@ -81,28 +111,6 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr) // infer the root type infered = item.get_tyty_for_receiver (root); - // we need resolve to the impl block - NodeId impl_resolved_id = UNKNOWN_NODEID; - bool have_associated_impl = resolver->lookup_resolved_name ( - qual_path_type.get_mappings ().get_nodeid (), &impl_resolved_id); - AssociatedImplTrait *lookup_associated = nullptr; - if (have_associated_impl) - { - HirId impl_block_id; - bool ok - = mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (), - impl_resolved_id, &impl_block_id); - rust_assert (ok); - - bool found_impl_trait - = context->lookup_associated_trait_impl (impl_block_id, - &lookup_associated); - if (found_impl_trait) - { - lookup_associated->setup_associated_types (root, specified_bound); - } - } - // turbo-fish segment path::<ty> if (item_seg.has_generic_args ()) { @@ -145,7 +153,9 @@ TypeCheckExpr::visit (HIR::PathInExpression &expr) return; if (tyseg->needs_generic_substitutions ()) - tyseg = SubstMapper::InferSubst (tyseg, expr.get_locus ()); + { + tyseg = SubstMapper::InferSubst (tyseg, expr.get_locus ()); + } bool fully_resolved = offset == expr.get_segments ().size (); if (fully_resolved) @@ -162,30 +172,19 @@ TyTy::BaseType * TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset, NodeId *root_resolved_node_id) { + TyTy::BaseType *root_tyty = nullptr; *offset = 0; for (size_t i = 0; i < expr.get_num_segments (); i++) { HIR::PathExprSegment &seg = expr.get_segments ().at (i); + bool have_more_segments = (expr.get_num_segments () - 1 != i); + bool is_root = *offset == 0; NodeId ast_node_id = seg.get_mappings ().get_nodeid (); // then lookup the reference_node_id NodeId ref_node_id = UNKNOWN_NODEID; - if (resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) - { - // these ref_node_ids will resolve to a pattern declaration but we - // are interested in the definition that this refers to get the - // parent id - Definition def; - if (!resolver->lookup_definition (ref_node_id, &def)) - { - rust_error_at (expr.get_locus (), - "unknown reference for resolved name"); - return new TyTy::ErrorType (expr.get_mappings ().get_hirid ()); - } - ref_node_id = def.parent; - } - else + if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) { resolver->lookup_resolved_type (ast_node_id, &ref_node_id); } @@ -193,6 +192,12 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset, // ref_node_id is the NodeId that the segments refers to. if (ref_node_id == UNKNOWN_NODEID) { + if (root_tyty != nullptr && *offset > 0) + { + // then we can let the impl path probe take over now + return root_tyty; + } + rust_error_at (seg.get_locus (), "failed to type resolve root segment"); return new TyTy::ErrorType (expr.get_mappings ().get_hirid ()); @@ -217,7 +222,8 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset, = (nullptr != mappings->lookup_module (expr.get_mappings ().get_crate_num (), ref)); - if (seg_is_module) + auto seg_is_crate = mappings->is_local_hirid_crate (ref); + if (seg_is_module || seg_is_crate) { // A::B::C::this_is_a_module::D::E::F // ^^^^^^^^^^^^^^^^ @@ -239,8 +245,33 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset, TyTy::BaseType *lookup = nullptr; if (!context->lookup_type (ref, &lookup)) { - rust_error_at (seg.get_locus (), "failed to resolve root segment"); - return new TyTy::ErrorType (expr.get_mappings ().get_hirid ()); + if (is_root) + { + rust_error_at (seg.get_locus (), + "failed to resolve root segment"); + return new TyTy::ErrorType (expr.get_mappings ().get_hirid ()); + } + return root_tyty; + } + + // if we have a previous segment type + if (root_tyty != nullptr) + { + // if this next segment needs substitution we must apply the + // previous type arguments + // + // such as: GenericStruct::<_>::new(123, 456) + if (lookup->needs_generic_substitutions ()) + { + if (!root_tyty->needs_generic_substitutions ()) + { + auto used_args_in_prev_segment + = GetUsedSubstArgs::From (root_tyty); + lookup + = SubstMapperInternal::Resolve (lookup, + used_args_in_prev_segment); + } + } } // turbo-fish segment path::<ty> @@ -248,21 +279,24 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset, { if (!lookup->can_substitute ()) { - rust_error_at (seg.get_locus (), + rust_error_at (expr.get_locus (), "substitutions not supported for %s", - lookup->as_string ().c_str ()); - return new TyTy::ErrorType (lookup->get_ref ()); + root_tyty->as_string ().c_str ()); + return new TyTy::ErrorType (expr.get_mappings ().get_hirid ()); } - lookup = SubstMapper::Resolve (lookup, seg.get_locus (), + + lookup = SubstMapper::Resolve (lookup, expr.get_locus (), &seg.get_generic_args ()); + if (lookup->get_kind () == TyTy::TypeKind::ERROR) + return new TyTy::ErrorType (expr.get_mappings ().get_hirid ()); } *root_resolved_node_id = ref_node_id; *offset = *offset + 1; - return lookup; + root_tyty = lookup; } - return new TyTy::ErrorType (expr.get_mappings ().get_hirid ()); + return root_tyty; } void @@ -423,22 +457,17 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id, context->insert_receiver (expr_mappings.get_hirid (), prev_segment); - // lookup if the name resolver was able to canonically resolve this or not - NodeId path_resolved_id = UNKNOWN_NODEID; - if (resolver->lookup_resolved_name (expr_mappings.get_nodeid (), - &path_resolved_id)) + // name scope first + if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id)) { - rust_assert (path_resolved_id == resolved_node_id); + resolver->insert_resolved_name (expr_mappings.get_nodeid (), + resolved_node_id); } // check the type scope - else if (resolver->lookup_resolved_type (expr_mappings.get_nodeid (), - &path_resolved_id)) + else if (resolver->get_type_scope ().decl_was_declared_here ( + resolved_node_id)) { - rust_assert (path_resolved_id == resolved_node_id); - } - else - { - resolver->insert_resolved_name (expr_mappings.get_nodeid (), + resolver->insert_resolved_type (expr_mappings.get_nodeid (), resolved_node_id); } diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc index be3b8e4..1018f81 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc @@ -350,5 +350,11 @@ TypeCheckPattern::visit (HIR::RangePattern &pattern) infered = upper->unify (lower); } +void +TypeCheckPattern::visit (HIR::IdentifierPattern &pattern) +{ + infered = parent; +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.h b/gcc/rust/typecheck/rust-hir-type-check-pattern.h index 03c4977..860aca9 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-pattern.h +++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.h @@ -58,6 +58,8 @@ public: void visit (HIR::RangePattern &pattern) override; + void visit (HIR::IdentifierPattern &pattern) override; + private: TypeCheckPattern (TyTy::BaseType *parent) : TypeCheckBase (), parent (parent), infered (nullptr) diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h index 327bffa..96e92b4 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h @@ -79,6 +79,7 @@ public: infered = TyTy::TupleType::get_unit_type (stmt.get_mappings ().get_hirid ()); + const HIR::Pattern &stmt_pattern = *stmt.get_pattern (); TyTy::BaseType *init_expr_ty = nullptr; if (stmt.has_init_expr ()) { @@ -86,10 +87,8 @@ public: if (init_expr_ty->get_kind () == TyTy::TypeKind::ERROR) return; - init_expr_ty = init_expr_ty->clone (); - auto ref = init_expr_ty->get_ref (); - init_expr_ty->set_ref (stmt.get_mappings ().get_hirid ()); - init_expr_ty->append_reference (ref); + init_expr_ty->append_reference ( + stmt_pattern.get_pattern_mappings ().get_hirid ()); } TyTy::BaseType *specified_ty = nullptr; @@ -99,38 +98,35 @@ public: // let x:i32 = 123; if (specified_ty != nullptr && init_expr_ty != nullptr) { - auto unified_ty = specified_ty->coerce (init_expr_ty); - if (unified_ty->get_kind () == TyTy::TypeKind::ERROR) - return; - - context->insert_type (stmt.get_mappings (), specified_ty); + // FIXME use this result and look at the regressions + specified_ty->coerce (init_expr_ty); + context->insert_type (stmt_pattern.get_pattern_mappings (), + specified_ty); } else { // let x:i32; if (specified_ty != nullptr) { - context->insert_type (stmt.get_mappings (), specified_ty); + context->insert_type (stmt_pattern.get_pattern_mappings (), + specified_ty); } // let x = 123; else if (init_expr_ty != nullptr) { - context->insert_type (stmt.get_mappings (), init_expr_ty); + context->insert_type (stmt_pattern.get_pattern_mappings (), + init_expr_ty); } // let x; else { context->insert_type ( - stmt.get_mappings (), - new TyTy::InferType (stmt.get_mappings ().get_hirid (), - TyTy::InferType::InferTypeKind::GENERAL, - stmt.get_locus ())); + stmt_pattern.get_pattern_mappings (), + new TyTy::InferType ( + stmt_pattern.get_pattern_mappings ().get_hirid (), + TyTy::InferType::InferTypeKind::GENERAL, stmt.get_locus ())); } } - - TyTy::BaseType *lookup = nullptr; - bool ok = context->lookup_type (stmt.get_mappings ().get_hirid (), &lookup); - rust_assert (ok); } void visit (HIR::TupleStruct &struct_decl) override diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index 85de3a1..a5597be 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -151,6 +151,36 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path) // inherit the bound root->inherit_bounds ({specified_bound}); + // setup the associated types + const TraitReference *specified_bound_ref = specified_bound.get (); + auto candidates = TypeBoundsProbe::Probe (root); + AssociatedImplTrait *associated_impl_trait = nullptr; + for (auto &probed_bound : candidates) + { + const TraitReference *bound_trait_ref = probed_bound.first; + const HIR::ImplBlock *associated_impl = probed_bound.second; + + HirId impl_block_id = associated_impl->get_mappings ().get_hirid (); + AssociatedImplTrait *associated = nullptr; + bool found_impl_trait + = context->lookup_associated_trait_impl (impl_block_id, &associated); + if (found_impl_trait) + { + bool found_trait = specified_bound_ref->is_equal (*bound_trait_ref); + bool found_self = associated->get_self ()->can_eq (root, false); + if (found_trait && found_self) + { + associated_impl_trait = associated; + break; + } + } + } + + if (associated_impl_trait != nullptr) + { + associated_impl_trait->setup_associated_types (root, specified_bound); + } + // lookup the associated item from the specified bound std::unique_ptr<HIR::TypePathSegment> &item_seg = path.get_associated_segment (); @@ -166,28 +196,6 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path) // infer the root type translated = item.get_tyty_for_receiver (root); - // we need resolve to the impl block - NodeId impl_resolved_id = UNKNOWN_NODEID; - bool have_associated_impl = resolver->lookup_resolved_name ( - qual_path_type.get_mappings ().get_nodeid (), &impl_resolved_id); - AssociatedImplTrait *lookup_associated = nullptr; - if (have_associated_impl) - { - HirId impl_block_id; - bool ok - = mappings->lookup_node_to_hir (path.get_mappings ().get_crate_num (), - impl_resolved_id, &impl_block_id); - rust_assert (ok); - - bool found_impl_trait - = context->lookup_associated_trait_impl (impl_block_id, - &lookup_associated); - if (found_impl_trait) - { - lookup_associated->setup_associated_types (root, specified_bound); - } - } - // turbo-fish segment path::<ty> if (item_seg->get_type () == HIR::TypePathSegment::SegmentType::GENERIC) { @@ -245,21 +253,7 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset, // then lookup the reference_node_id NodeId ref_node_id = UNKNOWN_NODEID; - if (resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) - { - // these ref_node_ids will resolve to a pattern declaration but we - // are interested in the definition that this refers to get the - // parent id - Definition def; - if (!resolver->lookup_definition (ref_node_id, &def)) - { - rust_error_at (path.get_locus (), - "unknown reference for resolved name"); - return new TyTy::ErrorType (path.get_mappings ().get_hirid ()); - } - ref_node_id = def.parent; - } - else + if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) { resolver->lookup_resolved_type (ast_node_id, &ref_node_id); } @@ -270,14 +264,15 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset, if (is_root) { rust_error_at (seg->get_locus (), - "failed to type resolve root segment"); + "unknown reference for resolved name: %<%s%>", + seg->get_ident_segment ().as_string ().c_str ()); return new TyTy::ErrorType (path.get_mappings ().get_hirid ()); } return root_tyty; } // node back to HIR - HirId ref; + HirId ref = UNKNOWN_HIRID; if (!mappings->lookup_node_to_hir (path.get_mappings ().get_crate_num (), ref_node_id, &ref)) { @@ -300,8 +295,8 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset, = (nullptr != mappings->lookup_module (path.get_mappings ().get_crate_num (), ref)); - - if (seg_is_module) + auto seg_is_crate = mappings->is_local_hirid_crate (ref); + if (seg_is_module || seg_is_crate) { // A::B::C::this_is_a_module::D::E::F // ^^^^^^^^^^^^^^^^ @@ -498,8 +493,19 @@ TypeCheckType::resolve_segments ( } else { - resolver->insert_resolved_type (expr_mappings.get_nodeid (), - resolved_node_id); + // name scope first + if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id)) + { + resolver->insert_resolved_name (expr_mappings.get_nodeid (), + 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_mappings.get_nodeid (), + resolved_node_id); + } } return tyseg; diff --git a/gcc/rust/typecheck/rust-tycheck-dump.h b/gcc/rust/typecheck/rust-tycheck-dump.h index ab7f59a..36963e5 100644 --- a/gcc/rust/typecheck/rust-tycheck-dump.h +++ b/gcc/rust/typecheck/rust-tycheck-dump.h @@ -128,7 +128,7 @@ public: void visit (HIR::LetStmt &stmt) override { dump += "let " + stmt.get_pattern ()->as_string () + ":" - + type_string (stmt.get_mappings ()); + + type_string (stmt.get_pattern ()->get_pattern_mappings ()); if (stmt.has_init_expr ()) { dump += " = "; diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index f9932a4..c21b681 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -201,6 +201,18 @@ Mappings::get_hir_crate (CrateNum crateNum) return it->second; } +bool +Mappings::is_local_hirid_crate (HirId crateNum) +{ + for (const auto &it : hirCrateMappings) + { + const HIR::Crate *crate = it.second; + if (crate->get_mappings ().get_hirid () == crateNum) + return true; + } + return false; +} + void Mappings::insert_hir_crate (HIR::Crate *crate) { @@ -208,6 +220,9 @@ Mappings::insert_hir_crate (HIR::Crate *crate) rust_assert (get_hir_crate (crateNum) == nullptr); hirCrateMappings[crateNum] = crate; + insert_node_to_hir (crate->get_mappings ().get_crate_num (), + crate->get_mappings ().get_nodeid (), + crate->get_mappings ().get_hirid ()); } void @@ -908,6 +923,25 @@ Mappings::lookup_module_chidren_items (NodeId module) return Optional<std::vector<Resolver::CanonicalPath> &>::some (it->second); } +Optional<Resolver::CanonicalPath &> +Mappings::lookup_module_child (NodeId module, const std::string &item_name) +{ + Optional<std::vector<Resolver::CanonicalPath> &> children + = lookup_module_chidren_items (module); + if (children.is_none ()) + return Optional<Resolver::CanonicalPath &>::none (); + + // lookup the children to match the name if we can + for (auto &child : children.get ()) + { + const std::string &raw_identifier = child.get (); + bool found = raw_identifier.compare (item_name) == 0; + if (found) + return Optional<Resolver::CanonicalPath &>::some (child); + } + return Optional<Resolver::CanonicalPath &>::none (); +} + void Mappings::insert_child_item_to_parent_module_mapping (NodeId child_item, NodeId parent_module) @@ -925,5 +959,11 @@ Mappings::lookup_parent_module (NodeId child_item) return Optional<NodeId>::some (it->second); } +bool +Mappings::node_is_module (NodeId query) +{ + return module_child_items.find (query) != module_child_items.end (); +} + } // namespace Analysis } // namespace Rust diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h index a48d4be..4360ae2 100644 --- a/gcc/rust/util/rust-hir-map.h +++ b/gcc/rust/util/rust-hir-map.h @@ -122,6 +122,7 @@ public: void insert_ast_crate (AST::Crate *crate); HIR::Crate *get_hir_crate (CrateNum crateNum); + bool is_local_hirid_crate (HirId crateNum); void insert_hir_crate (HIR::Crate *crate); void insert_defid_mapping (DefId id, HIR::Item *item); @@ -329,10 +330,13 @@ public: void insert_module_child_item (NodeId module, Resolver::CanonicalPath item); Optional<std::vector<Resolver::CanonicalPath> &> lookup_module_chidren_items (NodeId module); + Optional<Resolver::CanonicalPath &> + lookup_module_child (NodeId module, const std::string &item_name); void insert_child_item_to_parent_module_mapping (NodeId child_item, NodeId parent_module); Optional<NodeId> lookup_parent_module (NodeId child_item); + bool node_is_module (NodeId query); private: Mappings (); diff --git a/gcc/testsuite/rust/compile/complex-path1.rs b/gcc/testsuite/rust/compile/complex-path1.rs new file mode 100644 index 0000000..54011bd --- /dev/null +++ b/gcc/testsuite/rust/compile/complex-path1.rs @@ -0,0 +1,18 @@ +// { dg-additional-options "-w" } +mod a { + pub fn foo() {} +} + +mod b { + pub fn foo() { + super::a::foo(); + } +} + +mod foo { + pub struct bar(pub i32); +} + +fn test() -> crate::foo::bar { + foo::bar(123) +} diff --git a/gcc/testsuite/rust/compile/issue-1251.rs b/gcc/testsuite/rust/compile/issue-1251.rs new file mode 100644 index 0000000..b16e1e0 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-1251.rs @@ -0,0 +1,14 @@ +// { dg-additional-options "-w" } +mod a { + pub mod b { + pub mod a { + pub fn foo() {} + } + } + + pub fn bidule() { + crate::a::b::a::foo() + } +} + +fn main() {} |