Skip to content

Commit ff61ba4

Browse files
powerboat9P-E-P
authored andcommitted
nr2.0: Add more checks for alternate patterns
gcc/rust/ChangeLog: * resolve/rust-late-name-resolver-2.0.cc (visit_identifier_as_pattern): Handle is_ref and is_mut. (Late::visit): Likewise. * resolve/rust-name-resolution-context.cc (BindingLayer::insert_ident): Likewise. (BindingLayer::bind_test): Handle changes to BindingLayer fields. (BindingLayer::merge): Likewise and emit more error messages. * resolve/rust-name-resolution-context.h (struct IdentifierMode): New. (Binding::has_expected_bindings): New field. (Binding::set): Rename field to... (Binding::idents): ...here and convert from a set to a map. (Binding::Binding): Initialize has_expected_bindings. (BindingLayer::insert_ident): Adjust parameters. gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: Remove torture/alt_patterns1.rs. Signed-off-by: Owen Avery <[email protected]>
1 parent 1f53118 commit ff61ba4

File tree

4 files changed

+83
-14
lines changed

4 files changed

+83
-14
lines changed

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ Late::visit (AST::LetStmt &let)
211211
static void
212212
visit_identifier_as_pattern (NameResolutionContext &ctx,
213213
const Identifier &ident, location_t locus,
214-
NodeId node_id)
214+
NodeId node_id, bool is_ref, bool is_mut)
215215
{
216216
// do we insert in labels or in values
217217
// but values does not allow shadowing... since functions cannot shadow
@@ -232,7 +232,7 @@ visit_identifier_as_pattern (NameResolutionContext &ctx,
232232
return;
233233
}
234234

235-
ctx.bindings.peek ().insert_ident (ident);
235+
ctx.bindings.peek ().insert_ident (ident.as_string (), locus, is_ref, is_mut);
236236

237237
if (ctx.bindings.peek ().is_or_bound (ident))
238238
{
@@ -255,7 +255,9 @@ Late::visit (AST::IdentifierPattern &identifier)
255255

256256
visit_identifier_as_pattern (ctx, identifier.get_ident (),
257257
identifier.get_locus (),
258-
identifier.get_node_id ());
258+
identifier.get_node_id (),
259+
identifier.get_is_ref (),
260+
identifier.get_is_mut ());
259261
}
260262

261263
void
@@ -286,7 +288,8 @@ void
286288
Late::visit (AST::StructPatternFieldIdent &field)
287289
{
288290
visit_identifier_as_pattern (ctx, field.get_identifier (), field.get_locus (),
289-
field.get_node_id ());
291+
field.get_node_id (), field.is_ref (),
292+
field.is_mut ());
290293
}
291294

292295
void

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

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ BindingLayer::bind_test (Identifier ident, Binding::Kind kind)
3333
{
3434
for (auto &bind : bindings)
3535
{
36-
if (bind.set.find (ident) != bind.set.cend () && bind.kind == kind)
36+
if (bind.idents.find (ident.as_string ()) != bind.idents.cend ()
37+
&& bind.kind == kind)
3738
{
3839
return true;
3940
}
@@ -60,20 +61,66 @@ BindingLayer::is_or_bound (Identifier ident)
6061
}
6162

6263
void
63-
BindingLayer::insert_ident (Identifier ident)
64+
BindingLayer::insert_ident (std::string ident, location_t locus, bool is_ref,
65+
bool is_mut)
6466
{
65-
bindings.back ().set.insert (ident);
67+
bindings.back ().idents.emplace (
68+
std::move (ident), std::make_pair (locus, IdentifierMode (is_ref, is_mut)));
6669
}
6770

6871
void
6972
BindingLayer::merge ()
7073
{
71-
auto last_binding = bindings.back ();
74+
auto last_binding = std::move (bindings.back ());
7275
bindings.pop_back ();
73-
for (auto &value : last_binding.set)
76+
77+
if (bindings.back ().has_expected_bindings)
7478
{
75-
bindings.back ().set.insert (value);
79+
for (auto &value : bindings.back ().idents)
80+
{
81+
auto ident = value.first;
82+
if (last_binding.idents.find (ident) == last_binding.idents.end ())
83+
{
84+
location_t locus = value.second.first;
85+
rust_error_at (locus, ErrorCode::E0408,
86+
"variable %qs is not bound in all patterns",
87+
ident.c_str ());
88+
}
89+
}
7690
}
91+
92+
for (auto &value : last_binding.idents)
93+
{
94+
auto res = bindings.back ().idents.emplace (value);
95+
if (res.second)
96+
{
97+
if (bindings.back ().has_expected_bindings)
98+
{
99+
auto &ident = value.first;
100+
location_t locus = value.second.first;
101+
rust_error_at (locus, ErrorCode::E0408,
102+
"variable %qs is not bound in all patterns",
103+
ident.c_str ());
104+
}
105+
}
106+
else
107+
{
108+
auto this_mode = value.second.second;
109+
auto other_mode = res.first->second.second;
110+
if (this_mode != other_mode)
111+
{
112+
auto &ident = value.first;
113+
location_t locus = value.second.first;
114+
rust_error_at (locus, ErrorCode::E0409,
115+
"variable %qs is bound inconsistently across "
116+
"pattern alternatives",
117+
ident.c_str ());
118+
}
119+
}
120+
}
121+
122+
if (bindings.back ().kind == Binding::Kind::Or)
123+
bindings.back ().has_expected_bindings = true;
77124
}
78125

79126
BindingSource

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

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,22 @@ class Definition
158158
NodeId id;
159159
};
160160

161+
struct IdentifierMode
162+
{
163+
bool is_ref;
164+
bool is_mut;
165+
166+
IdentifierMode (bool is_ref, bool is_mut) : is_ref (is_ref), is_mut (is_mut)
167+
{}
168+
169+
bool operator== (const IdentifierMode &other)
170+
{
171+
return other.is_ref == is_ref && other.is_mut == is_mut;
172+
}
173+
174+
bool operator!= (const IdentifierMode &other) { return !(*this == other); }
175+
};
176+
161177
struct Binding
162178
{
163179
enum class Kind
@@ -166,9 +182,12 @@ struct Binding
166182
Or,
167183
} kind;
168184

169-
std::unordered_set<Identifier> set;
185+
// used to check the correctness of or-bindings
186+
bool has_expected_bindings;
187+
188+
std::unordered_map<std::string, std::pair<location_t, IdentifierMode>> idents;
170189

171-
Binding (Binding::Kind kind) : kind (kind) {}
190+
Binding (Binding::Kind kind) : kind (kind), has_expected_bindings (false) {}
172191
};
173192

174193
/**
@@ -208,7 +227,8 @@ class BindingLayer
208227
*/
209228
bool is_or_bound (Identifier ident);
210229

211-
void insert_ident (Identifier ident);
230+
void insert_ident (std::string ident, location_t locus, bool is_ref,
231+
bool is_mut);
212232

213233
void merge ();
214234

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
issue-3315-2.rs
2-
torture/alt_patterns1.rs
32
# please don't delete the trailing newline

0 commit comments

Comments
 (0)