From 5763df948f21e2034cbf88b91c8cafa7fb6207fc Mon Sep 17 00:00:00 2001 From: sofia Date: Mon, 21 Jul 2025 10:39:19 +0300 Subject: [PATCH] Check borrow mutability against variable mutability --- reid/src/mir/typecheck.rs | 19 +++++++++++++------ reid_src/borrow_hard.reid | 2 +- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/reid/src/mir/typecheck.rs b/reid/src/mir/typecheck.rs index 6247610..48c1b60 100644 --- a/reid/src/mir/typecheck.rs +++ b/reid/src/mir/typecheck.rs @@ -61,6 +61,8 @@ pub enum ErrorKind { AttemptedDerefNonBorrow(String), #[error("Types {0} and {1} differ in mutability")] TypesDifferMutability(TypeKind, TypeKind), + #[error("Cannot mutably borrow variable {0}, which is not declared as mutable")] + ImpossibleMutableBorrow(String), } /// Struct used to implement a type-checking pass that can be performed on the @@ -633,20 +635,25 @@ impl Expression { Ok(TypeKind::CustomType(struct_name.clone())) } ExprKind::Borrow(var_ref, mutable) => { + let scope_var = state.scope.variables.get(&var_ref.1).cloned(); + let existing = state .or_else( - state - .scope - .variables - .get(&var_ref.1) - .map(|var| &var.ty) - .cloned() + scope_var + .clone() + .map(|var| var.ty) .ok_or(ErrorKind::VariableNotDefined(var_ref.1.clone())), TypeKind::Vague(Vague::Unknown), var_ref.2, ) .resolve_ref(typerefs); + if let Some(scope_var) = scope_var { + if !scope_var.mutable && *mutable { + return Err(ErrorKind::ImpossibleMutableBorrow(var_ref.1.clone())); + } + } + // Update typing to be more accurate var_ref.0 = state.or_else( var_ref.0.resolve_ref(typerefs).collapse_into(&existing), diff --git a/reid_src/borrow_hard.reid b/reid_src/borrow_hard.reid index a074d51..d3cffbe 100644 --- a/reid_src/borrow_hard.reid +++ b/reid_src/borrow_hard.reid @@ -7,7 +7,7 @@ fn changer(param: &mut u32) { fn main() -> u32 { let value = 6; - changer(&mut value); + changer(&value); return value; }