Add fx var to Type::Function et al

This commit is contained in:
Agus Zubiaga 2024-10-05 20:12:29 -03:00
parent 75177c9c98
commit 3cef756559
No known key found for this signature in database
7 changed files with 133 additions and 51 deletions

View file

@ -67,6 +67,7 @@ fn constrain_untyped_args(
arguments: &[(Variable, AnnotatedMark, Loc<Pattern>)],
closure_type: Type,
return_type: Type,
fx_type: Type,
) -> (Vec<Variable>, PatternState, Type) {
let mut vars = Vec::with_capacity(arguments.len());
let mut pattern_types = Vec::with_capacity(arguments.len());
@ -97,8 +98,12 @@ fn constrain_untyped_args(
vars.push(*pattern_var);
}
let function_type =
Type::Function(pattern_types, Box::new(closure_type), Box::new(return_type));
let function_type = Type::Function(
pattern_types,
Box::new(closure_type),
Box::new(return_type),
Box::new(fx_type),
);
(vars, pattern_state, function_type)
}
@ -109,10 +114,10 @@ fn constrain_untyped_closure(
env: &mut Env,
region: Region,
expected: ExpectedTypeIndex,
fn_var: Variable,
closure_var: Variable,
ret_var: Variable,
fx_var: Variable,
early_returns: &[(Variable, Region)],
arguments: &[(Variable, AnnotatedMark, Loc<Pattern>)],
loc_body_expr: &Loc<Expr>,
@ -122,6 +127,7 @@ fn constrain_untyped_closure(
let closure_type = Type::Variable(closure_var);
let return_type = Type::Variable(ret_var);
let return_type_index = constraints.push_variable(ret_var);
let fx_type = Type::Variable(fx_var);
let (mut vars, pattern_state, function_type) = constrain_untyped_args(
types,
constraints,
@ -129,9 +135,11 @@ fn constrain_untyped_closure(
arguments,
closure_type,
return_type,
fx_type,
);
vars.push(ret_var);
vars.push(fx_var);
vars.push(closure_var);
vars.push(fn_var);
@ -141,6 +149,7 @@ fn constrain_untyped_closure(
loc_body_expr.region,
));
// [purity-inference] TODO: constrain calls in body with fx_var
let ret_constraint = constrain_expr(
types,
constraints,
@ -546,7 +555,9 @@ pub fn constrain_expr(
let arguments = types.from_old_type_slice(arg_types.iter());
let lambda_set = types.from_old_type(&closure_type);
let ret = types.from_old_type(&ret_type);
let typ = types.function(arguments, lambda_set, ret);
// [purity-inference] TODO: Add fx var to call
let fx = types.from_old_type(&Type::Variable(Variable::PURE));
let typ = types.function(arguments, lambda_set, ret, fx);
constraints.push_type(types, typ)
};
let expected_fn_type =
@ -646,6 +657,7 @@ pub fn constrain_expr(
function_type: fn_var,
closure_type: closure_var,
return_type: ret_var,
fx_type: fx_var,
early_returns,
arguments,
loc_body: boxed,
@ -663,6 +675,7 @@ pub fn constrain_expr(
*fn_var,
*closure_var,
*ret_var,
*fx_var,
early_returns,
arguments,
boxed,
@ -1288,6 +1301,7 @@ pub fn constrain_expr(
vec![record_type],
Box::new(closure_type),
Box::new(field_type),
Box::new(Type::Variable(Variable::PURE)),
));
constraints.push_type(types, typ)
};
@ -1668,6 +1682,7 @@ pub fn constrain_expr(
vec![argument_type],
Box::new(closure_type),
Box::new(opaque_type),
Box::new(Type::Variable(Variable::PURE)),
));
constraints.push_type(types, typ)
};
@ -1853,11 +1868,12 @@ fn constrain_function_def(
let signature_index = constraints.push_type(types, signature);
let (arg_types, _signature_closure_type, ret_type) = match types[signature] {
TypeTag::Function(signature_closure_type, ret_type) => (
let (arg_types, _signature_closure_type, ret_type, fx_type) = match types[signature] {
TypeTag::Function(signature_closure_type, ret_type, fx_type) => (
types.get_type_arguments(signature),
signature_closure_type,
ret_type,
fx_type,
),
_ => {
// aliases, or just something weird
@ -1917,6 +1933,7 @@ fn constrain_function_def(
expr_var,
function_def.closure_type,
function_def.return_type,
function_def.fx_type,
&function_def.early_returns,
&function_def.arguments,
loc_body_expr,
@ -1963,9 +1980,11 @@ fn constrain_function_def(
let closure_var = function_def.closure_type;
let ret_type_index = constraints.push_type(types, ret_type);
let fx_type_index = constraints.push_type(types, fx_type);
vars.push(function_def.return_type);
vars.push(function_def.closure_type);
vars.push(function_def.fx_type);
let mut def_pattern_state = PatternState::default();
@ -2043,8 +2062,9 @@ fn constrain_function_def(
);
let lambda_set = types.from_old_type(&Type::Variable(function_def.closure_type));
let ret_var = types.from_old_type(&Type::Variable(function_def.return_type));
let fx_var = types.from_old_type(&Type::Variable(function_def.fx_type));
let fn_type = types.function(pattern_types, lambda_set, ret_var);
let fn_type = types.function(pattern_types, lambda_set, ret_var, fx_var);
constraints.push_type(types, fn_type)
};
@ -2083,6 +2103,12 @@ fn constrain_function_def(
std::file!(),
std::line!(),
),
constraints.store(
fx_type_index,
function_def.fx_type,
std::file!(),
std::line!(),
),
// Now, check the solved function type matches the annotation.
constraints.equal_types(
solved_fn_type,
@ -2119,6 +2145,7 @@ fn constrain_function_def(
expr_var,
function_def.closure_type,
function_def.return_type,
function_def.fx_type,
&function_def.early_returns,
&function_def.arguments,
loc_expr,
@ -2841,13 +2868,14 @@ fn constrain_typed_def(
function_type: fn_var,
closure_type: closure_var,
return_type: ret_var,
fx_type: fx_var,
captured_symbols,
arguments,
loc_body,
name,
..
}),
TypeTag::Function(_signature_closure_type, ret_type),
TypeTag::Function(_signature_closure_type, ret_type, fx_type),
) => {
let arg_types = types.get_type_arguments(signature);
@ -2866,10 +2894,13 @@ fn constrain_typed_def(
let mut vars = Vec::with_capacity(argument_pattern_state.vars.capacity() + 1);
let ret_var = *ret_var;
let closure_var = *closure_var;
let fx_var = *fx_var;
let ret_type_index = constraints.push_type(types, ret_type);
let fx_type_index = constraints.push_type(types, fx_type);
vars.push(ret_var);
vars.push(closure_var);
vars.push(fx_var);
constrain_typed_function_arguments(
types,
@ -2899,8 +2930,9 @@ fn constrain_typed_def(
types.from_old_type_slice(arguments.iter().map(|a| Type::Variable(a.0)));
let lambda_set = types.from_old_type(&Type::Variable(closure_var));
let ret_var = types.from_old_type(&Type::Variable(ret_var));
let fx_var = types.from_old_type(&Type::Variable(fx_var));
let fn_type = types.function(arg_types, lambda_set, ret_var);
let fn_type = types.function(arg_types, lambda_set, ret_var, fx_var);
constraints.push_type(types, fn_type)
};
@ -2940,6 +2972,7 @@ fn constrain_typed_def(
// when we check that the solved function type matches the annotation, we can
// display the fully inferred return variable.
constraints.store(ret_type_index, ret_var, std::file!(), std::line!()),
constraints.store(fx_type_index, fx_var, std::file!(), std::line!()),
// Now, check the solved function type matches the annotation.
constraints.equal_types(
solved_fn_type,
@ -3700,6 +3733,7 @@ fn constraint_recursive_function(
expr_var,
function_def.closure_type,
function_def.return_type,
function_def.fx_type,
&function_def.early_returns,
&function_def.arguments,
loc_expr,
@ -3747,11 +3781,12 @@ fn constraint_recursive_function(
signature_index,
));
let (arg_types, _signature_closure_type, ret_type) = match types[signature] {
TypeTag::Function(signature_closure_type, ret_type) => (
let (arg_types, _signature_closure_type, ret_type, fx_type) = match types[signature] {
TypeTag::Function(signature_closure_type, ret_type, fx_type) => (
types.get_type_arguments(signature),
signature_closure_type,
ret_type,
fx_type,
),
_ => todo!("TODO {:?}", (loc_symbol, types[signature])),
};
@ -3767,11 +3802,14 @@ fn constraint_recursive_function(
};
let mut vars = Vec::with_capacity(argument_pattern_state.vars.capacity() + 1);
let ret_var = function_def.return_type;
let fx_var = function_def.fx_type;
let closure_var = function_def.closure_type;
let ret_type_index = constraints.push_type(types, ret_type);
let fx_type_index = constraints.push_type(types, fx_type);
vars.push(ret_var);
vars.push(closure_var);
vars.push(fx_var);
let mut def_pattern_state = PatternState::default();
@ -3819,11 +3857,12 @@ fn constraint_recursive_function(
let fn_type = {
// TODO(types-soa) optimize for Variable
let lambda_set = types.from_old_type(&Type::Variable(closure_var));
let typ = types.function(pattern_types, lambda_set, ret_type);
let typ = types.function(pattern_types, lambda_set, ret_type, fx_type);
constraints.push_type(types, typ)
};
let expr_con = {
// [purity-inference] TODO: constrain calls in body
let expected = constraints.push_expected_type(NoExpectation(ret_type_index));
constrain_expr(
types,
@ -3854,6 +3893,7 @@ fn constraint_recursive_function(
// Store type into AST vars. We use Store so errors aren't reported twice
constraints.store(signature_index, expr_var, std::file!(), std::line!()),
constraints.store(ret_type_index, ret_var, std::file!(), std::line!()),
constraints.store(fx_type_index, fx_var, std::file!(), std::line!()),
closure_constraint,
];
@ -4305,13 +4345,14 @@ fn rec_defs_help(
function_type: fn_var,
closure_type: closure_var,
return_type: ret_var,
fx_type: fx_var,
captured_symbols,
arguments,
loc_body,
name,
..
}),
TypeTag::Function(_closure_type, ret_type),
TypeTag::Function(_closure_type, ret_type, fx_type),
) => {
// NOTE if we ever have trouble with closure type unification, the ignored
// `_closure_type` here is a good place to start investigating
@ -4331,11 +4372,14 @@ fn rec_defs_help(
let mut vars =
Vec::with_capacity(argument_pattern_state.vars.capacity() + 1);
let ret_var = *ret_var;
let fx_var = *fx_var;
let closure_var = *closure_var;
let ret_type_index = constraints.push_type(types, ret_type);
let fx_type_index = constraints.push_type(types, fx_type);
vars.push(ret_var);
vars.push(closure_var);
vars.push(fx_var);
constrain_typed_function_arguments(
types,
@ -4364,12 +4408,13 @@ fn rec_defs_help(
let fn_type_index = {
// TODO(types-soa) optimize for variable
let lambda_set = types.from_old_type(&Type::Variable(closure_var));
let typ = types.function(pattern_types, lambda_set, ret_type);
let typ = types.function(pattern_types, lambda_set, ret_type, fx_type);
constraints.push_type(types, typ)
};
let expr_con = {
let body_type =
constraints.push_expected_type(NoExpectation(ret_type_index));
// [purity-inference] TODO: unify calls in body with the fx_type
constrain_expr(
types,
@ -4412,6 +4457,7 @@ fn rec_defs_help(
std::line!(),
),
constraints.store(ret_type_index, ret_var, std::file!(), std::line!()),
constraints.store(fx_type_index, fx_var, std::file!(), std::line!()),
closure_constraint,
];