Skip to content

Commit

Permalink
fix(check): Don't return non-skolemized types from lambda
Browse files Browse the repository at this point in the history
  • Loading branch information
Marwes committed Aug 22, 2018
1 parent dd14c0e commit b0f283f
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 36 deletions.
46 changes: 16 additions & 30 deletions check/src/typecheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,7 @@ impl<I: fmt::Display + AsRef<str> + Clone> fmt::Display for TypeError<I> {
.filter_map(|err| match *err {
UnifyError::Other(ref err) => Some(err.make_filter()),
_ => None,
})
.collect::<Vec<_>>();
}).collect::<Vec<_>>();
let filter = move |field: &I| {
if filters.is_empty() {
Filter::Retain
Expand Down Expand Up @@ -272,8 +271,7 @@ impl<'a> KindEnv for Environment<'a> {
kind = Kind::function(arg.kind.clone(), kind);
}
kind
})
.or_else(|| self.environment.find_kind(type_name))
}).or_else(|| self.environment.find_kind(type_name))
}
}

Expand Down Expand Up @@ -614,8 +612,7 @@ impl<'a> Typecheck<'a> {
let mut typ = typ.clone();
self.generalize_type(0, &mut typ);
typ
})
.collect();
}).collect();
}
Unification(ref mut expected, ref mut actual, ref mut errors) => {
self.generalize_type_without_forall(0, expected);
Expand Down Expand Up @@ -857,8 +854,7 @@ impl<'a> Typecheck<'a> {
name: self.symbols.symbol(format!("_{}", i)),
typ: typ,
}
})
.collect();
}).collect();
Type::record(vec![], fields)
}
};
Expand Down Expand Up @@ -959,6 +955,7 @@ impl<'a> Typecheck<'a> {
);

self.generalize_type(level, &mut typ);
typ = self.new_skolem_scope(&typ);
lambda.id.typ = typ.clone();
Ok(TailCall::Type(typ))
}
Expand Down Expand Up @@ -1006,8 +1003,7 @@ impl<'a> Typecheck<'a> {
expected_type
.row_iter()
.find(|expected_field| expected_field.name.name_eq(&name))
})
.map(|field| &field.typ);
}).map(|field| &field.typ);

let mut typ = match field.value {
Some(ref mut expr) => self.typecheck_opt(expr, expected_field_type),
Expand Down Expand Up @@ -1279,8 +1275,7 @@ impl<'a> Typecheck<'a> {
.map(|arg| {
span_end = arg.span.end();
self.infer_expr(arg.borrow_mut())
})
.collect::<Vec<_>>();
}).collect::<Vec<_>>();
let actual = self.type_cache.function(arg_types, self.subs.new_var());

let span = Span::new(span_start, span_end);
Expand Down Expand Up @@ -1484,8 +1479,7 @@ impl<'a> Typecheck<'a> {
associated_types
.iter()
.any(|other| other.name.value.name_eq(&field.name))
})
.cloned()
}).cloned()
.collect();

let fields = fields
Expand Down Expand Up @@ -1650,15 +1644,13 @@ impl<'a> Typecheck<'a> {
self.translate_ast_type(type_cache, typ)
}))
},
})
.collect(),
}).collect(),
fields
.iter()
.map(|field| Field {
name: field.name.clone(),
typ: self.translate_ast_type(type_cache, &field.typ),
})
.collect(),
}).collect(),
self.translate_ast_type(type_cache, rest),
),
Type::Ident(ref id) if id.name().module().as_str() != "" => {
Expand Down Expand Up @@ -2134,8 +2126,7 @@ impl<'a> Typecheck<'a> {
.map(|(id, var)| {
let kind = var.kind().into_owned();
Generic::new(id, kind)
})
.collect::<Vec<_>>();
}).collect::<Vec<_>>();

if params.is_empty() {
result_type
Expand Down Expand Up @@ -2186,8 +2177,7 @@ impl<'a> Typecheck<'a> {
.map(|(new, old)| match new {
Some(new) => Field::new(new.clone(), old.typ.clone()),
None => old.clone(),
})
.collect(),
}).collect(),
),
)
} else {
Expand Down Expand Up @@ -2472,15 +2462,13 @@ pub fn translate_projected_type(
} else {
None
}
})
.chain(aliased_type.row_iter().filter_map(|field| {
}).chain(aliased_type.row_iter().filter_map(|field| {
if field.name.name_eq(&symbol) {
Some(field.typ.clone())
} else {
None
}
}))
.next()
})).next()
.ok_or_else(|| TypeError::UndefinedField(typ, symbol))?,
)
}
Expand All @@ -2490,8 +2478,7 @@ pub fn translate_projected_type(
.or_else(|| {
env.find_type_info(&symbol)
.map(|alias| alias.typ().into_owned())
})
.ok_or_else(|| TypeError::UndefinedVariable(symbol.clone()))?,
}).ok_or_else(|| TypeError::UndefinedVariable(symbol.clone()))?,
),
};
}
Expand Down Expand Up @@ -2528,8 +2515,7 @@ pub fn extract_generics(args: &[ArcType]) -> Vec<Generic<Symbol>> {
.map(|arg| match **arg {
Type::Generic(ref gen) => gen.clone(),
_ => ice!("The type on the lhs of a type binding did not have all generic arguments"),
})
.collect()
}).collect()
}

fn get_alias_app<'a>(
Expand Down
12 changes: 6 additions & 6 deletions check/src/unify_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,12 +155,10 @@ where
.iter()
.map(|missing_field| {
::strsim::jaro_winkler(missing_field.as_ref(), field_in_type.as_ref())
})
.max_by(|l, r| l.partial_cmp(&r).unwrap())
}).max_by(|l, r| l.partial_cmp(&r).unwrap())
.expect("At least one missing field");
(field_in_type, (similarity * 1000000.) as i32)
})
.collect::<Vec<_>>();
}).collect::<Vec<_>>();
field_similarity.sort_by_key(|t| ::std::cmp::Reverse(t.1));

Box::new(move |field: &I| {
Expand Down Expand Up @@ -395,7 +393,8 @@ where
&& l_row
.iter()
.zip(r_row)
.all(|(l, r)| l.name.name_eq(&r.name)) && l_rest == r_rest
.all(|(l, r)| l.name.name_eq(&r.name))
&& l_rest == r_rest
{
let iter = l_row.iter().zip(r_row);
let new_fields = merge::merge_tuple_iter(iter, |l, r| {
Expand Down Expand Up @@ -439,7 +438,8 @@ where
&& l_args
.iter()
.zip(r_args)
.all(|(l, r)| l.name.name_eq(&r.name)) && l_types == r_types
.all(|(l, r)| l.name.name_eq(&r.name))
&& l_types == r_types
{
let new_args = merge::merge_tuple_iter(l_args.iter().zip(r_args), |l, r| {
unifier
Expand Down
17 changes: 17 additions & 0 deletions check/tests/forall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1045,3 +1045,20 @@ some_int // Undefined behaviour
support::print_ident_types(&expr);
assert!(result.is_err(), "{}", result.unwrap());
}

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

let text = r#"
type Option a = | None | Some a
type Record b = { x : Option b }
let f = \_ ->
{ x = None }
f
"#;
let result = support::typecheck(text);

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

0 comments on commit b0f283f

Please sign in to comment.