Skip to content

Commit c67466b

Browse files
committed
Keep definition provenance to skip enum variants
Enum variants shouldn't be accessed directly even from within an enum. This commit keeps the provenance for enum variants definition so we can skip them when resolving a value within an enum definition. gcc/rust/ChangeLog: * resolve/rust-forever-stack.h: Add new function to insert enum variants and add argument to resolver's get function to explicitely skip enum variants. * resolve/rust-forever-stack.hxx: Update function definitions. * resolve/rust-name-resolution-context.cc (NameResolutionContext::insert_variant): Add function to insert enum variants. * resolve/rust-name-resolution-context.h: Add function's prototype. * resolve/rust-rib.cc (Rib::Definition::Definition): Add new boolean to hint at enum variant provenance. (Rib::Definition::is_variant): New getter for variant status. (Rib::Definition::Shadowable): Update constructor to opt out of enum variants. (Rib::Definition::Globbed): Likewise. (Rib::Definition::NonShadowable): Change constructor to forward enum variant provenance status. * resolve/rust-rib.h: Update function prototypes. * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::insert_enum_variant_or_error_out): Add function to insert enum variants in the name resolver. (TopLevel::visit): Update several enum variant's visitor function with the new enum variant name resolving code. * resolve/rust-toplevel-name-resolver-2.0.h: Update function prototypes. Signed-off-by: Pierre-Emmanuel Patry <[email protected]>
1 parent 126680c commit c67466b

8 files changed

+106
-26
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,9 @@ template <Namespace N> class ForeverStack
591591
*/
592592
tl::expected<NodeId, DuplicateNameError> insert (Identifier name, NodeId id);
593593

594+
tl::expected<NodeId, DuplicateNameError> insert_variant (Identifier name,
595+
NodeId id);
596+
594597
/**
595598
* Insert a new shadowable definition in the innermost `Rib` in this stack
596599
*

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

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,14 @@ ForeverStack<Namespace::Labels>::insert (Identifier name, NodeId node)
173173
Rib::Definition::Shadowable (node));
174174
}
175175

176+
template <>
177+
inline tl::expected<NodeId, DuplicateNameError>
178+
ForeverStack<Namespace::Types>::insert_variant (Identifier name, NodeId node)
179+
{
180+
return insert_inner (peek (), name.as_string (),
181+
Rib::Definition::NonShadowable (node, true));
182+
}
183+
176184
template <Namespace N>
177185
Rib &
178186
ForeverStack<N>::peek ()
@@ -275,10 +283,12 @@ ForeverStack<N>::get (const Identifier &name)
275283

276284
return candidate.map_or (
277285
[&resolved_definition] (Rib::Definition found) {
278-
// for most namespaces, we do not need to care about various ribs - they
279-
// are available from all contexts if defined in the current scope, or
280-
// an outermore one. so if we do have a candidate, we can return it
281-
// directly and stop iterating
286+
if (found.is_variant ())
287+
return KeepGoing::Yes;
288+
// for most namespaces, we do not need to care about various ribs -
289+
// they are available from all contexts if defined in the current
290+
// scope, or an outermore one. so if we do have a candidate, we can
291+
// return it directly and stop iterating
282292
resolved_definition = found;
283293

284294
return KeepGoing::No;

gcc/rust/resolve/rust-name-resolution-context.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ NameResolutionContext::insert (Identifier name, NodeId id, Namespace ns)
4545
}
4646
}
4747

48+
tl::expected<NodeId, DuplicateNameError>
49+
NameResolutionContext::insert_variant (Identifier name, NodeId id)
50+
{
51+
return types.insert_variant (name, id);
52+
}
53+
4854
tl::expected<NodeId, DuplicateNameError>
4955
NameResolutionContext::insert_shadowable (Identifier name, NodeId id,
5056
Namespace ns)

gcc/rust/resolve/rust-name-resolution-context.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,9 @@ class NameResolutionContext
172172
tl::expected<NodeId, DuplicateNameError> insert (Identifier name, NodeId id,
173173
Namespace ns);
174174

175+
tl::expected<NodeId, DuplicateNameError> insert_variant (Identifier name,
176+
NodeId id);
177+
175178
tl::expected<NodeId, DuplicateNameError>
176179
insert_shadowable (Identifier name, NodeId id, Namespace ns);
177180

gcc/rust/resolve/rust-rib.cc

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
namespace Rust {
2323
namespace Resolver2_0 {
2424

25-
Rib::Definition::Definition (NodeId id, Mode mode)
25+
Rib::Definition::Definition (NodeId id, Mode mode, bool enum_variant)
26+
: enum_variant (enum_variant)
2627
{
2728
switch (mode)
2829
{
@@ -51,6 +52,12 @@ Rib::Definition::is_ambiguous () const
5152
return ids_globbed.size () > 1;
5253
}
5354

55+
bool
56+
Rib::Definition::is_variant () const
57+
{
58+
return enum_variant;
59+
}
60+
5461
std::string
5562
Rib::Definition::to_string () const
5663
{
@@ -75,19 +82,19 @@ Rib::Definition::to_string () const
7582
Rib::Definition
7683
Rib::Definition::Shadowable (NodeId id)
7784
{
78-
return Definition (id, Mode::SHADOWABLE);
85+
return Definition (id, Mode::SHADOWABLE, false);
7986
}
8087

8188
Rib::Definition
82-
Rib::Definition::NonShadowable (NodeId id)
89+
Rib::Definition::NonShadowable (NodeId id, bool enum_variant)
8390
{
84-
return Definition (id, Mode::NON_SHADOWABLE);
91+
return Definition (id, Mode::NON_SHADOWABLE, enum_variant);
8592
}
8693

8794
Rib::Definition
8895
Rib::Definition::Globbed (NodeId id)
8996
{
90-
return Definition (id, Mode::GLOBBED);
97+
return Definition (id, Mode::GLOBBED, false);
9198
}
9299

93100
DuplicateNameError::DuplicateNameError (std::string name, NodeId existing)

gcc/rust/resolve/rust-rib.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ class Rib
111111
class Definition
112112
{
113113
public:
114-
static Definition NonShadowable (NodeId id);
114+
static Definition NonShadowable (NodeId id, bool enum_variant = false);
115115
static Definition Shadowable (NodeId id);
116116
static Definition Globbed (NodeId id);
117117

@@ -124,11 +124,21 @@ class Rib
124124
std::vector<NodeId> ids_non_shadowable;
125125
std::vector<NodeId> ids_globbed;
126126

127+
// Enum variant should be skipped when dealing with inner definition.
128+
// struct E2;
129+
//
130+
// enum MyEnum<T> /* <-- Should be kept */{
131+
// E2 /* <-- Should be skipped */ (E2);
132+
// }
133+
bool enum_variant;
134+
127135
Definition () = default;
128136

129137
Definition &operator= (const Definition &) = default;
130138
Definition (Definition const &) = default;
131139

140+
bool is_variant () const;
141+
132142
bool is_ambiguous () const;
133143

134144
NodeId get_node_id () const
@@ -155,7 +165,7 @@ class Rib
155165
GLOBBED
156166
};
157167

158-
Definition (NodeId id, Mode mode);
168+
Definition (NodeId id, Mode mode, bool enum_variant);
159169
};
160170

161171
enum class Kind

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

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,18 @@ TopLevel::TopLevel (NameResolutionContext &resolver)
3232

3333
template <typename T>
3434
void
35-
TopLevel::insert_or_error_out (const Identifier &identifier, const T &node,
36-
Namespace ns)
35+
TopLevel::insert_enum_variant_or_error_out (const Identifier &identifier,
36+
const T &node)
3737
{
38-
insert_or_error_out (identifier, node.get_locus (), node.get_node_id (), ns);
38+
insert_enum_variant_or_error_out (identifier, node.get_locus (),
39+
node.get_node_id ());
3940
}
4041

4142
void
42-
TopLevel::insert_or_error_out (const Identifier &identifier,
43-
const location_t &locus, const NodeId &node_id,
44-
Namespace ns)
43+
TopLevel::check_multiple_insertion_error (
44+
tl::expected<NodeId, DuplicateNameError> result, const Identifier &identifier,
45+
const location_t &locus, const NodeId node_id)
4546
{
46-
// keep track of each node's location to provide useful errors
47-
node_locations.emplace (node_id, locus);
48-
49-
auto result = ctx.insert (identifier, node_id, ns);
5047
if (result)
5148
dirty = true;
5249
else if (result.error ().existing != node_id)
@@ -58,6 +55,37 @@ TopLevel::insert_or_error_out (const Identifier &identifier,
5855
identifier.as_string ().c_str ());
5956
}
6057
}
58+
void
59+
TopLevel::insert_enum_variant_or_error_out (const Identifier &identifier,
60+
const location_t &locus,
61+
const NodeId node_id)
62+
{
63+
// keep track of each node's location to provide useful errors
64+
node_locations.emplace (node_id, locus);
65+
66+
auto result = ctx.insert_variant (identifier, node_id);
67+
check_multiple_insertion_error (result, identifier, locus, node_id);
68+
}
69+
70+
template <typename T>
71+
void
72+
TopLevel::insert_or_error_out (const Identifier &identifier, const T &node,
73+
Namespace ns)
74+
{
75+
insert_or_error_out (identifier, node.get_locus (), node.get_node_id (), ns);
76+
}
77+
78+
void
79+
TopLevel::insert_or_error_out (const Identifier &identifier,
80+
const location_t &locus, const NodeId &node_id,
81+
Namespace ns)
82+
{
83+
// keep track of each node's location to provide useful errors
84+
node_locations.emplace (node_id, locus);
85+
86+
auto result = ctx.insert (identifier, node_id, ns);
87+
check_multiple_insertion_error (result, identifier, locus, node_id);
88+
}
6189

6290
void
6391
TopLevel::go (AST::Crate &crate)
@@ -336,19 +364,19 @@ TopLevel::visit (AST::TupleStruct &tuple_struct)
336364
void
337365
TopLevel::visit (AST::EnumItem &variant)
338366
{
339-
insert_or_error_out (variant.get_identifier (), variant, Namespace::Types);
367+
insert_enum_variant_or_error_out (variant.get_identifier (), variant);
340368
}
341369

342370
void
343371
TopLevel::visit (AST::EnumItemTuple &variant)
344372
{
345-
insert_or_error_out (variant.get_identifier (), variant, Namespace::Types);
373+
insert_enum_variant_or_error_out (variant.get_identifier (), variant);
346374
}
347375

348376
void
349377
TopLevel::visit (AST::EnumItemStruct &variant)
350378
{
351-
insert_or_error_out (variant.get_identifier (), variant, Namespace::Types);
379+
insert_enum_variant_or_error_out (variant.get_identifier (), variant);
352380
}
353381

354382
void

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,14 @@ class TopLevel : public DefaultResolver
114114
return std::move (imports_to_resolve);
115115
}
116116

117+
void check_multiple_insertion_error (
118+
tl::expected<NodeId, DuplicateNameError> result,
119+
const Identifier &identifier, const location_t &locus,
120+
const NodeId node_id);
121+
117122
/**
118-
* Insert a new definition or error out if a definition with the same name was
119-
* already present in the same namespace in the same scope.
123+
* Insert a new definition or error out if a definition with the same name
124+
* was already present in the same namespace in the same scope.
120125
*
121126
* @param identifier The identifier of the definition to add.
122127
* @param node A reference to the node, so we can get its `NodeId` and
@@ -130,6 +135,14 @@ class TopLevel : public DefaultResolver
130135
const location_t &locus, const NodeId &id,
131136
Namespace ns);
132137

138+
template <typename T>
139+
void insert_enum_variant_or_error_out (const Identifier &identifier,
140+
const T &node);
141+
142+
void insert_enum_variant_or_error_out (const Identifier &identifier,
143+
const location_t &locus,
144+
const NodeId node_id);
145+
133146
private:
134147
// If a new export has been defined whilst visiting the visitor is considered
135148
// dirty

0 commit comments

Comments
 (0)