Catch functions typed with too few arguments

Closes #5264
This commit is contained in:
Ayaz Hafiz 2023-04-12 15:20:54 -05:00
parent 8c32900e19
commit b46392311e
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
2 changed files with 85 additions and 41 deletions

View file

@ -1782,7 +1782,7 @@ fn constrain_function_def(
let signature_index = constraints.push_type(types, signature);
let (arg_types, signature_closure_type, ret_type) = match types[signature] {
let (arg_types, _signature_closure_type, ret_type) = match types[signature] {
TypeTag::Function(signature_closure_type, ret_type) => (
types.get_type_arguments(signature),
signature_closure_type,
@ -1888,13 +1888,12 @@ fn constrain_function_def(
delayed_is_open_constraints: vec![],
};
let mut vars = Vec::with_capacity(argument_pattern_state.vars.capacity() + 1);
let ret_var = function_def.return_type;
let closure_var = function_def.closure_type;
let ret_type_index = constraints.push_type(types, ret_type);
vars.push(ret_var);
vars.push(closure_var);
vars.push(function_def.return_type);
vars.push(function_def.closure_type);
let mut def_pattern_state = PatternState::default();
@ -1913,21 +1912,22 @@ fn constrain_function_def(
// TODO see if we can get away with not adding this constraint at all
def_pattern_state.vars.push(expr_var);
let annotation_expected = FromAnnotation(
loc_pattern.clone(),
arity,
AnnotationSource::TypedBody {
region: annotation.region,
},
signature_index,
);
let annotation_expected = {
constraints.push_expected_type(FromAnnotation(
loc_pattern.clone(),
arity,
AnnotationSource::TypedBody {
region: annotation.region,
},
signature_index,
))
};
{
let expr_type_index = constraints.push_variable(expr_var);
let expected_index = constraints.push_expected_type(annotation_expected);
def_pattern_state.constraints.push(constraints.equal_types(
expr_type_index,
expected_index,
annotation_expected,
Category::Storage(std::file!(), std::line!()),
Region::span_across(&annotation.region, &loc_body_expr.region),
));
@ -1955,7 +1955,7 @@ fn constrain_function_def(
&mut vars,
);
let annotation_expected = constraints.push_expected_type(FromAnnotation(
let return_type_annotation_expected = constraints.push_expected_type(FromAnnotation(
loc_pattern.clone(),
arity,
AnnotationSource::TypedBody {
@ -1964,31 +1964,34 @@ fn constrain_function_def(
ret_type_index,
));
let ret_constraint = constrain_expr(
types,
constraints,
env,
loc_body_expr.region,
&loc_body_expr.value,
annotation_expected,
);
let ret_constraint = attach_resolution_constraints(constraints, env, ret_constraint);
let solved_fn_type = {
// TODO(types-soa) optimize for Variable
let pattern_types = types.from_old_type_slice(
function_def.arguments.iter().map(|a| Type::Variable(a.0)),
);
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 fn_type = types.function(pattern_types, lambda_set, ret_var);
constraints.push_type(types, fn_type)
};
let ret_constraint = {
let con = constrain_expr(
types,
constraints,
env,
loc_body_expr.region,
&loc_body_expr.value,
return_type_annotation_expected,
);
attach_resolution_constraints(constraints, env, con)
};
vars.push(expr_var);
let defs_constraint = constraints.and_constraint(argument_pattern_state.constraints);
let signature_closure_type = {
let signature_closure_type_index =
constraints.push_type(types, signature_closure_type);
constraints.push_expected_type(Expected::FromAnnotation(
loc_pattern,
arity,
AnnotationSource::TypedBody {
region: annotation.region,
},
signature_closure_type_index,
))
};
let cons = [
constraints.let_constraint(
[],
@ -1999,14 +2002,24 @@ fn constrain_function_def(
// This is a syntactic function, it can be generalized
Generalizable(true),
),
constraints.equal_types_var(
closure_var,
signature_closure_type,
Category::ClosureSize,
// Store the inferred ret var into the function type now, so that
// when we check that the solved function type matches the annotation, we can
// display the fully inferred return variable.
constraints.store(
ret_type_index,
function_def.return_type,
std::file!(),
std::line!(),
),
// Now, check the solved function type matches the annotation.
constraints.equal_types(
solved_fn_type,
annotation_expected,
Category::Lambda,
region,
),
// Finally put the solved closure type into the dedicated def expr variable.
constraints.store(signature_index, expr_var, std::file!(), std::line!()),
constraints.store(ret_type_index, ret_var, std::file!(), std::line!()),
closure_constraint,
];