mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 14:54:47 +00:00
Merge pull request #1609 from rtfeldman/type-error-does-not-generate-function
Type error does not generate function
This commit is contained in:
commit
d15f7480dc
4 changed files with 66 additions and 6 deletions
|
@ -46,7 +46,14 @@ pub fn infer_borrow<'a>(
|
||||||
// component (in top-sorted order, from primitives (std-lib) to main)
|
// component (in top-sorted order, from primitives (std-lib) to main)
|
||||||
|
|
||||||
let successor_map = &make_successor_mapping(arena, procs);
|
let successor_map = &make_successor_mapping(arena, procs);
|
||||||
let successors = move |key: &Symbol| successor_map[key].iter().copied();
|
let successors = move |key: &Symbol| {
|
||||||
|
let slice = match successor_map.get(key) {
|
||||||
|
None => &[] as &[_],
|
||||||
|
Some(s) => s.as_slice(),
|
||||||
|
};
|
||||||
|
|
||||||
|
slice.iter().copied()
|
||||||
|
};
|
||||||
|
|
||||||
let mut symbols = Vec::with_capacity_in(procs.len(), arena);
|
let mut symbols = Vec::with_capacity_in(procs.len(), arena);
|
||||||
symbols.extend(procs.keys().map(|x| x.0));
|
symbols.extend(procs.keys().map(|x| x.0));
|
||||||
|
@ -217,7 +224,10 @@ impl<'a> DeclarationToIndex<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unreachable!("symbol/layout combo must be in DeclarationToIndex")
|
unreachable!(
|
||||||
|
"symbol/layout {:?} {:?} combo must be in DeclarationToIndex",
|
||||||
|
needle_symbol, needle_layout
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6159,6 +6159,38 @@ fn build_call<'a>(
|
||||||
Stmt::Let(assigned, Expr::Call(call), return_layout, hole)
|
Stmt::Let(assigned, Expr::Call(call), return_layout, hole)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// See https://github.com/rtfeldman/roc/issues/1549
|
||||||
|
///
|
||||||
|
/// What happened is that a function has a type error, but the arguments are not processed.
|
||||||
|
/// That means specializations were missing. Normally that is not a problem, but because
|
||||||
|
/// of our closure strategy, internal functions can "leak". That's what happened here.
|
||||||
|
///
|
||||||
|
/// The solution is to evaluate the arguments as normal, and only when calling the function give an error
|
||||||
|
fn evaluate_arguments_then_runtime_error<'a>(
|
||||||
|
env: &mut Env<'a, '_>,
|
||||||
|
procs: &mut Procs<'a>,
|
||||||
|
layout_cache: &mut LayoutCache<'a>,
|
||||||
|
msg: String,
|
||||||
|
loc_args: std::vec::Vec<(Variable, Located<roc_can::expr::Expr>)>,
|
||||||
|
) -> Stmt<'a> {
|
||||||
|
let arena = env.arena;
|
||||||
|
|
||||||
|
// eventually we will throw this runtime error
|
||||||
|
let result = Stmt::RuntimeError(env.arena.alloc(msg));
|
||||||
|
|
||||||
|
// but, we also still evaluate and specialize the arguments to give better error messages
|
||||||
|
let arg_symbols = Vec::from_iter_in(
|
||||||
|
loc_args
|
||||||
|
.iter()
|
||||||
|
.map(|(_, arg_expr)| possible_reuse_symbol(env, procs, &arg_expr.value)),
|
||||||
|
arena,
|
||||||
|
)
|
||||||
|
.into_bump_slice();
|
||||||
|
|
||||||
|
let iter = loc_args.into_iter().rev().zip(arg_symbols.iter().rev());
|
||||||
|
assign_to_symbols(env, procs, layout_cache, iter, result)
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn call_by_name<'a>(
|
fn call_by_name<'a>(
|
||||||
env: &mut Env<'a, '_>,
|
env: &mut Env<'a, '_>,
|
||||||
|
@ -6177,14 +6209,16 @@ fn call_by_name<'a>(
|
||||||
"Hit an unresolved type variable {:?} when creating a layout for {:?} (var {:?})",
|
"Hit an unresolved type variable {:?} when creating a layout for {:?} (var {:?})",
|
||||||
var, proc_name, fn_var
|
var, proc_name, fn_var
|
||||||
);
|
);
|
||||||
Stmt::RuntimeError(env.arena.alloc(msg))
|
|
||||||
|
evaluate_arguments_then_runtime_error(env, procs, layout_cache, msg, loc_args)
|
||||||
}
|
}
|
||||||
Err(LayoutProblem::Erroneous) => {
|
Err(LayoutProblem::Erroneous) => {
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
"Hit an erroneous type when creating a layout for {:?}",
|
"Hit an erroneous type when creating a layout for {:?}",
|
||||||
proc_name
|
proc_name
|
||||||
);
|
);
|
||||||
Stmt::RuntimeError(env.arena.alloc(msg))
|
|
||||||
|
evaluate_arguments_then_runtime_error(env, procs, layout_cache, msg, loc_args)
|
||||||
}
|
}
|
||||||
Ok(RawFunctionLayout::Function(arg_layouts, lambda_set, ret_layout)) => {
|
Ok(RawFunctionLayout::Function(arg_layouts, lambda_set, ret_layout)) => {
|
||||||
if procs.module_thunks.contains(&proc_name) {
|
if procs.module_thunks.contains(&proc_name) {
|
||||||
|
|
|
@ -327,6 +327,14 @@ fn subs_fmt_desc(this: &Descriptor, subs: &Subs, f: &mut fmt::Formatter) -> fmt:
|
||||||
write!(f, " m: {:?}", &this.mark)
|
write!(f, " m: {:?}", &this.mark)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct SubsFmtContent<'a>(pub &'a Content, pub &'a Subs);
|
||||||
|
|
||||||
|
impl<'a> fmt::Debug for SubsFmtContent<'a> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
subs_fmt_content(self.0, self.1, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn subs_fmt_content(this: &Content, subs: &Subs, f: &mut fmt::Formatter) -> fmt::Result {
|
fn subs_fmt_content(this: &Content, subs: &Subs, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match this {
|
match this {
|
||||||
Content::FlexVar(name) => write!(f, "Flex({:?})", name),
|
Content::FlexVar(name) => write!(f, "Flex({:?})", name),
|
||||||
|
@ -345,6 +353,14 @@ fn subs_fmt_content(this: &Content, subs: &Subs, f: &mut fmt::Formatter) -> fmt:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct SubsFmtFlatType<'a>(pub &'a FlatType, pub &'a Subs);
|
||||||
|
|
||||||
|
impl<'a> fmt::Debug for SubsFmtFlatType<'a> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
subs_fmt_flat_type(self.0, self.1, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn subs_fmt_flat_type(this: &FlatType, subs: &Subs, f: &mut fmt::Formatter) -> fmt::Result {
|
fn subs_fmt_flat_type(this: &FlatType, subs: &Subs, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match this {
|
match this {
|
||||||
FlatType::Apply(name, arguments) => {
|
FlatType::Apply(name, arguments) => {
|
||||||
|
|
|
@ -1076,8 +1076,8 @@ fn unify_flat_type(
|
||||||
// any other combination is a mismatch
|
// any other combination is a mismatch
|
||||||
mismatch!(
|
mismatch!(
|
||||||
"Trying to unify two flat types that are incompatible: {:?} ~ {:?}",
|
"Trying to unify two flat types that are incompatible: {:?} ~ {:?}",
|
||||||
other1,
|
roc_types::subs::SubsFmtFlatType(other1, subs),
|
||||||
other2
|
roc_types::subs::SubsFmtFlatType(other2, subs)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue