feat: more checks on impl blocks

This commit is contained in:
Edgar 2024-05-07 08:49:40 +02:00
parent 637aa8e229
commit 91fc31b627
No known key found for this signature in database
GPG key ID: 70ADAE8F35904387
6 changed files with 116 additions and 12 deletions

View file

@ -193,10 +193,44 @@ pub fn lowering_error_to_report(
.with_code("ParamCountMismatch")
.with_label(
Label::new((path, span.into()))
.with_message(format!("function call parameter count mismatch: has {}, needs {}.", has_args, needs))
.with_message(format!(
"function call parameter count mismatch: has {}, needs {}.",
has_args, needs
))
.with_color(colors.next()),
)
.finish()
},
}
LoweringError::NotMutable { span, file_id } => {
let path = session.file_paths[file_id].display().to_string();
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")
.with_color(colors.next()),
)
.finish()
}
LoweringError::NotMutableSelf {
span,
path_span,
file_id,
} => {
let path = session.file_paths[file_id].display().to_string();
Report::build(ReportKind::Error, path.clone(), span.lo)
.with_code("NotMutableSelf")
.with_label(
Label::new((path.clone(), path_span.into()))
.with_message("this value is not declared mutable")
.with_color(colors.next()),
)
.with_label(
Label::new((path, span.into()))
.with_message("this method requires a mutable 'self'")
.with_color(colors.next()),
)
.finish()
}
}
}

View file

@ -10,6 +10,7 @@ mod common;
#[test_case(include_str!("programs/factorial.ed"), "factorial", false, 24, &[] ; "factorial")]
#[test_case(include_str!("programs/refs.ed"), "refs", false, 2, &[] ; "refs")]
#[test_case(include_str!("programs/struct.ed"), "struct", false, 5, &[] ; "r#struct")]
#[test_case(include_str!("programs/struct_impl.ed"), "struct_impl", false, 6, &[] ; "struct_impl")]
#[test_case(include_str!("programs/casts.ed"), "casts", false, 2, &[] ; "casts")]
#[test_case(TEST_ADD, "test_add", false, 2, &[] ; "test_add")]
#[test_case(TEST_SUB, "test_sub", false, 1, &[] ; "test_sub")]

View file

@ -7,6 +7,6 @@ pub fn main() -> i64 {
return a;
}
pub fn hello(a: &mut i32) {
pub fn hello(a: &mut i64) {
*a = 2;
}

View file

@ -0,0 +1,21 @@
extern fn printf(a: &str);
fn main() -> u32 {
let x: A = A {
a: 2
};
let y: u32 = x.hello(4);
return y;
}
struct A {
a: u32,
}
impl A {
pub fn hello(self: &A, x: u32) -> u32 {
return self.a + x;
}
}

View file

@ -70,4 +70,12 @@ pub enum LoweringError {
needs: usize,
file_id: usize,
},
#[error("can't mutate this value because it's not declared mutable")]
NotMutable { span: Span, file_id: usize },
#[error("this method requires a mutable 'self'")]
NotMutableSelf {
span: Span,
path_span: Span,
file_id: usize,
},
}

View file

@ -1277,6 +1277,7 @@ fn lower_path(
)?;
let mut ty = builder.body.locals[local].ty.kind.clone();
let mutable = builder.body.locals[local].mutable;
let mut place = Place {
local,
projection: Default::default(),
@ -1353,26 +1354,65 @@ fn lower_path(
}
};
if args_ty.len() - 1 != value.params.len() {
return Err(LoweringError::ParamCountMismatch {
span: value.span,
has_args: value.params.len(),
needs: args_ty.len(),
file_id: builder.file_id,
});
}
let mut args = Vec::new();
assert_eq!(
args_ty.len() - 1,
value.params.len(),
"param length mismatch"
);
for (arg, arg_ty) in value.params.iter().zip(&args_ty[1..]) {
let (rvalue, _rvalue_ty, _span) = lower_expr(builder, arg, Some(arg_ty))?;
let (rvalue, rvalue_ty, arg_span) = lower_expr(builder, arg, Some(arg_ty))?;
if rvalue_ty != arg_ty.kind {
return Err(LoweringError::UnexpectedType {
span: arg_span,
found: rvalue_ty,
expected: arg_ty.clone(),
file_id: builder.file_id,
});
}
args.push(rvalue);
}
// insert self
match &args_ty[0].kind {
TypeKind::Ptr(is_mut, _) | TypeKind::Ref(is_mut, _) => {
TypeKind::Ptr(is_mut, inner_ty) | TypeKind::Ref(is_mut, inner_ty) => {
if ty != inner_ty.kind {
return Err(LoweringError::UnexpectedType {
span: info.span,
found: inner_ty.kind.clone(),
expected: args_ty[0].clone(),
file_id: builder.file_id,
});
}
if !mutable && *is_mut {
return Err(LoweringError::NotMutableSelf {
span: value.span,
path_span: info.span,
file_id: builder.file_id,
});
}
args.insert(0, RValue::Ref(*is_mut, Operand::Move(place), *span));
}
_ => {
expected_ty => {
if ty != *expected_ty {
return Err(LoweringError::UnexpectedType {
span: value.span,
found: ty.clone(),
expected: args_ty[0].clone(),
file_id: builder.file_id,
});
}
args.insert(0, RValue::Use(Operand::Move(place), *span));
}
}