Normalize c/Roc callconv parameters when C returns by pointer

Closes #2413
This commit is contained in:
ayazhafiz 2022-02-06 21:57:14 -05:00
parent 365b3bb9c0
commit 1a1eaf7f68
2 changed files with 46 additions and 5 deletions

View file

@ -3600,11 +3600,14 @@ fn expose_function_to_host_help_c_abi_v2<'a, 'ctx, 'env>(
let param_types = Vec::from_iter_in(roc_function.get_type().get_param_types(), env.arena);
// drop the "return pointer" if it exists on the roc function
let (params, param_types) = match (&roc_return, &cc_return) {
// Drop the "return pointer" if it exists on the roc function
// and the c function does not return via pointer
let param_types = match (&roc_return, &cc_return) {
(RocReturn::ByPointer, CCReturn::Return) => &param_types[1..],
_ => &param_types,
(RocReturn::ByPointer, CCReturn::Return) => (&params[..], &param_types[1..]),
// Drop the return pointer the other way, if the C function returns by pointer but Roc
// doesn't
(RocReturn::Return, CCReturn::ByPointer) => (&params[1..], &param_types[..]),
_ => (&params[..], &param_types[..]),
};
debug_assert_eq!(params.len(), param_types.len());

View file

@ -648,4 +648,42 @@ mod test_load {
Ok(_) => unreachable!("we expect failure here"),
}
}
#[test]
// See https://github.com/rtfeldman/roc/issues/2413
fn platform_exposes_main_return_by_pointer_issue() {
let modules = vec![
(
"platform/Package-Config.roc",
indoc!(
r#"
platform "examples/hello-world"
requires {} { main : { content: Str, other: Str } }
exposes []
packages {}
imports []
provides [ mainForHost ]
mainForHost : { content: Str, other: Str }
mainForHost = main
"#
),
),
(
"Main",
indoc!(
r#"
app "hello-world"
packages { pf: "platform" }
imports []
provides [ main ] to pf
main = { content: "Hello, World!\n", other: "" }
"#
),
),
];
assert!(multiple_modules(modules).is_ok());
}
}