mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +00:00
Turn invalid record field types into runtime errors
By emitting a runtime error rather than panicking when we can't layout a record, we help programs like ``` main = get = \{a} -> a get {b: "hello world"} ``` execute as ``` Mismatch in compiler/unify/src/unify.rs Line 1071 Column 13 Trying to unify two flat types that are incompatible: EmptyRecord ~ { 'a' : Demanded(122), }<130> 🔨 Rebuilding host... ── TYPE MISMATCH ─────────────────────────────────────────────────────────────── The 1st argument to get is not what I expect: 8│ get {b: "hello world"} ^^^^^^^^^^^^^^^^^^ This argument is a record of type: { b : Str } But get needs the 1st argument to be: { a : a }b Tip: Seems like a record field typo. Maybe a should be b? Tip: Can more type annotations be added? Type annotations always help me give more specific messages, and I think they could help a lot in this case ──────────────────────────────────────────────────────────────────────────────── '+fast-variable-shuffle' is not a recognized feature for this target (ignoring feature) '+fast-variable-shuffle' is not a recognized feature for this target (ignoring feature) Done! Application crashed with message Can't create record with improper layout Shutting down ``` rather than the hanging ``` Mismatch in compiler/unify/src/unify.rs Line 1071 Column 13 Trying to unify two flat types that are incompatible: EmptyRecord ~ { 'a' : Demanded(122), }<130> thread '<unnamed>' panicked at 'invalid layout from var: UnresolvedTypeVar(104)', compiler/mono/s rc/layout.rs:1510:52 ``` that was previously produced. Part of #2227
This commit is contained in:
parent
e728e319c6
commit
576f1293fd
7 changed files with 96 additions and 51 deletions
|
@ -3325,8 +3325,15 @@ pub fn with_hole<'a>(
|
|||
mut fields,
|
||||
..
|
||||
} => {
|
||||
let sorted_fields =
|
||||
crate::layout::sort_record_fields(env.arena, record_var, env.subs, env.ptr_bytes);
|
||||
let sorted_fields = match crate::layout::sort_record_fields(
|
||||
env.arena,
|
||||
record_var,
|
||||
env.subs,
|
||||
env.ptr_bytes,
|
||||
) {
|
||||
Ok(fields) => fields,
|
||||
Err(_) => return Stmt::RuntimeError("Can't create record with improper layout"),
|
||||
};
|
||||
|
||||
let mut field_symbols = Vec::with_capacity_in(fields.len(), env.arena);
|
||||
let mut can_fields = Vec::with_capacity_in(fields.len(), env.arena);
|
||||
|
@ -3678,8 +3685,15 @@ pub fn with_hole<'a>(
|
|||
loc_expr,
|
||||
..
|
||||
} => {
|
||||
let sorted_fields =
|
||||
crate::layout::sort_record_fields(env.arena, record_var, env.subs, env.ptr_bytes);
|
||||
let sorted_fields = match crate::layout::sort_record_fields(
|
||||
env.arena,
|
||||
record_var,
|
||||
env.subs,
|
||||
env.ptr_bytes,
|
||||
) {
|
||||
Ok(fields) => fields,
|
||||
Err(_) => return Stmt::RuntimeError("Can't access record with improper layout"),
|
||||
};
|
||||
|
||||
let mut index = None;
|
||||
let mut field_layouts = Vec::with_capacity_in(sorted_fields.len(), env.arena);
|
||||
|
@ -3821,8 +3835,15 @@ pub fn with_hole<'a>(
|
|||
// This has the benefit that we don't need to do anything special for reference
|
||||
// counting
|
||||
|
||||
let sorted_fields =
|
||||
crate::layout::sort_record_fields(env.arena, record_var, env.subs, env.ptr_bytes);
|
||||
let sorted_fields = match crate::layout::sort_record_fields(
|
||||
env.arena,
|
||||
record_var,
|
||||
env.subs,
|
||||
env.ptr_bytes,
|
||||
) {
|
||||
Ok(fields) => fields,
|
||||
Err(_) => return Stmt::RuntimeError("Can't update record with improper layout"),
|
||||
};
|
||||
|
||||
let mut field_layouts = Vec::with_capacity_in(sorted_fields.len(), env.arena);
|
||||
|
||||
|
@ -4378,11 +4399,7 @@ pub fn with_hole<'a>(
|
|||
}
|
||||
}
|
||||
}
|
||||
RuntimeError(e) => {
|
||||
eprintln!("emitted runtime error {:?}", &e);
|
||||
|
||||
Stmt::RuntimeError(env.arena.alloc(format!("{:?}", e)))
|
||||
}
|
||||
RuntimeError(e) => Stmt::RuntimeError(env.arena.alloc(format!("{:?}", e))),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7369,7 +7386,8 @@ fn from_can_pattern_help<'a>(
|
|||
use crate::layout::UnionVariant::*;
|
||||
|
||||
let res_variant =
|
||||
crate::layout::union_sorted_tags(env.arena, *whole_var, env.subs, env.ptr_bytes);
|
||||
crate::layout::union_sorted_tags(env.arena, *whole_var, env.subs, env.ptr_bytes)
|
||||
.map_err(Into::into);
|
||||
|
||||
let variant = match res_variant {
|
||||
Ok(cached) => cached,
|
||||
|
@ -7789,7 +7807,8 @@ fn from_can_pattern_help<'a>(
|
|||
} => {
|
||||
// sorted fields based on the type
|
||||
let sorted_fields =
|
||||
crate::layout::sort_record_fields(env.arena, *whole_var, env.subs, env.ptr_bytes);
|
||||
crate::layout::sort_record_fields(env.arena, *whole_var, env.subs, env.ptr_bytes)
|
||||
.map_err(Into::into)?;
|
||||
|
||||
// sorted fields based on the destruct
|
||||
let mut mono_destructs = Vec::with_capacity_in(destructs.len(), env.arena);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue