Skip to content

Commit 3b13ee4

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 3b13ee4

2 files changed

Lines changed: 63 additions & 2 deletions

File tree

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

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,61 @@ 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+
NodeId ref_id = init.get_mappings ().get_nodeid ();
102+
NodeId def_id = UNKNOWN_NODEID;
103+
104+
auto resolver = Rust::Resolver::Resolver::get ();
105+
if (resolver->lookup_resolved_name (ref_id, &def_id))
106+
{
107+
bool is_mutable = false;
108+
auto &mappings = Analysis::Mappings::get ();
109+
110+
auto result_hir_id = mappings.lookup_node_to_hir (def_id);
111+
if (result_hir_id.has_value ())
112+
{
113+
HirId var_hir_id = result_hir_id.value ();
114+
auto result_pattern
115+
= mappings.lookup_hir_pattern (var_hir_id);
116+
117+
if (result_pattern.has_value ())
118+
{
119+
HIR::Pattern *def_pattern = result_pattern.value ();
120+
if (def_pattern
121+
&& def_pattern->get_pattern_type ()
122+
== HIR::Pattern::PatternType::IDENTIFIER)
123+
{
124+
auto def_ident
125+
= static_cast<HIR::IdentifierPattern *> (
126+
def_pattern);
127+
128+
if (def_ident->is_mut ())
129+
is_mutable = true;
130+
}
131+
}
132+
}
133+
134+
if (!is_mutable)
135+
rust_error_at (
136+
stmt_pattern.get_locus (),
137+
"cannot borrow immutable local variable as mutable");
138+
}
139+
}
140+
}
141+
91142
if (init_expr_ty->get_kind () == TyTy::TypeKind::ERROR)
92143
return;
93144

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)