mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 06:14:46 +00:00
change constraints gen to give better errors
This commit is contained in:
parent
00978994bf
commit
197abd8553
1 changed files with 21 additions and 20 deletions
|
@ -431,6 +431,7 @@ pub fn constrain_expr(
|
|||
|
||||
match expected {
|
||||
FromAnnotation(name, arity, _, tipe) => {
|
||||
let num_branches = branches.len() + 1;
|
||||
for (index, (loc_cond, loc_body)) in branches.iter().enumerate() {
|
||||
let cond_con = constrain_expr(
|
||||
env,
|
||||
|
@ -448,7 +449,7 @@ pub fn constrain_expr(
|
|||
arity,
|
||||
AnnotationSource::TypedIfBranch {
|
||||
index: Index::zero_based(index),
|
||||
num_branches: branches.len(),
|
||||
num_branches,
|
||||
},
|
||||
tipe.clone(),
|
||||
),
|
||||
|
@ -467,7 +468,7 @@ pub fn constrain_expr(
|
|||
arity,
|
||||
AnnotationSource::TypedIfBranch {
|
||||
index: Index::zero_based(branches.len()),
|
||||
num_branches: branches.len(),
|
||||
num_branches,
|
||||
},
|
||||
tipe.clone(),
|
||||
),
|
||||
|
@ -558,15 +559,12 @@ pub fn constrain_expr(
|
|||
constraints.push(expr_con);
|
||||
|
||||
match &expected {
|
||||
FromAnnotation(name, arity, _, typ) => {
|
||||
// record the type of the whole expression in the AST
|
||||
let ast_con = Eq(
|
||||
Type::Variable(*expr_var),
|
||||
expected.clone(),
|
||||
Category::Storage(std::file!(), std::line!()),
|
||||
region,
|
||||
);
|
||||
constraints.push(ast_con);
|
||||
FromAnnotation(name, arity, _, _typ) => {
|
||||
// NOTE deviation from elm.
|
||||
//
|
||||
// in elm, `_typ` is used, but because we have this `expr_var` too
|
||||
// and need to constrain it, this is what works and gives better error messages
|
||||
let typ = Type::Variable(*expr_var);
|
||||
|
||||
for (index, when_branch) in branches.iter().enumerate() {
|
||||
let pattern_region =
|
||||
|
@ -595,6 +593,10 @@ pub fn constrain_expr(
|
|||
|
||||
constraints.push(branch_con);
|
||||
}
|
||||
|
||||
constraints.push(Eq(typ, expected, Category::When, region));
|
||||
|
||||
return exists(vec![cond_var, *expr_var], And(constraints));
|
||||
}
|
||||
|
||||
_ => {
|
||||
|
@ -1124,7 +1126,6 @@ fn constrain_def(env: &Env, def: &Def, body_con: Constraint) -> Constraint {
|
|||
// NOTE if we ever have problems with the closure, the ignored `_closure_type`
|
||||
// is probably a good place to start the investigation!
|
||||
|
||||
let expected = annotation_expected;
|
||||
let region = def.loc_expr.region;
|
||||
|
||||
let loc_body_expr = &**loc_body;
|
||||
|
@ -1200,12 +1201,15 @@ fn constrain_def(env: &Env, def: &Def, body_con: Constraint) -> Constraint {
|
|||
&mut vars,
|
||||
);
|
||||
|
||||
let fn_type = Type::Function(
|
||||
pattern_types,
|
||||
Box::new(Type::Variable(closure_var)),
|
||||
Box::new(ret_type.clone()),
|
||||
let body_type = FromAnnotation(
|
||||
def.loc_pattern.clone(),
|
||||
arguments.len(),
|
||||
AnnotationSource::TypedBody {
|
||||
region: annotation.region,
|
||||
},
|
||||
ret_type.clone(),
|
||||
);
|
||||
let body_type = NoExpectation(ret_type.clone());
|
||||
|
||||
let ret_constraint =
|
||||
constrain_expr(env, loc_body_expr.region, &loc_body_expr.value, body_type);
|
||||
|
||||
|
@ -1222,9 +1226,6 @@ fn constrain_def(env: &Env, def: &Def, body_con: Constraint) -> Constraint {
|
|||
defs_constraint,
|
||||
ret_constraint,
|
||||
})),
|
||||
// "the closure's type is equal to expected type"
|
||||
Eq(fn_type, expected, Category::Lambda, region),
|
||||
// Store type into AST vars. We use Store so errors aren't reported twice
|
||||
Store(signature.clone(), *fn_var, std::file!(), std::line!()),
|
||||
Store(signature, expr_var, std::file!(), std::line!()),
|
||||
Store(ret_type, ret_var, std::file!(), std::line!()),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue