diff --git a/crates/compiler/mono/src/ir.rs b/crates/compiler/mono/src/ir.rs index dba74eace9..4af646b3dd 100644 --- a/crates/compiler/mono/src/ir.rs +++ b/crates/compiler/mono/src/ir.rs @@ -6613,12 +6613,16 @@ pub fn from_can<'a>( branches, final_else, } => { - let ret_layout = layout_cache - .from_var(env.arena, branch_var, env.subs) - .expect("invalid ret_layout"); - let cond_layout = layout_cache - .from_var(env.arena, cond_var, env.subs) - .expect("invalid cond_layout"); + let ret_layout = return_on_layout_error!( + env, + layout_cache.from_var(env.arena, branch_var, env.subs), + "invalid return type in if expression" + ); + let cond_layout = return_on_layout_error!( + env, + layout_cache.from_var(env.arena, cond_var, env.subs), + "invalid condition type in if expression" + ); let mut stmt = from_can(env, branch_var, final_else.value, procs, layout_cache); diff --git a/crates/compiler/test_mono/generated/error_on_erroneous_condition.txt b/crates/compiler/test_mono/generated/error_on_erroneous_condition.txt new file mode 100644 index 0000000000..c588a7f4ff --- /dev/null +++ b/crates/compiler/test_mono/generated/error_on_erroneous_condition.txt @@ -0,0 +1,3 @@ +procedure Test.0 (): + let Test.2 : Str = "Erroneous: invalid condition type in if expression"; + Crash Test.2 diff --git a/crates/compiler/test_mono/src/tests.rs b/crates/compiler/test_mono/src/tests.rs index 076c12ab8a..47cd0de69f 100644 --- a/crates/compiler/test_mono/src/tests.rs +++ b/crates/compiler/test_mono/src/tests.rs @@ -76,7 +76,7 @@ fn promote_expr_to_module(src: &str) -> String { buffer } -fn compiles_to_ir(test_name: &str, src: &str, mode: &str, no_check: bool) { +fn compiles_to_ir(test_name: &str, src: &str, mode: &str, allow_type_errors: bool, no_check: bool) { use roc_packaging::cache::RocCacheDir; use std::path::PathBuf; @@ -146,7 +146,7 @@ fn compiles_to_ir(test_name: &str, src: &str, mode: &str, no_check: bool) { println!("Ignoring {} canonicalization problems", can_problems.len()); } - assert!(type_problems.is_empty()); + assert!(allow_type_errors || type_problems.is_empty()); let main_fn_symbol = exposed_to_host.top_level_values.keys().copied().next(); @@ -2888,3 +2888,14 @@ fn layout_cache_structure_with_multiple_recursive_structures() { "# ) } + +#[mono_test(allow_type_errors = "true")] +fn error_on_erroneous_condition() { + indoc!( + r#" + app "test" provides [main] to "./platform" + + main = if True then 1 else 2 + "# + ) +} diff --git a/crates/compiler/test_mono_macros/src/lib.rs b/crates/compiler/test_mono_macros/src/lib.rs index dedfba5ccd..49114cd200 100644 --- a/crates/compiler/test_mono_macros/src/lib.rs +++ b/crates/compiler/test_mono_macros/src/lib.rs @@ -7,6 +7,7 @@ use quote::quote; #[proc_macro_attribute] pub fn mono_test(args: TokenStream, item: TokenStream) -> TokenStream { let mut no_check = false; + let mut allow_type_errors = false; let mut mode = "exec".to_owned(); for arg in syn::parse_macro_input!(args as syn::AttributeArgs) { use syn::{Lit, Meta, MetaNameValue, NestedMeta}; @@ -22,6 +23,9 @@ pub fn mono_test(args: TokenStream, item: TokenStream) -> TokenStream { if path.is_ident("no_check") { no_check = true; } + if path.is_ident("allow_type_errors") { + allow_type_errors = true; + } } } @@ -40,7 +44,7 @@ pub fn mono_test(args: TokenStream, item: TokenStream) -> TokenStream { #[test] #(#attributes)* #visibility fn #name(#args) { - compiles_to_ir(#name_str, #body, &#mode, #no_check); + compiles_to_ir(#name_str, #body, &#mode, #allow_type_errors, #no_check); } };