Check borrow mutability against variable mutability
This commit is contained in:
parent
1fadaa60f2
commit
5763df948f
@ -61,6 +61,8 @@ pub enum ErrorKind {
|
|||||||
AttemptedDerefNonBorrow(String),
|
AttemptedDerefNonBorrow(String),
|
||||||
#[error("Types {0} and {1} differ in mutability")]
|
#[error("Types {0} and {1} differ in mutability")]
|
||||||
TypesDifferMutability(TypeKind, TypeKind),
|
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
|
/// 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()))
|
Ok(TypeKind::CustomType(struct_name.clone()))
|
||||||
}
|
}
|
||||||
ExprKind::Borrow(var_ref, mutable) => {
|
ExprKind::Borrow(var_ref, mutable) => {
|
||||||
|
let scope_var = state.scope.variables.get(&var_ref.1).cloned();
|
||||||
|
|
||||||
let existing = state
|
let existing = state
|
||||||
.or_else(
|
.or_else(
|
||||||
state
|
scope_var
|
||||||
.scope
|
.clone()
|
||||||
.variables
|
.map(|var| var.ty)
|
||||||
.get(&var_ref.1)
|
|
||||||
.map(|var| &var.ty)
|
|
||||||
.cloned()
|
|
||||||
.ok_or(ErrorKind::VariableNotDefined(var_ref.1.clone())),
|
.ok_or(ErrorKind::VariableNotDefined(var_ref.1.clone())),
|
||||||
TypeKind::Vague(Vague::Unknown),
|
TypeKind::Vague(Vague::Unknown),
|
||||||
var_ref.2,
|
var_ref.2,
|
||||||
)
|
)
|
||||||
.resolve_ref(typerefs);
|
.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
|
// Update typing to be more accurate
|
||||||
var_ref.0 = state.or_else(
|
var_ref.0 = state.or_else(
|
||||||
var_ref.0.resolve_ref(typerefs).collapse_into(&existing),
|
var_ref.0.resolve_ref(typerefs).collapse_into(&existing),
|
||||||
|
@ -7,7 +7,7 @@ fn changer(param: &mut u32) {
|
|||||||
fn main() -> u32 {
|
fn main() -> u32 {
|
||||||
let value = 6;
|
let value = 6;
|
||||||
|
|
||||||
changer(&mut value);
|
changer(&value);
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user