typecheck functions with alias (or weird) type annotations

This commit is contained in:
Folkert 2022-06-25 21:43:01 +02:00
parent 03aef94e44
commit c636cd6d2b
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
2 changed files with 109 additions and 11 deletions

View file

@ -1221,6 +1221,9 @@ fn constrain_function_def(
match opt_annotation {
Some(annotation) => {
let loc_pattern = Loc::at(loc_symbol.region, Pattern::Identifier(loc_symbol.value));
let loc_body_expr = loc_expr;
let arity = annotation.signature.arity();
let rigids = &env.rigids;
let mut ftv = rigids.clone();
@ -1235,20 +1238,101 @@ fn constrain_function_def(
&mut ftv,
);
let (arg_types, signature_closure_type, ret_type) = match &signature {
Type::Function(arg_types, signature_closure_type, ret_type) => {
(arg_types, signature_closure_type, ret_type)
}
_ => {
// aliases, or just something weird
let def_pattern_state = {
let mut def_pattern_state = PatternState::default();
def_pattern_state.headers.insert(
loc_symbol.value,
Loc {
region: loc_function_def.region,
// todo can we use Type::Variable(expr_var) here?
value: signature.clone(),
},
);
// 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.clone(),
);
def_pattern_state.constraints.push(constraints.equal_types(
Type::Variable(expr_var),
annotation_expected,
Category::Storage(std::file!(), std::line!()),
Region::span_across(&annotation.region, &loc_body_expr.region),
));
def_pattern_state
};
let annotation_expected = FromAnnotation(
loc_pattern,
arity,
AnnotationSource::TypedBody {
region: annotation.region,
},
signature.clone(),
);
let ret_constraint = constrain_untyped_closure(
constraints,
env,
loc_function_def.region,
annotation_expected,
expr_var,
function_def.closure_type,
function_def.return_type,
&function_def.arguments,
loc_body_expr,
&function_def.captured_symbols,
loc_symbol.value,
);
let ret_constraint =
attach_resolution_constraints(constraints, env, ret_constraint);
let cons = [
ret_constraint,
// Store type into AST vars. We use Store so errors aren't reported twice
constraints.store(signature, expr_var, std::file!(), std::line!()),
];
let expr_con = constraints.and_constraint(cons);
return constrain_function_def_make_constraint(
constraints,
new_rigid_variables,
new_infer_variables,
expr_con,
body_con,
def_pattern_state,
);
}
};
let env = &mut Env {
home: env.home,
rigids: ftv,
resolutions_to_make: vec![],
};
let loc_pattern = Loc::at(loc_symbol.region, Pattern::Identifier(loc_symbol.value));
// TODO missing equality of annotation_expected with expr_var?
// but the signature is stored into the expr_var below?!
let region = loc_function_def.region;
let loc_body_expr = loc_expr;
let mut argument_pattern_state = PatternState {
headers: VecMap::default(),
vars: Vec::with_capacity(function_def.arguments.len()),
@ -1259,14 +1343,6 @@ fn constrain_function_def(
let ret_var = function_def.return_type;
let closure_var = function_def.closure_type;
let (arg_types, signature_closure_type, ret_type) = match &signature {
Type::Function(arg_types, signature_closure_type, ret_type) => {
(arg_types, signature_closure_type, ret_type)
}
_ => todo!("TODO {:?}", (loc_symbol, &signature)),
};
// Type::Function(arg_types, signature_closure_type, ret_type),
let ret_type = *ret_type.clone();
vars.push(ret_var);

View file

@ -6901,4 +6901,26 @@ mod solve_expr {
print_only_under_alias = true
)
}
#[test]
fn function_alias_in_signature() {
infer_eq_without_problem(
indoc!(
r#"
app "test" provides [main] to "./platform"
Parser a : List U8 -> List [Pair a (List U8)]
any: Parser U8
any = \inp ->
when List.first inp is
Ok u -> [Pair u (List.drop inp 1)]
_ -> []
main = any
"#
),
"Parser U8",
);
}
}