preserve type-aliases from annotations on calls.
This commit is contained in:
parent
191e4d47b3
commit
c169596c76
|
@ -117,16 +117,18 @@ impl<'a> Environment<'a> {
|
||||||
fn_location: Span,
|
fn_location: Span,
|
||||||
call_location: Span,
|
call_location: Span,
|
||||||
) -> Result<(Vec<Rc<Type>>, Rc<Type>), Error> {
|
) -> Result<(Vec<Rc<Type>>, Rc<Type>), Error> {
|
||||||
if let Type::Var { tipo, .. } = tipo.deref() {
|
if let Type::Var { tipo, alias } = tipo.deref() {
|
||||||
let new_value = match tipo.borrow().deref() {
|
let new_value = match tipo.borrow().deref() {
|
||||||
TypeVar::Link { tipo, .. } => {
|
TypeVar::Link { tipo } => {
|
||||||
return self.match_fun_type(tipo.clone(), arity, fn_location, call_location);
|
let (args, ret) =
|
||||||
|
self.match_fun_type(tipo.clone(), arity, fn_location, call_location)?;
|
||||||
|
return Ok((args, Type::with_alias(ret, alias.clone())));
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeVar::Unbound { .. } => {
|
TypeVar::Unbound { .. } => {
|
||||||
let args: Vec<_> = (0..arity).map(|_| self.new_unbound_var()).collect();
|
let args: Vec<_> = (0..arity).map(|_| self.new_unbound_var()).collect();
|
||||||
|
|
||||||
let ret = self.new_unbound_var();
|
let ret = Type::with_alias(self.new_unbound_var(), alias.clone());
|
||||||
|
|
||||||
Some((args, ret))
|
Some((args, ret))
|
||||||
}
|
}
|
||||||
|
@ -139,7 +141,7 @@ impl<'a> Environment<'a> {
|
||||||
tipo: function(args.clone(), ret.clone()),
|
tipo: function(args.clone(), ret.clone()),
|
||||||
};
|
};
|
||||||
|
|
||||||
return Ok((args, ret));
|
return Ok((args, Type::with_alias(ret, alias.clone())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -579,11 +581,11 @@ impl<'a> Environment<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeVar::Generic { id } => match ids.get(id) {
|
TypeVar::Generic { id } => match ids.get(id) {
|
||||||
Some(t) => return t.clone(),
|
Some(t) => return Type::with_alias(t.clone(), alias.clone()),
|
||||||
None => {
|
None => {
|
||||||
if !hydrator.is_rigid(id) {
|
if !hydrator.is_rigid(id) {
|
||||||
// Check this in the hydrator, i.e. is it a created type
|
// Check this in the hydrator, i.e. is it a created type
|
||||||
let v = self.new_unbound_var();
|
let v = Type::with_alias(self.new_unbound_var(), alias.clone());
|
||||||
ids.insert(*id, v.clone());
|
ids.insert(*id, v.clone());
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,7 +147,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
expected_args: &[Rc<Type>],
|
expected_args: &[Rc<Type>],
|
||||||
body: UntypedExpr,
|
body: UntypedExpr,
|
||||||
return_annotation: &Option<Annotation>,
|
return_annotation: &Option<Annotation>,
|
||||||
) -> Result<(Vec<TypedArg>, TypedExpr), Error> {
|
) -> Result<(Vec<TypedArg>, TypedExpr, Rc<Type>), Error> {
|
||||||
// Construct an initial type for each argument of the function- either an unbound
|
// Construct an initial type for each argument of the function- either an unbound
|
||||||
// type variable or a type provided by an annotation.
|
// type variable or a type provided by an annotation.
|
||||||
|
|
||||||
|
@ -1491,11 +1491,12 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
return_annotation: Option<Annotation>,
|
return_annotation: Option<Annotation>,
|
||||||
location: Span,
|
location: Span,
|
||||||
) -> Result<TypedExpr, Error> {
|
) -> Result<TypedExpr, Error> {
|
||||||
let (args, body) = self.do_infer_fn(args, expected_args, body, &return_annotation)?;
|
let (args, body, return_type) =
|
||||||
|
self.do_infer_fn(args, expected_args, body, &return_annotation)?;
|
||||||
|
|
||||||
let args_types = args.iter().map(|a| a.tipo.clone()).collect();
|
let args_types = args.iter().map(|a| a.tipo.clone()).collect();
|
||||||
|
|
||||||
let tipo = function(args_types, body.tipo());
|
let tipo = function(args_types, return_type);
|
||||||
|
|
||||||
Ok(TypedExpr::Fn {
|
Ok(TypedExpr::Fn {
|
||||||
location,
|
location,
|
||||||
|
@ -1512,7 +1513,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
args: Vec<TypedArg>,
|
args: Vec<TypedArg>,
|
||||||
body: UntypedExpr,
|
body: UntypedExpr,
|
||||||
return_type: Option<Rc<Type>>,
|
return_type: Option<Rc<Type>>,
|
||||||
) -> Result<(Vec<TypedArg>, TypedExpr), Error> {
|
) -> Result<(Vec<TypedArg>, TypedExpr, Rc<Type>), Error> {
|
||||||
assert_no_assignment(&body)?;
|
assert_no_assignment(&body)?;
|
||||||
|
|
||||||
let (body_rigid_names, body_infer) = self.in_new_scope(|body_typer| {
|
let (body_rigid_names, body_infer) = self.in_new_scope(|body_typer| {
|
||||||
|
@ -1558,7 +1559,8 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
let body = body_infer.map_err(|e| e.with_unify_error_rigid_names(&body_rigid_names))?;
|
let body = body_infer.map_err(|e| e.with_unify_error_rigid_names(&body_rigid_names))?;
|
||||||
|
|
||||||
// Check that any return type is accurate.
|
// Check that any return type is accurate.
|
||||||
if let Some(return_type) = return_type {
|
let return_type = match return_type {
|
||||||
|
Some(return_type) => {
|
||||||
self.unify(
|
self.unify(
|
||||||
return_type.clone(),
|
return_type.clone(),
|
||||||
body.tipo(),
|
body.tipo(),
|
||||||
|
@ -1569,12 +1571,16 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
e.return_annotation_mismatch()
|
e.return_annotation_mismatch()
|
||||||
.with_unify_error_rigid_names(&body_rigid_names)
|
.with_unify_error_rigid_names(&body_rigid_names)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
Type::with_alias(body.tipo(), return_type.alias())
|
||||||
}
|
}
|
||||||
|
None => body.tipo(),
|
||||||
|
};
|
||||||
|
|
||||||
// Ensure elements are serialisable to Data.
|
// Ensure elements are serialisable to Data.
|
||||||
ensure_serialisable(true, body.tipo(), body.type_defining_location())?;
|
ensure_serialisable(true, return_type.clone(), body.type_defining_location())?;
|
||||||
|
|
||||||
Ok((args, body))
|
Ok((args, body, return_type))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn infer_uint(&mut self, value: String, location: Span) -> TypedExpr {
|
fn infer_uint(&mut self, value: String, location: Span) -> TypedExpr {
|
||||||
|
|
|
@ -701,11 +701,12 @@ fn infer_function(
|
||||||
.remove(&name)
|
.remove(&name)
|
||||||
.expect("Could not find hydrator for fn");
|
.expect("Could not find hydrator for fn");
|
||||||
|
|
||||||
let (args, body) = expr_typer.infer_fn_with_known_types(args, body, Some(return_type))?;
|
let (args, body, return_type) =
|
||||||
|
expr_typer.infer_fn_with_known_types(args, body, Some(return_type))?;
|
||||||
|
|
||||||
let args_types = args.iter().map(|a| a.tipo.clone()).collect();
|
let args_types = args.iter().map(|a| a.tipo.clone()).collect();
|
||||||
|
|
||||||
let tipo = function(args_types, body.tipo());
|
let tipo = function(args_types, return_type);
|
||||||
|
|
||||||
let safe_to_generalise = !expr_typer.ungeneralised_function_used;
|
let safe_to_generalise = !expr_typer.ungeneralised_function_used;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue