diff options
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() {} |