Skip to content

Commit

Permalink
fix(check): Propagate the expected type through array expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
Marwes committed Apr 9, 2018
1 parent a4ae10f commit 9f0f657
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 10 deletions.
21 changes: 12 additions & 9 deletions check/src/typecheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -646,12 +646,10 @@ impl<'a> Typecheck<'a> {
let _ = ::rename::rename(&mut self.symbols, expr);
self.implicit_resolver.metadata = ::metadata::metadata(&self.environment, expr).1;

let temp = expected_type.and_then(|expected| self.create_unifiable_signature(expected));
let expected_type = temp.as_ref().or(expected_type);

let mut typ = self.typecheck_opt(expr, expected_type);
if let Some(expected) = expected_type {
let expected = self.create_unifiable_signature(expected)
.unwrap_or_else(|| expected.clone());
typ = self.subsumes_expr(expr_check_span(expr), 0, &expected, typ, expr);
}
// Only the 'tail' expression need to be generalized at this point as all bindings
// will have already been generalized
self.generalize_variables(0, &mut [].iter_mut(), tail_expr(expr));
Expand Down Expand Up @@ -908,12 +906,17 @@ impl<'a> Typecheck<'a> {
}
}
Expr::Array(ref mut array) => {
let mut expected_type = self.subs.new_var();
let mut expected_element_type = self.subs.new_var();

if let Some(expected_type) = expected_type.take() {
array.typ = self.type_cache.array(expected_element_type.clone());
self.unify_span(expr.span, &expected_type, array.typ.clone());
}

for expr in &mut array.exprs {
let typ = self.typecheck(expr, &expected_type);
expected_type = self.unify_span(expr.span, &expected_type, typ);
expected_element_type = self.typecheck(expr, &expected_element_type);
}
array.typ = self.type_cache.array(expected_type);

Ok(TailCall::Type(array.typ.clone()))
}
Expr::Lambda(ref mut lambda) => {
Expand Down
26 changes: 26 additions & 0 deletions check/tests/pass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,15 @@ fn expected_type_do_not_override_actual_type_for_returned_type() {
assert_req!(result, Ok(typ("Int")));
}

#[test]
fn expected_type_do_not_override_actual_type_for_returned_type_array() {
let text = "[1]";
let (_, result) = support::typecheck_expr_expected(text, Some(&Type::hole()));

assert_req!(result.map(|t| t.to_string()), Ok("Array Int"));
}


#[test]
fn dont_guess_record_type() {
let _ = env_logger::try_init();
Expand All @@ -835,3 +844,20 @@ let x : Test = { a = 0, b = "" }

assert!(result.is_ok(), "{}", result.unwrap_err());
}

#[test]
fn generalize_function_in_record_and_array() {
let _ = env_logger::try_init();

let text = r#"
let string x : String -> String = x
let a: Array { f : String -> String } = [
{ f = \x -> x },
{ f = \x -> string x },
]
a
"#;
let result = support::typecheck(text);

assert_req!(result.map(|t| t.to_string()), Ok("Array { f : String -> String }"));
}
2 changes: 1 addition & 1 deletion repl/src/repl.glu
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ let make_commands cpu_pool : CpuPool -> Commands =
| Err x -> io.println x

let commands = ref []
let cmds = [{
let cmds : Array Cmd = [{
name = "quit",
alias = "q",
info = "Quit the REPL",
Expand Down

0 comments on commit 9f0f657

Please sign in to comment.