Skip to content

Commit 4263286

Browse files
committed
gccrs: Emit error when borrowing immutable variable as mutable
Fixes #4289 Rust rules strictly forbid creating a mutable reference ('&mut T') to an immutable binding. Previously, the compiler failed to validate the mutability of the source variable when using a 'ref mut' pattern. This patch adds verification logic to TypeCheckStmt to check the mutability status of the variable definition. gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-stmt.cc (TypeCheckStmt::visit): Add check to ensure 'ref mut' patterns bind to mutable variables. gcc/testsuite/ChangeLog: * rust/compile/issue-4289.rs: New test. Signed-off-by: Jayant Chauhan <0001jayant@gmail.com>
1 parent 32622b7 commit 4263286

File tree

2 files changed

+102
-2
lines changed

2 files changed

+102
-2
lines changed

gcc/rust/typecheck/rust-hir-type-check-stmt.cc

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,100 @@ TypeCheckStmt::visit (HIR::LetStmt &stmt)
8484
auto &stmt_pattern = stmt.get_pattern ();
8585
TyTy::BaseType *init_expr_ty = nullptr;
8686
location_t init_expr_locus = UNKNOWN_LOCATION;
87+
8788
if (stmt.has_init_expr ())
8889
{
89-
init_expr_locus = stmt.get_init_expr ().get_locus ();
90-
init_expr_ty = TypeCheckExpr::Resolve (stmt.get_init_expr ());
90+
HIR::Expr &init = stmt.get_init_expr ();
91+
init_expr_locus = init.get_locus ();
92+
init_expr_ty = TypeCheckExpr::Resolve (init);
93+
94+
if (stmt_pattern.get_pattern_type ()
95+
== HIR::Pattern::PatternType::IDENTIFIER)
96+
{
97+
auto &ident = static_cast<HIR::IdentifierPattern &> (stmt_pattern);
98+
99+
if (ident.get_is_ref () && ident.is_mut ())
100+
{
101+
HIR::Expr *probe = &init;
102+
while (probe->get_expression_type ()
103+
== HIR::Expr::ExprType::Grouped)
104+
{
105+
probe = static_cast<HIR::GroupedExpr *> (probe)
106+
->get_expr_in_parens ()
107+
.get ();
108+
}
109+
110+
NodeId def_id = UNKNOWN_NODEID;
111+
bool found = false;
112+
auto resolver = Rust::Resolver::Resolver::get ();
113+
114+
if (resolver->lookup_resolved_name (
115+
probe->get_mappings ().get_nodeid (), &def_id))
116+
{
117+
found = true;
118+
}
119+
else if (probe->get_expression_type ()
120+
== HIR::Expr::ExprType::Path)
121+
{
122+
auto *path_ptr = static_cast<HIR::PathInExpression *> (probe);
123+
124+
if (resolver->lookup_resolved_name (
125+
path_ptr->get_mappings ().get_nodeid (), &def_id))
126+
{
127+
found = true;
128+
}
129+
else
130+
{
131+
for (auto &seg : path_ptr->get_segments ())
132+
{
133+
if (resolver->lookup_resolved_name (
134+
seg.get_mappings ().get_nodeid (), &def_id))
135+
{
136+
found = true;
137+
break;
138+
}
139+
}
140+
}
141+
}
142+
143+
if (found)
144+
{
145+
bool is_mutable = false;
146+
auto &mappings = Analysis::Mappings::get ();
147+
148+
auto result_hir_id = mappings.lookup_node_to_hir (def_id);
149+
if (result_hir_id.has_value ())
150+
{
151+
HirId var_hir_id = result_hir_id.value ();
152+
auto result_pattern
153+
= mappings.lookup_hir_pattern (var_hir_id);
154+
155+
if (result_pattern.has_value ())
156+
{
157+
HIR::Pattern *def_pattern = result_pattern.value ();
158+
159+
if (def_pattern
160+
&& def_pattern->get_pattern_type ()
161+
== HIR::Pattern::PatternType::IDENTIFIER)
162+
{
163+
auto def_ident
164+
= static_cast<HIR::IdentifierPattern *> (
165+
def_pattern);
166+
167+
if (def_ident->is_mut ())
168+
is_mutable = true;
169+
}
170+
}
171+
}
172+
173+
if (!is_mutable)
174+
rust_error_at (
175+
stmt_pattern.get_locus (),
176+
"cannot borrow immutable local variable as mutable");
177+
}
178+
}
179+
}
180+
91181
if (init_expr_ty->get_kind () == TyTy::TypeKind::ERROR)
92182
return;
93183

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// { dg-options "-fsyntax-only" }
2+
pub fn a() {
3+
let v = 10;
4+
let ref mut r = v; // { dg-error "cannot borrow immutable local variable as mutable" }
5+
}
6+
7+
pub fn b() {
8+
let mut v2 = 10;
9+
let ref mut r2 = v2; // Should compile fine
10+
}

0 commit comments

Comments
 (0)