Skip to content

Commit 359322c

Browse files
committed
nr2.0: Improve visibility path handling
gcc/rust/ChangeLog: * resolve/rust-forever-stack.h (enum ResolutionMode): New. (ForeverStack::get): Add a private overload that takes a starting node as a parameter. (ForeverStack::resolve_path): Replace boolean parameter has_opening_scope_resolution with ResolutionMode parameter mode. * resolve/rust-forever-stack.hxx (ForeverStack::resolve_path): Likewise. (ForeverStack::get): Add a private overload that takes a starting node as a parameter. * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Add Visibility visitor. * resolve/rust-late-name-resolver-2.0.h (Late::visit): Likewise. * resolve/rust-name-resolution-context.h (NameResolutionContext::resolve_path): Rework overloading a bit and accept ResolutionMode parameter. gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: Remove entries. Signed-off-by: Owen Avery <[email protected]>
1 parent 1b0703f commit 359322c

File tree

6 files changed

+174
-93
lines changed

6 files changed

+174
-93
lines changed

gcc/rust/resolve/rust-forever-stack.h

+11-1
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,13 @@ class ForeverStackStore
543543
Node root;
544544
};
545545

546+
enum class ResolutionMode
547+
{
548+
Normal,
549+
FromRoot,
550+
FromExtern, // extern prelude
551+
};
552+
546553
template <Namespace N> class ForeverStack
547554
{
548555
public:
@@ -672,7 +679,7 @@ template <Namespace N> class ForeverStack
672679
*/
673680
template <typename S>
674681
tl::optional<Rib::Definition> resolve_path (
675-
const std::vector<S> &segments, bool has_opening_scope_resolution,
682+
const std::vector<S> &segments, ResolutionMode mode,
676683
std::function<void (const S &, NodeId)> insert_segment_resolution,
677684
std::vector<Error> &collect_errors);
678685

@@ -739,6 +746,9 @@ template <Namespace N> class ForeverStack
739746
tl::optional<Node &> parent; // `None` only if the node is a root
740747
};
741748

749+
// private overload which allows specifying a starting point
750+
tl::optional<Rib::Definition> get (Node &start, const Identifier &name);
751+
742752
/* Should we keep going upon seeing a Rib? */
743753
enum class KeepGoing
744754
{

gcc/rust/resolve/rust-forever-stack.hxx

+53-50
Original file line numberDiff line numberDiff line change
@@ -291,12 +291,12 @@ ForeverStack<N>::update_cursor (Node &new_cursor)
291291

292292
template <Namespace N>
293293
tl::optional<Rib::Definition>
294-
ForeverStack<N>::get (const Identifier &name)
294+
ForeverStack<N>::get (Node &start, const Identifier &name)
295295
{
296296
tl::optional<Rib::Definition> resolved_definition = tl::nullopt;
297297

298298
// TODO: Can we improve the API? have `reverse_iter` return an optional?
299-
reverse_iter ([&resolved_definition, &name] (Node &current) {
299+
reverse_iter (start, [&resolved_definition, &name] (Node &current) {
300300
auto candidate = current.rib.get (name.as_string ());
301301

302302
return candidate.map_or (
@@ -318,6 +318,13 @@ ForeverStack<N>::get (const Identifier &name)
318318
return resolved_definition;
319319
}
320320

321+
template <Namespace N>
322+
tl::optional<Rib::Definition>
323+
ForeverStack<N>::get (const Identifier &name)
324+
{
325+
return get (cursor (), name);
326+
}
327+
321328
template <Namespace N>
322329
tl::optional<Rib::Definition>
323330
ForeverStack<N>::get_lang_prelude (const Identifier &name)
@@ -625,23 +632,25 @@ template <Namespace N>
625632
template <typename S>
626633
tl::optional<Rib::Definition>
627634
ForeverStack<N>::resolve_path (
628-
const std::vector<S> &segments, bool has_opening_scope_resolution,
635+
const std::vector<S> &segments, ResolutionMode mode,
629636
std::function<void (const S &, NodeId)> insert_segment_resolution,
630637
std::vector<Error> &collect_errors)
631638
{
632639
rust_assert (!segments.empty ());
633640

634-
// handle paths with opening scopes
635-
std::function<void (void)> cleanup_current = [] () {};
636-
if (has_opening_scope_resolution)
641+
std::reference_wrapper<Node> starting_point = cursor ();
642+
switch (mode)
637643
{
638-
Node *last_current = &cursor_reference.get ();
639-
if (get_rust_edition () == Edition::E2015)
640-
cursor_reference = root;
641-
else
642-
cursor_reference = extern_prelude;
643-
cleanup_current
644-
= [this, last_current] () { cursor_reference = *last_current; };
644+
case ResolutionMode::Normal:
645+
break; // default
646+
case ResolutionMode::FromRoot:
647+
starting_point = root;
648+
break;
649+
case ResolutionMode::FromExtern:
650+
starting_point = extern_prelude;
651+
break;
652+
default:
653+
rust_unreachable ();
645654
}
646655

647656
// if there's only one segment, we just use `get`
@@ -654,59 +663,53 @@ ForeverStack<N>::resolve_path (
654663
lang_item.value ());
655664

656665
insert_segment_resolution (seg, seg_id);
657-
cleanup_current ();
658666
// TODO: does NonShadowable matter?
659667
return Rib::Definition::NonShadowable (seg_id);
660668
}
661669

662670
tl::optional<Rib::Definition> res
663-
= get (unwrap_type_segment (segments.back ()).as_string ());
671+
= get (starting_point.get (),
672+
unwrap_type_segment (segments.back ()).as_string ());
664673

665674
if (!res)
666675
res = get_lang_prelude (
667676
unwrap_type_segment (segments.back ()).as_string ());
668677

669678
if (res && !res->is_ambiguous ())
670679
insert_segment_resolution (segments.back (), res->get_node_id ());
671-
cleanup_current ();
672680
return res;
673681
}
674682

675-
std::reference_wrapper<Node> starting_point = cursor ();
683+
return find_starting_point (segments, starting_point,
684+
insert_segment_resolution, collect_errors)
685+
.and_then (
686+
[this, &segments, &starting_point, &insert_segment_resolution,
687+
&collect_errors] (typename std::vector<S>::const_iterator iterator) {
688+
return resolve_segments (starting_point.get (), segments, iterator,
689+
insert_segment_resolution, collect_errors);
690+
})
691+
.and_then ([this, &segments, &insert_segment_resolution] (
692+
Node &final_node) -> tl::optional<Rib::Definition> {
693+
// leave resolution within impl blocks to type checker
694+
if (final_node.rib.kind == Rib::Kind::TraitOrImpl)
695+
return tl::nullopt;
696+
697+
auto &seg = unwrap_type_segment (segments.back ());
698+
std::string seg_name = seg.as_string ();
699+
700+
// assuming this can't be a lang item segment
701+
tl::optional<Rib::Definition> res
702+
= resolve_final_segment (final_node, seg_name,
703+
seg.is_lower_self_seg ());
704+
// Ok we didn't find it in the rib, Lets try the prelude...
705+
if (!res)
706+
res = get_lang_prelude (seg_name);
676707

677-
auto res
678-
= find_starting_point (segments, starting_point, insert_segment_resolution,
679-
collect_errors)
680-
.and_then (
681-
[this, &segments, &starting_point, &insert_segment_resolution,
682-
&collect_errors] (typename std::vector<S>::const_iterator iterator) {
683-
return resolve_segments (starting_point.get (), segments, iterator,
684-
insert_segment_resolution, collect_errors);
685-
})
686-
.and_then ([this, &segments, &insert_segment_resolution] (
687-
Node &final_node) -> tl::optional<Rib::Definition> {
688-
// leave resolution within impl blocks to type checker
689-
if (final_node.rib.kind == Rib::Kind::TraitOrImpl)
690-
return tl::nullopt;
691-
692-
auto &seg = unwrap_type_segment (segments.back ());
693-
std::string seg_name = seg.as_string ();
694-
695-
// assuming this can't be a lang item segment
696-
tl::optional<Rib::Definition> res
697-
= resolve_final_segment (final_node, seg_name,
698-
seg.is_lower_self_seg ());
699-
// Ok we didn't find it in the rib, Lets try the prelude...
700-
if (!res)
701-
res = get_lang_prelude (seg_name);
702-
703-
if (res && !res->is_ambiguous ())
704-
insert_segment_resolution (segments.back (), res->get_node_id ());
705-
706-
return res;
707-
});
708-
cleanup_current ();
709-
return res;
708+
if (res && !res->is_ambiguous ())
709+
insert_segment_resolution (segments.back (), res->get_node_id ());
710+
711+
return res;
712+
});
710713
}
711714

712715
template <Namespace N>

gcc/rust/resolve/rust-late-name-resolver-2.0.cc

+56
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,62 @@ Late::visit (AST::TypePath &type)
520520
Definition (resolved->get_node_id ()));
521521
}
522522

523+
void
524+
Late::visit (AST::Visibility &vis)
525+
{
526+
if (!vis.has_path ())
527+
return;
528+
529+
AST::SimplePath &path = vis.get_path ();
530+
531+
rust_assert (path.get_segments ().size ());
532+
auto &first_seg = path.get_segments ()[0];
533+
534+
auto mode = ResolutionMode::Normal;
535+
536+
if (path.has_opening_scope_resolution ())
537+
{
538+
if (get_rust_edition () == Edition::E2015)
539+
mode = ResolutionMode::FromRoot;
540+
else
541+
mode = ResolutionMode::FromExtern;
542+
}
543+
else if (!first_seg.is_crate_path_seg () && !first_seg.is_super_path_seg ()
544+
&& !first_seg.is_lower_self_seg ())
545+
{
546+
if (get_rust_edition () == Edition::E2015)
547+
{
548+
mode = ResolutionMode::FromRoot;
549+
}
550+
else
551+
{
552+
rust_error_at (path.get_locus (),
553+
"relative paths are not supported in visibilities in "
554+
"2018 edition or later");
555+
return;
556+
}
557+
}
558+
559+
auto res = ctx.resolve_path (path.get_segments (), mode, Namespace::Types);
560+
561+
if (!res.has_value ())
562+
{
563+
rust_error_at (path.get_locus (), ErrorCode::E0433,
564+
"could not resolve path %qs", path.as_string ().c_str ());
565+
return;
566+
}
567+
568+
// TODO: is this possible?
569+
if (res->is_ambiguous ())
570+
{
571+
rust_error_at (path.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
572+
path.as_string ().c_str ());
573+
return;
574+
}
575+
576+
ctx.map_usage (Usage (path.get_node_id ()), Definition (res->get_node_id ()));
577+
}
578+
523579
void
524580
Late::visit (AST::Trait &trait)
525581
{

gcc/rust/resolve/rust-late-name-resolver-2.0.h

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class Late : public DefaultResolver
6060
void visit (AST::LoopLabel &) override;
6161
void visit (AST::PathInExpression &) override;
6262
void visit (AST::TypePath &) override;
63+
void visit (AST::Visibility &) override;
6364
void visit (AST::Trait &) override;
6465
void visit (AST::StructExprStruct &) override;
6566
void visit (AST::StructExprStructBase &) override;

0 commit comments

Comments
 (0)