From b52af8ae6d2510c77a91e49e24734b25783a7bb7 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Tue, 7 May 2024 08:24:22 +0200 Subject: [PATCH 1/2] add function call type checks --- crates/concrete_check/src/lib.rs | 19 +++++++++++ crates/concrete_driver/tests/checks.rs | 33 +++++++++++++++++++ .../invalid_programs/call_count_mismatch.con | 9 +++++ .../invalid_programs/invalid_call_params.con | 10 ++++++ crates/concrete_ir/src/lowering.rs | 23 +++++++++++-- crates/concrete_ir/src/lowering/errors.rs | 7 ++++ 6 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 crates/concrete_driver/tests/invalid_programs/call_count_mismatch.con create mode 100644 crates/concrete_driver/tests/invalid_programs/invalid_call_params.con diff --git a/crates/concrete_check/src/lib.rs b/crates/concrete_check/src/lib.rs index 608d53b..6289620 100644 --- a/crates/concrete_check/src/lib.rs +++ b/crates/concrete_check/src/lib.rs @@ -222,5 +222,24 @@ pub fn lowering_error_to_report( .with_message(msg) .finish() } + LoweringError::CallParamCountMismatch { + span, + found, + needs, + program_id, + } => { + let path = file_paths[program_id].to_str().unwrap().to_string(); + Report::build(ReportKind::Error, path.clone(), span.from) + .with_code("CallParamCountMismatch") + .with_label( + Label::new((path, span.into())) + .with_message(format!( + "function call parameter count mismatch: found {}, needs {}.", + found, needs + )) + .with_color(colors.next()), + ) + .finish() + } } } diff --git a/crates/concrete_driver/tests/checks.rs b/crates/concrete_driver/tests/checks.rs index 2a5e670..d4af71d 100644 --- a/crates/concrete_driver/tests/checks.rs +++ b/crates/concrete_driver/tests/checks.rs @@ -102,3 +102,36 @@ fn undeclared_var() { error ); } + +#[test] +fn call_count_mismatch() { + let (source, name) = ( + include_str!("invalid_programs/call_count_mismatch.con"), + "call_count_mismatch", + ); + let error = check_invalid_program(source, name); + + assert!( + matches!( + &error, + LoweringError::CallParamCountMismatch { found, needs, .. } if *found == 2 && *needs == 1 + ), + "{:#?}", + error + ); +} + +#[test] +fn invalid_call_params() { + let (source, name) = ( + include_str!("invalid_programs/invalid_call_params.con"), + "invalid_call_params", + ); + let error = check_invalid_program(source, name); + + assert!( + matches!(&error, LoweringError::UnexpectedType { .. }), + "{:#?}", + error + ); +} diff --git a/crates/concrete_driver/tests/invalid_programs/call_count_mismatch.con b/crates/concrete_driver/tests/invalid_programs/call_count_mismatch.con new file mode 100644 index 0000000..8fd3b1f --- /dev/null +++ b/crates/concrete_driver/tests/invalid_programs/call_count_mismatch.con @@ -0,0 +1,9 @@ +mod Test { + fn main() -> i32 { + return hello(1, 2); + } + + fn hello(a: i32) -> i32 { + return a * 2; + } +} diff --git a/crates/concrete_driver/tests/invalid_programs/invalid_call_params.con b/crates/concrete_driver/tests/invalid_programs/invalid_call_params.con new file mode 100644 index 0000000..6ae9715 --- /dev/null +++ b/crates/concrete_driver/tests/invalid_programs/invalid_call_params.con @@ -0,0 +1,10 @@ +mod Test { + fn main() -> i32 { + let x: u32 = 1; + return hello(x); + } + + fn hello(a: i32) -> i32 { + return a * 2; + } +} diff --git a/crates/concrete_ir/src/lowering.rs b/crates/concrete_ir/src/lowering.rs index 6cf620e..fefd5f8 100644 --- a/crates/concrete_ir/src/lowering.rs +++ b/crates/concrete_ir/src/lowering.rs @@ -1179,11 +1179,30 @@ fn lower_fn_call( } }; + if args_ty.len() != info.args.len() { + return Err(LoweringError::CallParamCountMismatch { + span: info.span, + found: info.args.len(), + needs: args_ty.len(), + program_id: builder.get_module_body().id.program_id, + }); + } + let mut args = Vec::new(); for (arg, arg_ty) in info.args.iter().zip(args_ty) { - let rvalue = lower_expression(builder, arg, Some(arg_ty.clone()))?; - args.push(rvalue.0); + let (rvalue, rvalue_ty, arg_span) = lower_expression(builder, arg, Some(arg_ty.clone()))?; + + if rvalue_ty.kind != arg_ty.kind { + return Err(LoweringError::UnexpectedType { + span: arg_span, + found: rvalue_ty, + expected: arg_ty, + program_id: builder.get_module_body().id.program_id, + }); + } + + args.push(rvalue); } let dest_local = builder.add_local(Local::temp(ret_ty.clone())); diff --git a/crates/concrete_ir/src/lowering/errors.rs b/crates/concrete_ir/src/lowering/errors.rs index 48d9a58..febab2d 100644 --- a/crates/concrete_ir/src/lowering/errors.rs +++ b/crates/concrete_ir/src/lowering/errors.rs @@ -76,4 +76,11 @@ pub enum LoweringError { }, #[error("internal error: {0}")] InternalError(String, usize), + #[error("function call parameter count mismatch, found {found}, needs {needs}")] + CallParamCountMismatch { + span: Span, + found: usize, + needs: usize, + program_id: usize, + }, } From 5644d2f060a83a7b44ce717bb68975c77b54684d Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Wed, 8 May 2024 11:38:15 +0200 Subject: [PATCH 2/2] apply suggestions --- crates/concrete_check/src/lib.rs | 26 +++++++++---------- crates/concrete_driver/tests/checks.rs | 12 ++++----- ...atch.con => call_param_count_mismatch.con} | 0 ...arams.con => call_param_type_mismatch.con} | 0 4 files changed, 19 insertions(+), 19 deletions(-) rename crates/concrete_driver/tests/invalid_programs/{call_count_mismatch.con => call_param_count_mismatch.con} (100%) rename crates/concrete_driver/tests/invalid_programs/{invalid_call_params.con => call_param_type_mismatch.con} (100%) diff --git a/crates/concrete_check/src/lib.rs b/crates/concrete_check/src/lib.rs index 6289620..81830c4 100644 --- a/crates/concrete_check/src/lib.rs +++ b/crates/concrete_check/src/lib.rs @@ -17,7 +17,7 @@ pub fn lowering_error_to_report( program_id, } => { let offset = span.from; - let path = file_paths[program_id].to_str().unwrap().to_string(); + let path = file_paths[program_id].display().to_string(); Report::build(ReportKind::Error, path.clone(), offset) .with_code("ModuleNotFound") .with_label( @@ -33,7 +33,7 @@ pub fn lowering_error_to_report( function, program_id, } => { - let path = file_paths[program_id].to_str().unwrap().to_string(); + let path = file_paths[program_id].display().to_string(); Report::build(ReportKind::Error, path.clone(), span.from) .with_code("FunctionNotFound") .with_label( @@ -48,7 +48,7 @@ pub fn lowering_error_to_report( name, program_id, } => { - let path = file_paths[program_id].to_str().unwrap().to_string(); + let path = file_paths[program_id].display().to_string(); Report::build(ReportKind::Error, path.clone(), span.from) .with_code("StructFieldNotFound") .with_label( @@ -64,7 +64,7 @@ pub fn lowering_error_to_report( symbol, program_id, } => { - let path = file_paths[program_id].to_str().unwrap().to_string(); + let path = file_paths[program_id].display().to_string(); let offset = symbol.span.from; Report::build(ReportKind::Error, path.clone(), offset) .with_code("ImportNotFound") @@ -90,7 +90,7 @@ pub fn lowering_error_to_report( type_span, program_id, } => { - let path = file_paths[program_id].to_str().unwrap().to_string(); + let path = file_paths[program_id].display().to_string(); let mut labels = vec![Label::new((path.clone(), span.into())) .with_message(format!( "Can't mutate {name:?} because it's behind a immutable borrow" @@ -115,7 +115,7 @@ pub fn lowering_error_to_report( name, program_id, } => { - let path = file_paths[program_id].to_str().unwrap().to_string(); + let path = file_paths[program_id].display().to_string(); Report::build(ReportKind::Error, path.clone(), span.from) .with_code("UnrecognizedType") .with_label( @@ -131,7 +131,7 @@ pub fn lowering_error_to_report( id, program_id, } => { - let path = file_paths[program_id].to_str().unwrap().to_string(); + let path = file_paths[program_id].display().to_string(); Report::build(ReportKind::Error, path.clone(), span.from) .with_code("E_ID") .with_label( @@ -147,7 +147,7 @@ pub fn lowering_error_to_report( message, program_id, } => { - let path = file_paths[program_id].to_str().unwrap().to_string(); + let path = file_paths[program_id].display().to_string(); Report::build(ReportKind::Error, path.clone(), span.from) .with_code("NotYetImplemented") .with_label( @@ -163,7 +163,7 @@ pub fn lowering_error_to_report( expected, program_id, } => { - let path = file_paths[program_id].to_str().unwrap().to_string(); + let path = file_paths[program_id].display().to_string(); let mut labels = vec![Label::new((path.clone(), span.into())) .with_message(format!( "Unexpected type '{}', expected '{}'", @@ -190,7 +190,7 @@ pub fn lowering_error_to_report( name, program_id, } => { - let path = file_paths[program_id].to_str().unwrap().to_string(); + let path = file_paths[program_id].display().to_string(); Report::build(ReportKind::Error, path.clone(), span.from) .with_code("UseOfUndeclaredVariable") .with_label( @@ -205,7 +205,7 @@ pub fn lowering_error_to_report( name, program_id, } => { - let path = file_paths[program_id].to_str().unwrap().to_string(); + let path = file_paths[program_id].display().to_string(); Report::build(ReportKind::Error, path.clone(), span.from) .with_code("ExternFnWithBody") .with_label( @@ -216,7 +216,7 @@ pub fn lowering_error_to_report( .finish() } LoweringError::InternalError(msg, program_id) => { - let path = file_paths[program_id].to_str().unwrap().to_string(); + let path = file_paths[program_id].display().to_string(); Report::build(ReportKind::Error, path.clone(), 0) .with_code("InternalError") .with_message(msg) @@ -228,7 +228,7 @@ pub fn lowering_error_to_report( needs, program_id, } => { - let path = file_paths[program_id].to_str().unwrap().to_string(); + let path = file_paths[program_id].display().to_string(); Report::build(ReportKind::Error, path.clone(), span.from) .with_code("CallParamCountMismatch") .with_label( diff --git a/crates/concrete_driver/tests/checks.rs b/crates/concrete_driver/tests/checks.rs index d4af71d..b5368ae 100644 --- a/crates/concrete_driver/tests/checks.rs +++ b/crates/concrete_driver/tests/checks.rs @@ -104,10 +104,10 @@ fn undeclared_var() { } #[test] -fn call_count_mismatch() { +fn call_param_count_mismatch() { let (source, name) = ( - include_str!("invalid_programs/call_count_mismatch.con"), - "call_count_mismatch", + include_str!("invalid_programs/call_param_count_mismatch.con"), + "call_param_count_mismatch", ); let error = check_invalid_program(source, name); @@ -122,10 +122,10 @@ fn call_count_mismatch() { } #[test] -fn invalid_call_params() { +fn call_param_type_mismatch() { let (source, name) = ( - include_str!("invalid_programs/invalid_call_params.con"), - "invalid_call_params", + include_str!("invalid_programs/call_param_type_mismatch.con"), + "call_param_type_mismatch", ); let error = check_invalid_program(source, name); diff --git a/crates/concrete_driver/tests/invalid_programs/call_count_mismatch.con b/crates/concrete_driver/tests/invalid_programs/call_param_count_mismatch.con similarity index 100% rename from crates/concrete_driver/tests/invalid_programs/call_count_mismatch.con rename to crates/concrete_driver/tests/invalid_programs/call_param_count_mismatch.con diff --git a/crates/concrete_driver/tests/invalid_programs/invalid_call_params.con b/crates/concrete_driver/tests/invalid_programs/call_param_type_mismatch.con similarity index 100% rename from crates/concrete_driver/tests/invalid_programs/invalid_call_params.con rename to crates/concrete_driver/tests/invalid_programs/call_param_type_mismatch.con