mirror of
https://github.com/roc-lang/roc.git
synced 2024-11-10 10:02:38 +03:00
more rigid fixes?
This commit is contained in:
parent
f438cefd68
commit
7a719172bc
@ -1376,23 +1376,7 @@ pub fn rec_defs_help(
|
||||
let expr_var = def.expr_var;
|
||||
let expr_type = Type::Variable(expr_var);
|
||||
|
||||
let pattern_expected = PExpected::NoExpectation(expr_type.clone());
|
||||
|
||||
let mut pattern_state = PatternState {
|
||||
headers: SendMap::default(),
|
||||
vars: flex_info.vars.clone(),
|
||||
constraints: Vec::with_capacity(1),
|
||||
};
|
||||
|
||||
constrain_pattern(
|
||||
env,
|
||||
&def.loc_pattern.value,
|
||||
def.loc_pattern.region,
|
||||
pattern_expected,
|
||||
&mut pattern_state,
|
||||
);
|
||||
|
||||
pattern_state.vars.push(expr_var);
|
||||
let mut def_pattern_state = constrain_def_pattern(env, &def.loc_pattern, expr_type.clone());
|
||||
|
||||
let mut new_rigids = Vec::new();
|
||||
match &def.annotation {
|
||||
@ -1404,6 +1388,8 @@ pub fn rec_defs_help(
|
||||
NoExpectation(expr_type),
|
||||
);
|
||||
|
||||
def_pattern_state.vars.push(expr_var);
|
||||
|
||||
// TODO investigate if this let can be safely removed
|
||||
let def_con = Let(Box::new(LetConstraint {
|
||||
rigid_vars: Vec::new(),
|
||||
@ -1413,9 +1399,9 @@ pub fn rec_defs_help(
|
||||
ret_constraint: expr_con,
|
||||
}));
|
||||
|
||||
flex_info.vars = pattern_state.vars;
|
||||
flex_info.vars = def_pattern_state.vars;
|
||||
flex_info.constraints.push(def_con);
|
||||
flex_info.def_types.extend(pattern_state.headers);
|
||||
flex_info.def_types.extend(def_pattern_state.headers);
|
||||
}
|
||||
|
||||
Some(annotation) => {
|
||||
@ -1428,7 +1414,7 @@ pub fn rec_defs_help(
|
||||
&mut new_rigids,
|
||||
&mut ftv,
|
||||
&def.loc_pattern,
|
||||
&mut pattern_state.headers,
|
||||
&mut def_pattern_state.headers,
|
||||
);
|
||||
|
||||
let annotation_expected = FromAnnotation(
|
||||
@ -1440,43 +1426,176 @@ pub fn rec_defs_help(
|
||||
signature.clone(),
|
||||
);
|
||||
|
||||
let expr_con = constrain_expr(
|
||||
&Env {
|
||||
rigids: ftv,
|
||||
home: env.home,
|
||||
},
|
||||
def.loc_expr.region,
|
||||
&def.loc_expr.value,
|
||||
annotation_expected.clone(),
|
||||
);
|
||||
// when a def is annotated, and it's body is a closure, treat this
|
||||
// as a named function (in elm terms) for error messages.
|
||||
//
|
||||
// This means we get errors like "the first argument of `f` is weird"
|
||||
// instead of the more generic "something is wrong with the body of `f`"
|
||||
match (&def.loc_expr.value, &signature) {
|
||||
(
|
||||
Closure {
|
||||
function_type: fn_var,
|
||||
closure_type: closure_var,
|
||||
closure_ext_var,
|
||||
return_type: ret_var,
|
||||
captured_symbols,
|
||||
arguments,
|
||||
loc_body,
|
||||
name,
|
||||
..
|
||||
},
|
||||
Type::Function(arg_types, _, _),
|
||||
) => {
|
||||
let expected = annotation_expected;
|
||||
let region = def.loc_expr.region;
|
||||
|
||||
// ensure expected type unifies with annotated type
|
||||
let storage_con = Eq(
|
||||
expr_type,
|
||||
annotation_expected.clone(),
|
||||
Category::Storage(std::file!(), std::line!()),
|
||||
def.loc_expr.region,
|
||||
);
|
||||
let loc_body_expr = &**loc_body;
|
||||
let mut state = PatternState {
|
||||
headers: SendMap::default(),
|
||||
vars: Vec::with_capacity(arguments.len()),
|
||||
constraints: Vec::with_capacity(1),
|
||||
};
|
||||
let mut vars = Vec::with_capacity(state.vars.capacity() + 1);
|
||||
let mut pattern_types = Vec::with_capacity(state.vars.capacity());
|
||||
let ret_var = *ret_var;
|
||||
let closure_var = *closure_var;
|
||||
let closure_ext_var = *closure_ext_var;
|
||||
let ret_type = Type::Variable(ret_var);
|
||||
|
||||
// TODO investigate if this let can be safely removed
|
||||
let def_con = Let(Box::new(LetConstraint {
|
||||
rigid_vars: Vec::new(),
|
||||
flex_vars: Vec::new(), // empty because Roc function defs have no args
|
||||
def_types: SendMap::default(), // empty because Roc function defs have no args
|
||||
defs_constraint: storage_con,
|
||||
ret_constraint: expr_con,
|
||||
}));
|
||||
vars.push(ret_var);
|
||||
vars.push(closure_var);
|
||||
vars.push(closure_ext_var);
|
||||
|
||||
rigid_info.vars.extend(&new_rigids);
|
||||
let it = arguments.iter().zip(arg_types.iter()).enumerate();
|
||||
for (index, ((pattern_var, loc_pattern), loc_ann)) in it {
|
||||
{
|
||||
// ensure type matches the one in the annotation
|
||||
let opt_label =
|
||||
if let Pattern::Identifier(label) = def.loc_pattern.value {
|
||||
Some(label)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let pattern_type: &Type = loc_ann;
|
||||
|
||||
rigid_info.constraints.push(Let(Box::new(LetConstraint {
|
||||
rigid_vars: new_rigids,
|
||||
flex_vars: pattern_state.vars,
|
||||
def_types: SendMap::default(), // no headers introduced (at this level)
|
||||
defs_constraint: def_con,
|
||||
ret_constraint: True,
|
||||
})));
|
||||
rigid_info.def_types.extend(pattern_state.headers);
|
||||
let pattern_expected = PExpected::ForReason(
|
||||
PReason::TypedArg {
|
||||
index: Index::zero_based(index),
|
||||
opt_name: opt_label,
|
||||
},
|
||||
pattern_type.clone(),
|
||||
loc_pattern.region,
|
||||
);
|
||||
|
||||
constrain_pattern(
|
||||
env,
|
||||
&loc_pattern.value,
|
||||
loc_pattern.region,
|
||||
pattern_expected,
|
||||
&mut state,
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
// NOTE: because we perform an equality with part of the signature
|
||||
// this constraint must be to the def_pattern_state's constraints
|
||||
def_pattern_state.vars.push(*pattern_var);
|
||||
pattern_types.push(Type::Variable(*pattern_var));
|
||||
|
||||
let pattern_con = Eq(
|
||||
Type::Variable(*pattern_var),
|
||||
Expected::NoExpectation(loc_ann.clone()),
|
||||
Category::Storage(std::file!(), std::line!()),
|
||||
loc_pattern.region,
|
||||
);
|
||||
|
||||
def_pattern_state.constraints.push(pattern_con);
|
||||
}
|
||||
}
|
||||
|
||||
let closure_constraint = constrain_closure_size(
|
||||
*name,
|
||||
region,
|
||||
captured_symbols,
|
||||
closure_var,
|
||||
closure_ext_var,
|
||||
&mut vars,
|
||||
);
|
||||
|
||||
let fn_type = Type::Function(
|
||||
pattern_types,
|
||||
Box::new(Type::Variable(closure_var)),
|
||||
Box::new(ret_type.clone()),
|
||||
);
|
||||
let body_type = NoExpectation(ret_type);
|
||||
let expr_con = constrain_expr(
|
||||
env,
|
||||
loc_body_expr.region,
|
||||
&loc_body_expr.value,
|
||||
body_type,
|
||||
);
|
||||
|
||||
vars.push(*fn_var);
|
||||
|
||||
// let expr_con = constrain_expr(
|
||||
// &Env {
|
||||
// rigids: ftv,
|
||||
// home: env.home,
|
||||
// },
|
||||
// def.loc_expr.region,
|
||||
// &def.loc_expr.value,
|
||||
// annotation_expected.clone(),
|
||||
// );
|
||||
//
|
||||
// // ensure expected type unifies with annotated type
|
||||
// let storage_con = Eq(
|
||||
// expr_type,
|
||||
// annotation_expected.clone(),
|
||||
// Category::Storage(std::file!(), std::line!()),
|
||||
// def.loc_expr.region,
|
||||
// );
|
||||
//
|
||||
// def_pattern_state.vars.push(expr_var);
|
||||
// // Open question: where should this constraint live?
|
||||
// // rigid_info.vars.push(expr_var);
|
||||
// rigid_info.constraints.push(storage_con);
|
||||
|
||||
// TODO investigate if this let can be safely removed
|
||||
let def_con = exists(
|
||||
vars,
|
||||
And(vec![
|
||||
Let(Box::new(LetConstraint {
|
||||
rigid_vars: Vec::new(),
|
||||
flex_vars: state.vars,
|
||||
def_types: state.headers,
|
||||
defs_constraint: And(state.constraints),
|
||||
ret_constraint: expr_con,
|
||||
})),
|
||||
Eq(fn_type.clone(), expected, Category::Lambda, region),
|
||||
// "fn_var is equal to the closure's type" - fn_var is used in code gen
|
||||
Eq(
|
||||
Type::Variable(*fn_var),
|
||||
NoExpectation(fn_type),
|
||||
Category::Storage(std::file!(), std::line!()),
|
||||
region,
|
||||
),
|
||||
closure_constraint,
|
||||
]),
|
||||
);
|
||||
|
||||
rigid_info.vars.extend(&new_rigids);
|
||||
|
||||
rigid_info.constraints.push(Let(Box::new(LetConstraint {
|
||||
rigid_vars: new_rigids,
|
||||
flex_vars: def_pattern_state.vars,
|
||||
def_types: SendMap::default(), // no headers introduced (at this level)
|
||||
defs_constraint: def_con,
|
||||
ret_constraint: True,
|
||||
})));
|
||||
rigid_info.def_types.extend(def_pattern_state.headers);
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user