mirror of
https://github.com/edg-l/edlang.git
synced 2024-11-22 07:58:24 +00:00
add asref check
This commit is contained in:
parent
9a7e510e1f
commit
7657a05ebd
|
@ -201,16 +201,28 @@ pub fn lowering_error_to_report(
|
|||
)
|
||||
.finish()
|
||||
}
|
||||
LoweringError::NotMutable { span, file_id } => {
|
||||
LoweringError::NotMutable {
|
||||
span,
|
||||
declare_span,
|
||||
file_id,
|
||||
} => {
|
||||
let path = session.file_paths[file_id].display().to_string();
|
||||
Report::build(ReportKind::Error, path.clone(), span.lo)
|
||||
let mut report = Report::build(ReportKind::Error, path.clone(), span.lo)
|
||||
.with_code("NotMutable")
|
||||
.with_label(
|
||||
Label::new((path, span.into()))
|
||||
.with_message("can't mutate this value because it's not declared mutable")
|
||||
Label::new((path.clone(), span.into()))
|
||||
.with_message("can't mutate this variable because it's not mutable")
|
||||
.with_color(colors.next()),
|
||||
)
|
||||
.finish()
|
||||
);
|
||||
|
||||
if let Some(declare_span) = declare_span {
|
||||
report = report.with_label(
|
||||
Label::new((path, declare_span.into()))
|
||||
.with_message("variable declared here")
|
||||
.with_color(colors.next()),
|
||||
);
|
||||
}
|
||||
report.finish()
|
||||
}
|
||||
LoweringError::NotMutableSelf {
|
||||
span,
|
||||
|
@ -232,5 +244,28 @@ pub fn lowering_error_to_report(
|
|||
)
|
||||
.finish()
|
||||
}
|
||||
LoweringError::CantTakeMutableBorrow {
|
||||
span,
|
||||
declare_span,
|
||||
file_id,
|
||||
} => {
|
||||
let path = session.file_paths[file_id].display().to_string();
|
||||
let mut report = Report::build(ReportKind::Error, path.clone(), span.lo)
|
||||
.with_code("CantTakeMutableBorrow")
|
||||
.with_label(
|
||||
Label::new((path.clone(), span.into()))
|
||||
.with_message("can't take a mutate borrow to this variable because it's not declared mutable")
|
||||
.with_color(colors.next()),
|
||||
);
|
||||
|
||||
if let Some(declare_span) = declare_span {
|
||||
report = report.with_label(
|
||||
Label::new((path, declare_span.into()))
|
||||
.with_message("variable declared here")
|
||||
.with_color(colors.next()),
|
||||
);
|
||||
}
|
||||
report.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
fn main() -> i32 {
|
||||
let foo: i32 = 7;
|
||||
let mut foo: i32 = 7;
|
||||
|
||||
if true {
|
||||
if false {
|
||||
|
|
|
@ -178,6 +178,18 @@ impl Local {
|
|||
mutable: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_mutable(&self) -> bool {
|
||||
if self.mutable {
|
||||
return true;
|
||||
}
|
||||
|
||||
match self.ty.kind {
|
||||
TypeKind::Ptr(is_mut, _) => is_mut,
|
||||
TypeKind::Ref(is_mut, _) => is_mut,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
|
@ -424,6 +436,19 @@ pub enum RValue {
|
|||
Cast(Operand, TypeInfo, Span),
|
||||
}
|
||||
|
||||
impl RValue {
|
||||
pub fn get_local(&self) -> Option<usize> {
|
||||
match self {
|
||||
RValue::Use(op, _) => op.get_local(),
|
||||
RValue::Ref(_, op, _) => op.get_local(),
|
||||
RValue::BinOp(_, _, _, _) => None,
|
||||
RValue::LogicOp(_, _, _, _) => None,
|
||||
RValue::UnOp(_, _, _) => None,
|
||||
RValue::Cast(op, _, _) => op.get_local(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Operand {
|
||||
Copy(Place),
|
||||
|
@ -431,6 +456,16 @@ pub enum Operand {
|
|||
Constant(ConstData),
|
||||
}
|
||||
|
||||
impl Operand {
|
||||
pub fn get_local(&self) -> Option<usize> {
|
||||
match self {
|
||||
Operand::Copy(place) => Some(place.local),
|
||||
Operand::Move(place) => Some(place.local),
|
||||
Operand::Constant(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Place {
|
||||
pub local: usize,
|
||||
|
|
|
@ -71,7 +71,17 @@ pub enum LoweringError {
|
|||
file_id: usize,
|
||||
},
|
||||
#[error("can't mutate this value because it's not declared mutable")]
|
||||
NotMutable { span: Span, file_id: usize },
|
||||
NotMutable {
|
||||
span: Span,
|
||||
declare_span: Option<Span>,
|
||||
file_id: usize,
|
||||
},
|
||||
#[error("can't take a mutable borrow to this value because it's not declared mutable")]
|
||||
CantTakeMutableBorrow {
|
||||
span: Span,
|
||||
declare_span: Option<Span>,
|
||||
file_id: usize,
|
||||
},
|
||||
#[error("this method requires a mutable 'self'")]
|
||||
NotMutableSelf {
|
||||
span: Span,
|
||||
|
|
|
@ -536,6 +536,14 @@ fn lower_assign(builder: &mut BodyBuilder, info: &ast::AssignStmt) -> Result<(),
|
|||
kind: ty,
|
||||
};
|
||||
|
||||
if !builder.body.locals[place.local].is_mutable() {
|
||||
return Err(LoweringError::NotMutable {
|
||||
span: info.span,
|
||||
declare_span: builder.body.locals[place.local].span,
|
||||
file_id: builder.file_id,
|
||||
});
|
||||
}
|
||||
|
||||
for _ in 0..info.deref_times {
|
||||
match &path_ty.kind {
|
||||
TypeKind::Ptr(is_mut, inner) => {
|
||||
|
@ -687,7 +695,7 @@ fn lower_expr(
|
|||
let ty = match ty {
|
||||
TypeKind::Ptr(_, inner) => *inner,
|
||||
TypeKind::Ref(_, inner) => *inner,
|
||||
_ => todo!("proepr error here"),
|
||||
_ => todo!("proper error here"),
|
||||
};
|
||||
|
||||
(
|
||||
|
@ -706,6 +714,16 @@ fn lower_expr(
|
|||
};
|
||||
let (mut value, ty, _span) = lower_expr(builder, inner, type_hint)?;
|
||||
|
||||
if let Some(local) = value.get_local() {
|
||||
if *mutable && !builder.body.locals[local].mutable {
|
||||
return Err(LoweringError::CantTakeMutableBorrow {
|
||||
span: *as_ref_span,
|
||||
declare_span: builder.body.locals[local].span,
|
||||
file_id: builder.file_id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// check if its a use directly, to avoid a temporary.
|
||||
value = match value {
|
||||
RValue::Use(op, _span) => RValue::Ref(*mutable, op, *as_ref_span),
|
||||
|
|
Loading…
Reference in a new issue