Surface constrain_expr takes an index

This commit is contained in:
Ayaz Hafiz 2022-11-07 16:36:23 -06:00
parent 9abed3472a
commit 4e2eb67ff1
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
3 changed files with 82 additions and 52 deletions

View file

@ -6,7 +6,9 @@ use crate::builtins::{
}; };
use crate::pattern::{constrain_pattern, PatternState}; use crate::pattern::{constrain_pattern, PatternState};
use roc_can::annotation::IntroducedVariables; use roc_can::annotation::IntroducedVariables;
use roc_can::constraint::{Constraint, Constraints, OpportunisticResolve, TypeOrVar}; use roc_can::constraint::{
Constraint, Constraints, ExpectedTypeIndex, OpportunisticResolve, TypeOrVar,
};
use roc_can::def::Def; use roc_can::def::Def;
use roc_can::exhaustive::{sketch_pattern_to_rows, sketch_when_branches, ExhaustiveContext}; use roc_can::exhaustive::{sketch_pattern_to_rows, sketch_when_branches, ExhaustiveContext};
use roc_can::expected::Expected::{self, *}; use roc_can::expected::Expected::{self, *};
@ -121,7 +123,7 @@ fn constrain_untyped_closure(
vars.push(closure_var); vars.push(closure_var);
vars.push(fn_var); vars.push(fn_var);
let body_type = NoExpectation(return_type_index); let body_type = constraints.push_expected_type(NoExpectation(return_type_index));
let ret_constraint = constrain_expr( let ret_constraint = constrain_expr(
constraints, constraints,
env, env,
@ -174,6 +176,17 @@ fn constrain_untyped_closure(
} }
pub fn constrain_expr( pub fn constrain_expr(
constraints: &mut Constraints,
env: &mut Env,
region: Region,
expr: &Expr,
expected: ExpectedTypeIndex,
) -> Constraint {
let expected = constraints.expectations[expected.index()].clone();
constrain_expr_inner(constraints, env, region, expr, expected)
}
fn constrain_expr_inner(
constraints: &mut Constraints, constraints: &mut Constraints,
env: &mut Env, env: &mut Env,
region: Region, region: Region,
@ -337,7 +350,7 @@ pub fn constrain_expr(
list_elem_type_index, list_elem_type_index,
loc_elem.region, loc_elem.region,
); );
let constraint = constrain_expr( let constraint = constrain_expr_inner(
constraints, constraints,
env, env,
loc_elem.region, loc_elem.region,
@ -381,7 +394,7 @@ pub fn constrain_expr(
}; };
let fn_con = let fn_con =
constrain_expr(constraints, env, loc_fn.region, &loc_fn.value, fn_expected); constrain_expr_inner(constraints, env, loc_fn.region, &loc_fn.value, fn_expected);
// The function's return type // The function's return type
let ret_type = Variable(*ret_var); let ret_type = Variable(*ret_var);
@ -409,7 +422,7 @@ pub fn constrain_expr(
arg_index: HumanIndex::zero_based(index), arg_index: HumanIndex::zero_based(index),
}; };
let expected_arg = ForReason(reason, arg_type_index, region); let expected_arg = ForReason(reason, arg_type_index, region);
let arg_con = constrain_expr( let arg_con = constrain_expr_inner(
constraints, constraints,
env, env,
loc_arg.region, loc_arg.region,
@ -516,7 +529,7 @@ pub fn constrain_expr(
Expected::ForReason(Reason::ExpectCondition, bool_type, loc_condition.region) Expected::ForReason(Reason::ExpectCondition, bool_type, loc_condition.region)
}; };
let cond_con = constrain_expr( let cond_con = constrain_expr_inner(
constraints, constraints,
env, env,
loc_condition.region, loc_condition.region,
@ -524,7 +537,7 @@ pub fn constrain_expr(
expected_bool, expected_bool,
); );
let continuation_con = constrain_expr( let continuation_con = constrain_expr_inner(
constraints, constraints,
env, env,
loc_continuation.region, loc_continuation.region,
@ -567,7 +580,7 @@ pub fn constrain_expr(
Expected::ForReason(Reason::ExpectCondition, bool_type, loc_condition.region) Expected::ForReason(Reason::ExpectCondition, bool_type, loc_condition.region)
}; };
let cond_con = constrain_expr( let cond_con = constrain_expr_inner(
constraints, constraints,
env, env,
loc_condition.region, loc_condition.region,
@ -575,7 +588,7 @@ pub fn constrain_expr(
expected_bool, expected_bool,
); );
let continuation_con = constrain_expr( let continuation_con = constrain_expr_inner(
constraints, constraints,
env, env,
loc_continuation.region, loc_continuation.region,
@ -640,7 +653,7 @@ pub fn constrain_expr(
let num_branches = branches.len() + 1; let num_branches = branches.len() + 1;
for (index, (loc_cond, loc_body)) in branches.iter().enumerate() { for (index, (loc_cond, loc_body)) in branches.iter().enumerate() {
let expected_bool = expect_bool(constraints, loc_cond.region); let expected_bool = expect_bool(constraints, loc_cond.region);
let cond_con = constrain_expr( let cond_con = constrain_expr_inner(
constraints, constraints,
env, env,
loc_cond.region, loc_cond.region,
@ -648,7 +661,7 @@ pub fn constrain_expr(
expected_bool, expected_bool,
); );
let then_con = constrain_expr( let then_con = constrain_expr_inner(
constraints, constraints,
env, env,
loc_body.region, loc_body.region,
@ -669,7 +682,7 @@ pub fn constrain_expr(
branch_cons.push(then_con); branch_cons.push(then_con);
} }
let else_con = constrain_expr( let else_con = constrain_expr_inner(
constraints, constraints,
env, env,
final_else.region, final_else.region,
@ -705,7 +718,7 @@ pub fn constrain_expr(
for (index, (loc_cond, loc_body)) in branches.iter().enumerate() { for (index, (loc_cond, loc_body)) in branches.iter().enumerate() {
let expected_bool = expect_bool(constraints, loc_cond.region); let expected_bool = expect_bool(constraints, loc_cond.region);
let cond_con = constrain_expr( let cond_con = constrain_expr_inner(
constraints, constraints,
env, env,
loc_cond.region, loc_cond.region,
@ -713,7 +726,7 @@ pub fn constrain_expr(
expected_bool, expected_bool,
); );
let then_con = constrain_expr( let then_con = constrain_expr_inner(
constraints, constraints,
env, env,
loc_body.region, loc_body.region,
@ -731,7 +744,7 @@ pub fn constrain_expr(
branch_cons.push(cond_con); branch_cons.push(cond_con);
branch_cons.push(then_con); branch_cons.push(then_con);
} }
let else_con = constrain_expr( let else_con = constrain_expr_inner(
constraints, constraints,
env, env,
final_else.region, final_else.region,
@ -901,7 +914,7 @@ pub fn constrain_expr(
// First, solve the condition type. // First, solve the condition type.
let real_cond_var = *real_cond_var; let real_cond_var = *real_cond_var;
let real_cond_type = constraints.push_type(Type::Variable(real_cond_var)); let real_cond_type = constraints.push_type(Type::Variable(real_cond_var));
let cond_constraint = constrain_expr( let cond_constraint = constrain_expr_inner(
constraints, constraints,
env, env,
loc_cond.region, loc_cond.region,
@ -980,7 +993,7 @@ pub fn constrain_expr(
let record_con = let record_con =
constraints.equal_types_var(*record_var, record_expected, category.clone(), region); constraints.equal_types_var(*record_var, record_expected, category.clone(), region);
let constraint = constrain_expr( let constraint = constrain_expr_inner(
constraints, constraints,
env, env,
region, region,
@ -1074,7 +1087,7 @@ pub fn constrain_expr(
) )
} }
LetRec(defs, loc_ret, cycle_mark) => { LetRec(defs, loc_ret, cycle_mark) => {
let body_con = constrain_expr( let body_con = constrain_expr_inner(
constraints, constraints,
env, env,
loc_ret.region, loc_ret.region,
@ -1096,7 +1109,7 @@ pub fn constrain_expr(
loc_ret = new_loc_ret; loc_ret = new_loc_ret;
} }
let mut body_con = constrain_expr( let mut body_con = constrain_expr_inner(
constraints, constraints,
env, env,
loc_ret.region, loc_ret.region,
@ -1124,7 +1137,7 @@ pub fn constrain_expr(
for (var, loc_expr) in arguments { for (var, loc_expr) in arguments {
let var_index = constraints.push_type(Variable(*var)); let var_index = constraints.push_type(Variable(*var));
let arg_con = constrain_expr( let arg_con = constrain_expr_inner(
constraints, constraints,
env, env,
loc_expr.region, loc_expr.region,
@ -1213,7 +1226,7 @@ pub fn constrain_expr(
}); });
// Constrain the argument // Constrain the argument
let arg_con = constrain_expr( let arg_con = constrain_expr_inner(
constraints, constraints,
env, env,
arg_loc_expr.region, arg_loc_expr.region,
@ -1386,7 +1399,8 @@ pub fn constrain_expr(
arg_index: HumanIndex::zero_based(index), arg_index: HumanIndex::zero_based(index),
}; };
let expected_arg = ForReason(reason, arg_type, Region::zero()); let expected_arg = ForReason(reason, arg_type, Region::zero());
let arg_con = constrain_expr(constraints, env, Region::zero(), arg, expected_arg); let arg_con =
constrain_expr_inner(constraints, env, Region::zero(), arg, expected_arg);
arg_types.push(arg_type); arg_types.push(arg_type);
arg_cons.push(arg_con); arg_cons.push(arg_con);
@ -1428,7 +1442,8 @@ pub fn constrain_expr(
arg_index: HumanIndex::zero_based(index), arg_index: HumanIndex::zero_based(index),
}; };
let expected_arg = ForReason(reason, arg_type, Region::zero()); let expected_arg = ForReason(reason, arg_type, Region::zero());
let arg_con = constrain_expr(constraints, env, Region::zero(), arg, expected_arg); let arg_con =
constrain_expr_inner(constraints, env, Region::zero(), arg, expected_arg);
arg_types.push(arg_type); arg_types.push(arg_type);
arg_cons.push(arg_con); arg_cons.push(arg_con);
@ -1678,14 +1693,14 @@ fn constrain_function_def(
&mut vars, &mut vars,
); );
let annotation_expected = FromAnnotation( let annotation_expected = constraints.push_expected_type(FromAnnotation(
loc_pattern.clone(), loc_pattern.clone(),
arity, arity,
AnnotationSource::TypedBody { AnnotationSource::TypedBody {
region: annotation.region, region: annotation.region,
}, },
ret_type_index, ret_type_index,
); ));
let ret_constraint = constrain_expr( let ret_constraint = constrain_expr(
constraints, constraints,
@ -1823,14 +1838,14 @@ fn constrain_destructure_def(
let signature_index = constraints.push_type(signature); let signature_index = constraints.push_type(signature);
let annotation_expected = FromAnnotation( let annotation_expected = constraints.push_expected_type(FromAnnotation(
loc_pattern.clone(), loc_pattern.clone(),
arity, arity,
AnnotationSource::TypedBody { AnnotationSource::TypedBody {
region: annotation.region, region: annotation.region,
}, },
signature_index, signature_index,
); ));
// This will fill in inference variables in the `signature` as well, so that we can // This will fill in inference variables in the `signature` as well, so that we can
// then take the signature as the source-of-truth without having to worry about // then take the signature as the source-of-truth without having to worry about
@ -1862,12 +1877,13 @@ fn constrain_destructure_def(
None => { None => {
let expr_type = constraints.push_type(Variable(expr_var)); let expr_type = constraints.push_type(Variable(expr_var));
let expected_type = constraints.push_expected_type(NoExpectation(expr_type));
let expr_con = constrain_expr( let expr_con = constrain_expr(
constraints, constraints,
env, env,
loc_expr.region, loc_expr.region,
&loc_expr.value, &loc_expr.value,
NoExpectation(expr_type), expected_type,
); );
constrain_function_def_make_constraint( constrain_function_def_make_constraint(
@ -1920,14 +1936,14 @@ fn constrain_value_def(
let signature_index = constraints.push_type(signature); let signature_index = constraints.push_type(signature);
let annotation_expected = FromAnnotation( let annotation_expected = constraints.push_expected_type(FromAnnotation(
loc_pattern, loc_pattern,
arity, arity,
AnnotationSource::TypedBody { AnnotationSource::TypedBody {
region: annotation.region, region: annotation.region,
}, },
signature_index, signature_index,
); ));
// This will fill in inference variables in the `signature` as well, so that we can // This will fill in inference variables in the `signature` as well, so that we can
// then take the signature as the source-of-truth without having to worry about // then take the signature as the source-of-truth without having to worry about
@ -1962,12 +1978,13 @@ fn constrain_value_def(
None => { None => {
let expr_type = constraints.push_type(Type::Variable(expr_var)); let expr_type = constraints.push_type(Type::Variable(expr_var));
let expected_type = constraints.push_expected_type(NoExpectation(expr_type));
let expr_con = constrain_expr( let expr_con = constrain_expr(
constraints, constraints,
env, env,
loc_expr.region, loc_expr.region,
&loc_expr.value, &loc_expr.value,
NoExpectation(expr_type), expected_type,
); );
let expr_con = attach_resolution_constraints(constraints, env, expr_con); let expr_con = attach_resolution_constraints(constraints, env, expr_con);
@ -2005,6 +2022,7 @@ fn constrain_when_branch_help(
pattern_expected: impl Fn(HumanIndex, Region) -> PExpected<TypeOrVar>, pattern_expected: impl Fn(HumanIndex, Region) -> PExpected<TypeOrVar>,
expr_expected: Expected<TypeOrVar>, expr_expected: Expected<TypeOrVar>,
) -> ConstrainedBranch { ) -> ConstrainedBranch {
let expr_expected = constraints.push_expected_type(expr_expected);
let ret_constraint = constrain_expr( let ret_constraint = constrain_expr(
constraints, constraints,
env, env,
@ -2077,7 +2095,7 @@ fn constrain_when_branch_help(
if let Some(loc_guard) = &when_branch.guard { if let Some(loc_guard) = &when_branch.guard {
let bool_index = constraints.push_type(Variable(Variable::BOOL)); let bool_index = constraints.push_type(Variable(Variable::BOOL));
let guard_constraint = constrain_expr( let guard_constraint = constrain_expr_inner(
constraints, constraints,
env, env,
region, region,
@ -2118,7 +2136,7 @@ fn constrain_field(
) -> (Type, Constraint) { ) -> (Type, Constraint) {
let field_type = constraints.push_type(Variable(field_var)); let field_type = constraints.push_type(Variable(field_var));
let field_expected = NoExpectation(field_type); let field_expected = NoExpectation(field_type);
let constraint = constrain_expr( let constraint = constrain_expr_inner(
constraints, constraints,
env, env,
loc_expr.region, loc_expr.region,
@ -2174,8 +2192,11 @@ pub fn constrain_decls(
let loc_expr = &declarations.expressions[index]; let loc_expr = &declarations.expressions[index];
let bool_type = constraints.push_type(Variable(Variable::BOOL)); let bool_type = constraints.push_type(Variable(Variable::BOOL));
let expected = let expected = constraints.push_expected_type(Expected::ForReason(
Expected::ForReason(Reason::ExpectCondition, bool_type, loc_expr.region); Reason::ExpectCondition,
bool_type,
loc_expr.region,
));
let expect_constraint = constrain_expr( let expect_constraint = constrain_expr(
constraints, constraints,
@ -2191,8 +2212,11 @@ pub fn constrain_decls(
let loc_expr = &declarations.expressions[index]; let loc_expr = &declarations.expressions[index];
let bool_type = constraints.push_type(Variable(Variable::BOOL)); let bool_type = constraints.push_type(Variable(Variable::BOOL));
let expected = let expected = constraints.push_expected_type(Expected::ForReason(
Expected::ForReason(Reason::ExpectCondition, bool_type, loc_expr.region); Reason::ExpectCondition,
bool_type,
loc_expr.region,
));
let expect_constraint = constrain_expr( let expect_constraint = constrain_expr(
constraints, constraints,
@ -2404,14 +2428,14 @@ fn constrain_typed_def(
&mut vars, &mut vars,
); );
let body_type = FromAnnotation( let body_type = constraints.push_expected_type(FromAnnotation(
def.loc_pattern.clone(), def.loc_pattern.clone(),
arguments.len(), arguments.len(),
AnnotationSource::TypedBody { AnnotationSource::TypedBody {
region: annotation.region, region: annotation.region,
}, },
ret_type_index, ret_type_index,
); ));
let ret_constraint = constrain_expr( let ret_constraint = constrain_expr(
constraints, constraints,
@ -2470,14 +2494,14 @@ fn constrain_typed_def(
} }
_ => { _ => {
let annotation_expected = FromAnnotation( let annotation_expected = constraints.push_expected_type(FromAnnotation(
def.loc_pattern.clone(), def.loc_pattern.clone(),
arity, arity,
AnnotationSource::TypedBody { AnnotationSource::TypedBody {
region: annotation.region, region: annotation.region,
}, },
expr_type_index, expr_type_index,
); ));
let ret_constraint = constrain_expr( let ret_constraint = constrain_expr(
constraints, constraints,
@ -2781,12 +2805,13 @@ fn constrain_def(
def_pattern_state.vars.push(expr_var); def_pattern_state.vars.push(expr_var);
// no annotation, so no extra work with rigids // no annotation, so no extra work with rigids
let expected = constraints.push_expected_type(NoExpectation(expr_type_index));
let expr_con = constrain_expr( let expr_con = constrain_expr(
constraints, constraints,
env, env,
def.loc_expr.region, def.loc_expr.region,
&def.loc_expr.value, &def.loc_expr.value,
NoExpectation(expr_type_index), expected,
); );
let expr_con = attach_resolution_constraints(constraints, env, expr_con); let expr_con = attach_resolution_constraints(constraints, env, expr_con);
@ -3203,12 +3228,13 @@ fn constraint_recursive_function(
)); ));
let expr_con = { let expr_con = {
let expected = constraints.push_expected_type(NoExpectation(ret_type_index));
constrain_expr( constrain_expr(
constraints, constraints,
env, env,
loc_body_expr.region, loc_body_expr.region,
&loc_body_expr.value, &loc_body_expr.value,
NoExpectation(ret_type_index), expected,
) )
}; };
let expr_con = attach_resolution_constraints(constraints, env, expr_con); let expr_con = attach_resolution_constraints(constraints, env, expr_con);
@ -3289,12 +3315,14 @@ pub fn rec_defs_help_simple(
match opt_annotation { match opt_annotation {
None => { None => {
let expected =
constraints.push_expected_type(NoExpectation(expr_var_index));
let expr_con = constrain_expr( let expr_con = constrain_expr(
constraints, constraints,
env, env,
loc_expr.region, loc_expr.region,
&loc_expr.value, &loc_expr.value,
NoExpectation(expr_var_index), expected,
); );
let expr_con = attach_resolution_constraints(constraints, env, expr_con); let expr_con = attach_resolution_constraints(constraints, env, expr_con);
@ -3339,7 +3367,7 @@ pub fn rec_defs_help_simple(
signature_index, signature_index,
); );
let expected = annotation_expected; let expected = constraints.push_expected_type(annotation_expected);
let ret_constraint = constrain_expr( let ret_constraint = constrain_expr(
constraints, constraints,
@ -3501,12 +3529,13 @@ fn rec_defs_help(
match &def.annotation { match &def.annotation {
None => { None => {
let expected = constraints.push_expected_type(NoExpectation(expr_type_index));
let expr_con = constrain_expr( let expr_con = constrain_expr(
constraints, constraints,
env, env,
def.loc_expr.region, def.loc_expr.region,
&def.loc_expr.value, &def.loc_expr.value,
NoExpectation(expr_type_index), expected,
); );
let expr_con = attach_resolution_constraints(constraints, env, expr_con); let expr_con = attach_resolution_constraints(constraints, env, expr_con);
@ -3617,7 +3646,8 @@ fn rec_defs_help(
Box::new(Type::Variable(closure_var)), Box::new(Type::Variable(closure_var)),
Box::new(*ret_type.clone()), Box::new(*ret_type.clone()),
)); ));
let body_type = NoExpectation(ret_type_index); let body_type =
constraints.push_expected_type(NoExpectation(ret_type_index));
let expr_con = constrain_expr( let expr_con = constrain_expr(
constraints, constraints,
env, env,
@ -3684,7 +3714,7 @@ fn rec_defs_help(
} }
} }
_ => { _ => {
let expected = annotation_expected; let expected = constraints.push_expected_type(annotation_expected);
let ret_constraint = constrain_expr( let ret_constraint = constrain_expr(
constraints, constraints,
@ -3816,7 +3846,7 @@ fn constrain_field_update(
let field_type = constraints.push_type(Variable(var)); let field_type = constraints.push_type(Variable(var));
let reason = Reason::RecordUpdateValue(field); let reason = Reason::RecordUpdateValue(field);
let expected = ForReason(reason, field_type, region); let expected = ForReason(reason, field_type, region);
let con = constrain_expr(constraints, env, loc_expr.region, &loc_expr.value, expected); let con = constrain_expr_inner(constraints, env, loc_expr.region, &loc_expr.value, expected);
(var, Variable(var), con) (var, Variable(var), con)
} }

View file

@ -467,11 +467,11 @@ pub fn constrain_pattern(
state.vars.push(*expr_var); state.vars.push(*expr_var);
let expr_expected = Expected::ForReason( let expr_expected = constraints.push_expected_type(Expected::ForReason(
Reason::RecordDefaultField(label.clone()), Reason::RecordDefaultField(label.clone()),
pat_type_index, pat_type_index,
loc_expr.region, loc_expr.region,
); ));
let expr_con = constrain_expr( let expr_con = constrain_expr(
constraints, constraints,

View file

@ -145,7 +145,7 @@ pub fn can_expr_with<'a>(
let mut var_store = VarStore::default(); let mut var_store = VarStore::default();
let var = var_store.fresh(); let var = var_store.fresh();
let var_index = constraints.push_type(Type::Variable(var)); let var_index = constraints.push_type(Type::Variable(var));
let expected = Expected::NoExpectation(var_index); let expected = constraints.push_expected_type(Expected::NoExpectation(var_index));
let mut module_ids = ModuleIds::default(); let mut module_ids = ModuleIds::default();
// ensure the Test module is accessible in our tests // ensure the Test module is accessible in our tests