From a716f283726ee613186f2ba108927f7997be8361 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Mon, 28 Apr 2025 15:20:52 +0200 Subject: [PATCH 1/9] Fix test to match rust 2018 behavior Relative module path are only permitted with rust 2015 edition. gcc/testsuite/ChangeLog: * rust/compile/privacy5.rs: Convert test to 2018 edition. Signed-off-by: Pierre-Emmanuel Patry --- gcc/testsuite/rust/compile/privacy5.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gcc/testsuite/rust/compile/privacy5.rs b/gcc/testsuite/rust/compile/privacy5.rs index 16445ddc3e3b..a10929a8c47f 100644 --- a/gcc/testsuite/rust/compile/privacy5.rs +++ b/gcc/testsuite/rust/compile/privacy5.rs @@ -1,11 +1,12 @@ mod orange { mod green { struct Foo; - pub(in orange) struct Bar; + pub(in crate::orange) struct Bar; pub struct Baz; } - fn brown() {// E0603 + fn brown() { + // E0603 let _ = green::Foo; // { dg-error "definition is private in this context" } let _ = green::Bar; let _ = green::Baz; From 9719f98fdaa35ae55d8b5d1c23fea59f1a676e0a Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Mon, 28 Apr 2025 17:22:38 +0200 Subject: [PATCH 2/9] Resolve visibility path when it exists gcc/rust/ChangeLog: * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Resolve visibility path when it exists. * resolve/rust-late-name-resolver-2.0.h: Add function prototype. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/resolve/rust-late-name-resolver-2.0.cc | 12 ++++++++++++ gcc/rust/resolve/rust-late-name-resolver-2.0.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index 5f215db0a72b..d32bbeb1dc65 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -537,6 +537,18 @@ Late::visit (AST::StructStruct &s) ctx.scoped (Rib::Kind::Item, s.get_node_id (), s_vis); } +void +Late::visit (AST::Visibility &vis) +{ + if (vis.has_path ()) + { + auto resolved = ctx.resolve_path (vis.get_path (), Namespace::Types); + + ctx.map_usage (Usage (vis.get_path ().get_node_id ()), + Definition (resolved->get_node_id ())); + } +} + void Late::visit (AST::StructExprStruct &s) { diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h b/gcc/rust/resolve/rust-late-name-resolver-2.0.h index 896b72ce4399..724b48975395 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h @@ -52,6 +52,8 @@ class Late : public DefaultResolver void visit (AST::ForLoopExpr &) override; void visit (AST::IfLetExpr &) override; + void visit (AST::Visibility &vis) override; + // resolutions void visit (AST::IdentifierExpr &) override; void visit (AST::StructExprFieldIdentifier &) override; From a284eaf75210eb3888e8f9e6443c7a833d620958 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Mon, 28 Apr 2025 17:33:19 +0200 Subject: [PATCH 3/9] Make path optional in visibility gcc/rust/ChangeLog: * ast/rust-ast-collector.cc (TokenCollector::visit): Use getter. * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise. * ast/rust-ast.cc (Visibility::as_string): Likewise. * hir/rust-ast-lower.cc (translate_visibility): Likewise. * resolve/rust-ast-resolve-base.cc (ResolverBase::resolve_visibility): Likewise. * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Likewise. * ast/rust-ast.h: Make path optional and change getter name to reflect potential unavailability. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/ast/rust-ast-collector.cc | 2 +- gcc/rust/ast/rust-ast-visitor.cc | 3 ++- gcc/rust/ast/rust-ast.cc | 3 ++- gcc/rust/ast/rust-ast.h | 18 +++++++++++------- gcc/rust/hir/rust-ast-lower.cc | 3 ++- gcc/rust/resolve/rust-ast-resolve-base.cc | 2 +- .../resolve/rust-late-name-resolver-2.0.cc | 5 +++-- 7 files changed, 22 insertions(+), 14 deletions(-) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index f0fc4caad663..209b0fc290eb 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -245,7 +245,7 @@ TokenCollector::visit (Visibility &vis) push (Rust::Token::make (PUB, vis.get_locus ())); push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION)); push (Rust::Token::make (IN, UNDEF_LOCATION)); - visit (vis.get_path ()); + visit (vis.get_path_unchecked ()); push (Rust::Token::make (RIGHT_PAREN, UNDEF_LOCATION)); break; case Visibility::PRIV: diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index 7584d1af5bb1..29e70a72e405 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -755,7 +755,8 @@ DefaultASTVisitor::visit (AST::TypeBoundWhereClauseItem &item) void DefaultASTVisitor::visit (AST::Visibility &vis) { - visit (vis.get_path ()); + if (vis.has_path ()) + visit (vis.get_path_unchecked ()); } void diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index 494b21a1ba56..2fc517c67fb4 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -453,7 +453,8 @@ Visibility::as_string () const case PUB_SUPER: return std::string ("pub(super)"); case PUB_IN_PATH: - return std::string ("pub(in ") + in_path.as_string () + std::string (")"); + return std::string ("pub(in ") + get_path_unchecked ().as_string () + + std::string (")"); default: rust_unreachable (); } diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 9581dd57b739..c1856c282ee4 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -497,27 +497,31 @@ struct Visibility private: VisType vis_type; // Only assigned if vis_type is IN_PATH - SimplePath in_path; + tl::optional in_path; location_t locus; // should this store location info? -public: // Creates a Visibility - TODO make constructor protected or private? - Visibility (VisType vis_type, SimplePath in_path, location_t locus) + Visibility (VisType vis_type, tl::optional in_path, + location_t locus) : vis_type (vis_type), in_path (std::move (in_path)), locus (locus) {} +public: VisType get_vis_type () const { return vis_type; } // Returns whether visibility is in an error state. bool is_error () const { - return vis_type == PUB_IN_PATH && in_path.is_empty (); + return vis_type == PUB_IN_PATH && !in_path.has_value (); } // Returns whether a visibility has a path - bool has_path () const { return !is_error () && vis_type >= PUB_CRATE; } + bool has_path () const + { + return in_path.has_value () && vis_type >= PUB_CRATE; + } // Returns whether visibility is public or not. bool is_public () const { return vis_type != PRIV && !is_error (); } @@ -591,8 +595,8 @@ struct Visibility } std::string as_string () const; - const SimplePath &get_path () const { return in_path; } - SimplePath &get_path () { return in_path; } + const SimplePath &get_path_unchecked () const { return in_path.value (); } + SimplePath &get_path_unchecked () { return in_path.value (); } protected: // Clone function implementation - not currently virtual but may be if diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc index f70c7878216e..61a7083442d5 100644 --- a/gcc/rust/hir/rust-ast-lower.cc +++ b/gcc/rust/hir/rust-ast-lower.cc @@ -52,7 +52,8 @@ translate_visibility (const AST::Visibility &vis) case AST::Visibility::PUB_SUPER: case AST::Visibility::PUB_IN_PATH: return Visibility (Visibility::VisType::RESTRICTED, - ASTLoweringSimplePath::translate (vis.get_path ()), + ASTLoweringSimplePath::translate ( + vis.get_path_unchecked ()), vis.get_locus ()); break; } diff --git a/gcc/rust/resolve/rust-ast-resolve-base.cc b/gcc/rust/resolve/rust-ast-resolve-base.cc index 397abf5b9a2c..db978882f320 100644 --- a/gcc/rust/resolve/rust-ast-resolve-base.cc +++ b/gcc/rust/resolve/rust-ast-resolve-base.cc @@ -30,7 +30,7 @@ ResolverBase::resolve_visibility (const AST::Visibility &vis) { if (vis.has_path ()) { - auto path = vis.get_path (); + auto path = vis.get_path_unchecked (); ResolvePath::go (path); // Do we need to lookup something here? diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index d32bbeb1dc65..50fa9fc3c04e 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -542,9 +542,10 @@ Late::visit (AST::Visibility &vis) { if (vis.has_path ()) { - auto resolved = ctx.resolve_path (vis.get_path (), Namespace::Types); + auto resolved + = ctx.resolve_path (vis.get_path_unchecked (), Namespace::Types); - ctx.map_usage (Usage (vis.get_path ().get_node_id ()), + ctx.map_usage (Usage (vis.get_path_unchecked ().get_node_id ()), Definition (resolved->get_node_id ())); } } From 96bdb2b2115a57d0f9b23341ad493b0c921cbb4a Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Mon, 28 Apr 2025 18:01:15 +0200 Subject: [PATCH 4/9] Remove error state from visibility gcc/rust/ChangeLog: * ast/rust-ast.h: * ast/rust-item.h: * ast/rust-macro.h: * hir/rust-ast-lower.cc (translate_visibility): * parse/rust-parse-impl.h (Parser::parse_visibility): * rust-session-manager.cc (Session::injection): Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/ast/rust-ast.h | 16 +--------------- gcc/rust/ast/rust-item.h | 16 ++++++++-------- gcc/rust/ast/rust-macro.h | 2 +- gcc/rust/hir/rust-ast-lower.cc | 7 ------- gcc/rust/parse/rust-parse-impl.h | 4 ++-- gcc/rust/rust-session-manager.cc | 2 +- 6 files changed, 13 insertions(+), 34 deletions(-) diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index c1856c282ee4..07ee84a34764 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -511,12 +511,6 @@ struct Visibility public: VisType get_vis_type () const { return vis_type; } - // Returns whether visibility is in an error state. - bool is_error () const - { - return vis_type == PUB_IN_PATH && !in_path.has_value (); - } - // Returns whether a visibility has a path bool has_path () const { @@ -524,18 +518,10 @@ struct Visibility } // Returns whether visibility is public or not. - bool is_public () const { return vis_type != PRIV && !is_error (); } + bool is_public () const { return vis_type != PRIV; } location_t get_locus () const { return locus; } - // empty? - // Creates an error visibility. - static Visibility create_error () - { - return Visibility (PUB_IN_PATH, SimplePath::create_empty (), - UNDEF_LOCATION); - } - // Unique pointer custom clone function /*std::unique_ptr clone_visibility() const { return std::unique_ptr(clone_visibility_impl()); diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index f507c90dc962..ec84ad0347d9 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -807,7 +807,7 @@ class Module : public VisItem // Loaded module constructor, with items Module (Identifier name, location_t locus, std::vector> items, - Visibility visibility = Visibility::create_error (), + Visibility visibility = Visibility::create_private (), Unsafety safety = Unsafety::Normal, std::vector inner_attrs = std::vector (), std::vector outer_attrs = std::vector ()) @@ -1727,7 +1727,7 @@ class StructField bool has_outer_attributes () const { return !outer_attrs.empty (); } // Returns whether struct field has a non-private (non-default) visibility. - bool has_visibility () const { return !visibility.is_error (); } + bool has_visibility () const { return visibility.is_public (); } StructField (Identifier field_name, std::unique_ptr field_type, Visibility vis, location_t locus, @@ -1781,8 +1781,8 @@ class StructField // Creates an error state struct field. static StructField create_error () { - return StructField (std::string (""), nullptr, Visibility::create_error (), - UNDEF_LOCATION); + return StructField (std::string (""), nullptr, + Visibility::create_private (), UNDEF_LOCATION); } std::string as_string () const; @@ -1886,7 +1886,7 @@ class TupleField /* Returns whether tuple field has a non-default visibility (i.e. a public * one) */ - bool has_visibility () const { return !visibility.is_error (); } + bool has_visibility () const { return visibility.is_public (); } // Complete constructor TupleField (std::unique_ptr field_type, Visibility vis, @@ -1936,7 +1936,7 @@ class TupleField // Creates an error state tuple field. static TupleField create_error () { - return TupleField (nullptr, Visibility::create_error (), UNDEF_LOCATION); + return TupleField (nullptr, Visibility::create_private (), UNDEF_LOCATION); } std::string as_string () const; @@ -3466,7 +3466,7 @@ class ExternalTypeItem : public ExternalItem bool has_outer_attrs () const { return !outer_attrs.empty (); } // Returns whether item has non-default visibility. - bool has_visibility () const { return !visibility.is_error (); } + bool has_visibility () const { return visibility.is_public (); } location_t get_locus () const { return locus; } @@ -3558,7 +3558,7 @@ class ExternalStaticItem : public ExternalItem bool has_outer_attrs () const { return !outer_attrs.empty (); } // Returns whether item has non-default visibility. - bool has_visibility () const { return !visibility.is_error (); } + bool has_visibility () const { return visibility.is_public (); } location_t get_locus () const { return locus; } diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h index 575cd231af79..62c054b4890b 100644 --- a/gcc/rust/ast/rust-macro.h +++ b/gcc/rust/ast/rust-macro.h @@ -524,7 +524,7 @@ class MacroRulesDefinition : public VisItem return std::make_unique ( MacroRulesDefinition (rule_name, delim_type, rules, outer_attrs, locus, AST::MacroRulesDefinition::MacroKind::MBE, - AST::Visibility::create_error ())); + AST::Visibility::create_private ())); } static std::unique_ptr diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc index 61a7083442d5..ff3d21905379 100644 --- a/gcc/rust/hir/rust-ast-lower.cc +++ b/gcc/rust/hir/rust-ast-lower.cc @@ -34,13 +34,6 @@ using HIR::ClosureParam; Visibility translate_visibility (const AST::Visibility &vis) { - // FIXME: How do we create a private visibility here? Is it always private if - // the AST vis is an error? - // FIXME: We need to add a `create_private()` static function to the - // AST::Visibility class and use it when the vis is empty in the parser... - if (vis.is_error ()) - return Visibility::create_error (); - switch (vis.get_vis_type ()) { case AST::Visibility::PUB: diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index e47b9e015e2e..110d1eda263f 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -2414,7 +2414,7 @@ Parser::parse_visibility () add_error (std::move (error)); // skip after somewhere? - return AST::Visibility::create_error (); + return AST::Visibility::create_private (); } skip_token (RIGHT_PAREN); @@ -2426,7 +2426,7 @@ Parser::parse_visibility () t->get_token_description ())); lexer.skip_token (); - return AST::Visibility::create_error (); + return AST::Visibility::create_private (); } } diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 5563d103ff5e..4f9098f86b4b 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -874,7 +874,7 @@ Session::injection (AST::Crate &crate) // create "extern crate" item with the name std::unique_ptr extern_crate ( - new AST::ExternCrate (*it, AST::Visibility::create_error (), + new AST::ExternCrate (*it, AST::Visibility::create_private (), {std::move (attr)}, UNKNOWN_LOCATION)); // insert at beginning From faeef09f9c04044b2b71346fbcb62c42ce434bd2 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Mon, 28 Apr 2025 18:18:13 +0200 Subject: [PATCH 5/9] Insert crate module name at root gcc/rust/ChangeLog: * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::go): Insert the crate module name at crate root. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc index 3ec06aaf0183..aace4dcd206c 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -94,6 +94,8 @@ TopLevel::go (AST::Crate &crate) // they are not used until `Late`. furthermore, we run this visitor multiple // times in a row in a fixed-point fashion, so it would make the code // responsible for this ugly and perfom a lot of error checking. + insert_or_error_out (Identifier ("crate"), UNKNOWN_LOCATION, + crate.get_node_id (), Namespace::Types); for (auto &item : crate.items) item->accept_vis (*this); From acb37419432a7d31200b9e640a0b9b0102624616 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Mon, 28 Apr 2025 18:36:11 +0200 Subject: [PATCH 6/9] FIXUP ChangeLog: * c/gcc/rust/resolve/rust-late-name-resolver-2.0.cc (Late::visit): Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/resolve/rust-late-name-resolver-2.0.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index 50fa9fc3c04e..2d1870cbc45b 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -542,11 +542,10 @@ Late::visit (AST::Visibility &vis) { if (vis.has_path ()) { - auto resolved - = ctx.resolve_path (vis.get_path_unchecked (), Namespace::Types); - - ctx.map_usage (Usage (vis.get_path_unchecked ().get_node_id ()), - Definition (resolved->get_node_id ())); + if (auto resolved + = ctx.resolve_path (vis.get_path_unchecked (), Namespace::Types)) + ctx.map_usage (Usage (vis.get_path_unchecked ().get_node_id ()), + Definition (resolved->get_node_id ())); } } From bd5c33ef5bff66764ae200ea3984fb8c6b7195ab Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Mon, 28 Apr 2025 18:56:40 +0200 Subject: [PATCH 7/9] Remove now passing test from exclusion list gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: Remove several tests from exclusion list. Signed-off-by: Pierre-Emmanuel Patry --- gcc/testsuite/rust/compile/nr2/exclude | 3 --- 1 file changed, 3 deletions(-) diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index c020e36fba4a..a1b1e729e6ee 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -1,10 +1,7 @@ canonical_paths1.rs issue-3315-2.rs -privacy5.rs -privacy8.rs pub_restricted_1.rs pub_restricted_2.rs -pub_restricted_3.rs issue-2905-2.rs derive-default1.rs derive-eq-invalid.rs From 9ac02058a9c1e6ab2a04e466eb92f135e8a052ca Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Wed, 30 Apr 2025 13:37:55 +0200 Subject: [PATCH 8/9] Make resolve_path return an error context gcc/rust/ChangeLog: * resolve/rust-early-name-resolver-2.0.cc (Early::visit): * resolve/rust-forever-stack.h (class ResolutionError): * resolve/rust-forever-stack.hxx: * resolve/rust-name-resolution-context.h (class PathResolutionError): Signed-off-by: Pierre-Emmanuel Patry --- .../resolve/rust-early-name-resolver-2.0.cc | 6 +- gcc/rust/resolve/rust-forever-stack.h | 34 +++++++- gcc/rust/resolve/rust-forever-stack.hxx | 86 +++++++++++-------- .../resolve/rust-name-resolution-context.h | 40 ++++++--- 4 files changed, 117 insertions(+), 49 deletions(-) diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc index 3060b2904ec4..70a5582d1503 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -272,7 +272,11 @@ Early::visit (AST::MacroInvocation &invoc) // we won't have changed `definition` from `nullopt` if there are more // than one segments in our path if (!definition.has_value ()) - definition = ctx.resolve_path (path.get_segments (), Namespace::Macros); + { + if (auto resolved + = ctx.resolve_path (path.get_segments (), Namespace::Macros)) + definition = resolved.value (); + } // if the definition still does not have a value, then it's an error if (!definition.has_value ()) diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h index 3ca6e286e5fc..061d8e3e0505 100644 --- a/gcc/rust/resolve/rust-forever-stack.h +++ b/gcc/rust/resolve/rust-forever-stack.h @@ -543,6 +543,34 @@ class ForeverStackStore Node root; }; +class ResolutionError +{ + NodeId offending_id; + location_t offending_location; + std::vector suggestions; + + ResolutionError (NodeId node_id, location_t loc, + std::vector suggestions) + : offending_id (node_id), offending_location (loc), + suggestions (suggestions) + {} + +public: + template + static ResolutionError make_error (const T &node, + std::vector suggestions = {}) + { + return ResolutionError (node.get_node_id (), node.get_locus (), + suggestions); + } + + static ResolutionError make_error (location_t loc, + std::vector suggestions = {}) + { + return ResolutionError (UNKNOWN_NODEID, loc, suggestions); + } +}; + template class ForeverStack { public: @@ -671,7 +699,7 @@ template class ForeverStack * current map, an empty one otherwise. */ template - tl::optional resolve_path ( + tl::expected resolve_path ( const std::vector &segments, bool has_opening_scope_resolution, std::function insert_segment_resolution, std::vector &collect_errors); @@ -790,14 +818,14 @@ template class ForeverStack Node &find_closest_module (Node &starting_point); template - tl::optional> find_starting_point ( + tl::expected, ResolutionError> find_starting_point ( const std::vector &segments, std::reference_wrapper &starting_point, std::function insert_segment_resolution, std::vector &collect_errors); template - tl::optional resolve_segments ( + tl::expected, ResolutionError> resolve_segments ( Node &starting_point, const std::vector &segments, SegIterator iterator, std::function insert_segment_resolution, diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index abf3a531fae0..eb4577552867 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -417,7 +417,7 @@ check_leading_kw_at_start (std::vector &collect_errors, const S &segment, // correct one or the root. template template -tl::optional::const_iterator> +tl::expected::const_iterator, ResolutionError> ForeverStack::find_starting_point ( const std::vector &segments, std::reference_wrapper &starting_point, std::function insert_segment_resolution, @@ -441,7 +441,8 @@ ForeverStack::find_starting_point ( if (check_leading_kw_at_start (collect_errors, seg, !is_start (iterator, segments) && is_self_or_crate)) - return tl::nullopt; + return tl::make_unexpected ( + ResolutionError::make_error (seg.get_locus ())); if (seg.is_crate_path_seg ()) { @@ -466,7 +467,8 @@ ForeverStack::find_starting_point ( collect_errors.emplace_back ( seg.get_locus (), ErrorCode::E0433, "too many leading % keywords"); - return tl::nullopt; + return tl::make_unexpected ( + ResolutionError::make_error (seg.get_locus ())); } starting_point @@ -487,7 +489,8 @@ ForeverStack::find_starting_point ( template template -tl::optional::Node &> +tl::expected::Node>, + ResolutionError> ForeverStack::resolve_segments ( Node &starting_point, const std::vector &segments, typename std::vector::const_iterator iterator, @@ -518,7 +521,8 @@ ForeverStack::resolve_segments ( seg.is_crate_path_seg () || seg.is_super_path_seg () || seg.is_lower_self_seg ())) - return tl::nullopt; + return tl::make_unexpected ( + ResolutionError::make_error (seg.get_locus ())); tl::optional::Node &> child = tl::nullopt; @@ -571,7 +575,8 @@ ForeverStack::resolve_segments ( { insert_segment_resolution (outer_seg, rib_lookup->get_node_id ()); - return tl::nullopt; + return tl::make_unexpected ( + ResolutionError::make_error (seg.get_locus ())); } } @@ -586,7 +591,8 @@ ForeverStack::resolve_segments ( || current_node->rib.kind == Rib::Kind::Module || current_node->is_prelude ()) { - return tl::nullopt; + return tl::make_unexpected ( + ResolutionError::make_error (seg.get_locus ())); } current_node = ¤t_node->parent.value (); @@ -598,7 +604,8 @@ ForeverStack::resolve_segments ( insert_segment_resolution (outer_seg, current_node->id); } - return *current_node; + return tl::expected::Node>, + ResolutionError> (std::ref (*current_node)); } template <> @@ -623,7 +630,7 @@ ForeverStack::resolve_final_segment (Node &final_node, std::string &seg_name, template template -tl::optional +tl::expected ForeverStack::resolve_path ( const std::vector &segments, bool has_opening_scope_resolution, std::function insert_segment_resolution, @@ -659,8 +666,8 @@ ForeverStack::resolve_path ( return Rib::Definition::NonShadowable (seg_id); } - tl::optional res - = get (unwrap_type_segment (segments.back ()).as_string ()); + auto unwrapped = unwrap_type_segment (segments.back ()); + tl::optional res = get (unwrapped.as_string ()); if (!res) res = get_lang_prelude ( @@ -669,7 +676,11 @@ ForeverStack::resolve_path ( if (res && !res->is_ambiguous ()) insert_segment_resolution (segments.back (), res->get_node_id ()); cleanup_current (); - return res; + if (res) + return res.value (); + else + return tl::make_unexpected ( + ResolutionError::make_error (unwrapped.get_locus ())); } std::reference_wrapper starting_point = cursor (); @@ -683,28 +694,35 @@ ForeverStack::resolve_path ( return resolve_segments (starting_point.get (), segments, iterator, insert_segment_resolution, collect_errors); }) - .and_then ([this, &segments, &insert_segment_resolution] ( - Node &final_node) -> tl::optional { - // leave resolution within impl blocks to type checker - if (final_node.rib.kind == Rib::Kind::TraitOrImpl) - return tl::nullopt; - - auto &seg = unwrap_type_segment (segments.back ()); - std::string seg_name = seg.as_string (); - - // assuming this can't be a lang item segment - tl::optional res - = resolve_final_segment (final_node, seg_name, - seg.is_lower_self_seg ()); - // Ok we didn't find it in the rib, Lets try the prelude... - if (!res) - res = get_lang_prelude (seg_name); - - if (res && !res->is_ambiguous ()) - insert_segment_resolution (segments.back (), res->get_node_id ()); - - return res; - }); + .and_then ( + [this, &segments, &insert_segment_resolution] (Node &final_node) + -> tl::expected { + auto &seg = unwrap_type_segment (segments.back ()); + // + // leave resolution within impl blocks to type checker + if (final_node.rib.kind == Rib::Kind::TraitOrImpl) + return tl::make_unexpected ( + ResolutionError::make_error (seg.get_locus ())); + + std::string seg_name = seg.as_string (); + + // assuming this can't be a lang item segment + tl::optional res + = resolve_final_segment (final_node, seg_name, + seg.is_lower_self_seg ()); + // Ok we didn't find it in the rib, Lets try the prelude... + if (!res) + res = get_lang_prelude (seg_name); + + if (res && !res->is_ambiguous ()) + insert_segment_resolution (segments.back (), res->get_node_id ()); + + if (res) + return res.value (); + else + return tl::make_unexpected ( + ResolutionError::make_error (seg.get_locus ())); + }); cleanup_current (); return res; } diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h index aab04ccc18eb..6b99ca880479 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.h +++ b/gcc/rust/resolve/rust-name-resolution-context.h @@ -213,6 +213,23 @@ class BindingLayer BindingSource get_source () const; }; +class PathResolutionError +{ + tl::optional error; + +public: + enum class Kind + { + RESOLVE, + OTHER, + } kind; + + PathResolutionError () : error (tl::nullopt), kind (Kind::OTHER) {} + + PathResolutionError (ResolutionError error) + : error (error), kind (Kind::RESOLVE) + {} +}; // Now our resolver, which keeps track of all the `ForeverStack`s we could want class NameResolutionContext { @@ -278,7 +295,7 @@ class NameResolutionContext tl::optional lookup (NodeId usage) const; template - tl::optional + tl::expected resolve_path (const std::vector &segments, bool has_opening_scope_resolution, std::vector &collect_errors, Namespace ns) @@ -309,7 +326,7 @@ class NameResolutionContext } template - tl::optional + tl::expected resolve_path (const std::vector &segments, bool has_opening_scope_resolution, tl::optional &> collect_errors, @@ -322,7 +339,8 @@ class NameResolutionContext std::vector collect_errors_inner; if (auto ret = resolve_path (segments, has_opening_scope_resolution, collect_errors_inner, ns)) - return ret; + return ret.value (); + if (!collect_errors_inner.empty ()) { if (collect_errors.has_value ()) @@ -336,15 +354,15 @@ class NameResolutionContext for (auto &e : collect_errors_inner) e.emit (); } - return tl::nullopt; + return tl::make_unexpected (PathResolutionError{}); } } - return tl::nullopt; + return tl::make_unexpected (PathResolutionError{}); } template - tl::optional + tl::expected resolve_path (const AST::SimplePath &path, tl::optional &> collect_errors, Namespace ns_first, Args... ns_args) @@ -355,7 +373,7 @@ class NameResolutionContext } template - tl::optional + tl::expected resolve_path (const AST::PathInExpression &path, tl::optional &> collect_errors, Namespace ns_first, Args... ns_args) @@ -365,7 +383,7 @@ class NameResolutionContext } template - tl::optional + tl::expected resolve_path (const AST::TypePath &path, tl::optional &> collect_errors, Namespace ns_first, Args... ns_args) @@ -376,14 +394,14 @@ class NameResolutionContext } template - tl::optional resolve_path (const P &path, Namespace ns_first, - Args... ns_args) + tl::expected + resolve_path (const P &path, Namespace ns_first, Args... ns_args) { return resolve_path (path, tl::nullopt, ns_first, ns_args...); } template - tl::optional + tl::expected resolve_path (const P &path_segments, bool has_opening_scope_resolution, Namespace ns_first, Args... ns_args) { From eb7150747cd36a44cae66987212026b81db6cbd4 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Wed, 30 Apr 2025 13:41:34 +0200 Subject: [PATCH 9/9] FIXUP ChangeLog: * c/gcc/rust/resolve/rust-forever-stack.h (class ResolutionError): Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/resolve/rust-forever-stack.h | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h index 061d8e3e0505..cb56f310170d 100644 --- a/gcc/rust/resolve/rust-forever-stack.h +++ b/gcc/rust/resolve/rust-forever-stack.h @@ -545,29 +545,18 @@ class ForeverStackStore class ResolutionError { - NodeId offending_id; location_t offending_location; std::vector suggestions; - ResolutionError (NodeId node_id, location_t loc, - std::vector suggestions) - : offending_id (node_id), offending_location (loc), - suggestions (suggestions) + ResolutionError (location_t loc, std::vector suggestions) + : offending_location (loc), suggestions (suggestions) {} public: - template - static ResolutionError make_error (const T &node, - std::vector suggestions = {}) - { - return ResolutionError (node.get_node_id (), node.get_locus (), - suggestions); - } - static ResolutionError make_error (location_t loc, std::vector suggestions = {}) { - return ResolutionError (UNKNOWN_NODEID, loc, suggestions); + return ResolutionError (loc, suggestions); } };