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_code("ParamCountMismatch")
.with_label( .with_label(
Label::new((path, span.into())) 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()), .with_color(colors.next()),
) )
.finish() .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/factorial.ed"), "factorial", false, 24, &[] ; "factorial")]
#[test_case(include_str!("programs/refs.ed"), "refs", false, 2, &[] ; "refs")] #[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.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(include_str!("programs/casts.ed"), "casts", false, 2, &[] ; "casts")]
#[test_case(TEST_ADD, "test_add", false, 2, &[] ; "test_add")] #[test_case(TEST_ADD, "test_add", false, 2, &[] ; "test_add")]
#[test_case(TEST_SUB, "test_sub", false, 1, &[] ; "test_sub")] #[test_case(TEST_SUB, "test_sub", false, 1, &[] ; "test_sub")]

View file

@ -7,6 +7,6 @@ pub fn main() -> i64 {
return a; return a;
} }
pub fn hello(a: &mut i32) { pub fn hello(a: &mut i64) {
*a = 2; *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, needs: usize,
file_id: 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 mut ty = builder.body.locals[local].ty.kind.clone();
let mutable = builder.body.locals[local].mutable;
let mut place = Place { let mut place = Place {
local, local,
projection: Default::default(), 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(); 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..]) { 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); args.push(rvalue);
} }
// insert self // insert self
match &args_ty[0].kind { 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)); 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)); args.insert(0, RValue::Use(Operand::Move(place), *span));
} }
} }