use std::{
borrow::{BorrowMut, Cow},
mem,
sync::Arc,
};
use crate::base::{
ast::{
self, Argument, AstType, DisplayEnv, Do, Expr, IdentEnv, KindedIdent, Literal, MutVisitor,
Pattern, PatternField, SpannedExpr, SpannedIdent, SpannedPattern, TypeBinding, Typed,
TypedIdent, ValueBinding, ValueBindings,
},
error::Errors,
fnv::{FnvMap, FnvSet},
kind::{ArcKind, Kind, KindCache, KindEnv},
merge,
metadata::{Metadata, MetadataEnv},
pos::{self, BytePos, Span, Spanned},
resolve,
scoped_map::{self, ScopedMap},
symbol::{Symbol, SymbolModule, SymbolRef, Symbols},
types::{
self, Alias, AliasRef, AppVec, ArcType, ArgType, Field, Flags, Generic, PrimitiveEnv, Type,
TypeCache, TypeContext, TypeEnv, TypeExt, TypePtr, Walker,
},
};
use crate::{
implicits,
kindcheck::KindCheck,
substitution::{self, Substitution},
typ::RcType,
unify, unify_type, TypecheckEnv,
};
use self::{
generalize::TypeGeneralizer,
mod_type::{ModType, ModTypeRef, TypeModifier},
};
pub use self::error::{Help, HelpError, SpannedTypeError, TypeError};
mod error;
mod generalize;
mod mod_type;
pub(crate) type TcResult<T> = Result<T, TypeError<Symbol, RcType<Symbol>>>;
enum ErrorOrder {
ExpectedActual,
ActualExpected,
}
#[derive(Clone, Debug)]
struct StackBinding {
typ: ModType,
}
pub(crate) struct Environment<'a> {
environment: &'a (dyn TypecheckEnv<Type = RcType> + 'a),
stack: ScopedMap<Symbol, StackBinding>,
stack_types: ScopedMap<Symbol, (RcType, Alias<Symbol, RcType>)>,
kind_cache: KindCache,
type_variables: ScopedMap<Symbol, RcType>,
skolem_variables: ScopedMap<Symbol, RcType>,
}
impl<'a> KindEnv for Environment<'a> {
fn find_kind(&self, type_name: &SymbolRef) -> Option<ArcKind> {
self.stack_types
.get(type_name)
.map(|&(_, ref alias)| alias.kind(&self.kind_cache).into_owned())
.or_else(|| {
self.type_variables
.get(type_name)
.map(|t| t.kind(&self.kind_cache).into_owned())
})
.or_else(|| self.environment.find_kind(type_name))
}
}
impl<'a> TypeEnv for Environment<'a> {
type Type = RcType;
fn find_type(&self, id: &SymbolRef) -> Option<RcType> {
self.stack
.get(id)
.map(|bind| bind.typ.concrete.clone())
.or_else(|| self.environment.find_type(id))
}
fn find_type_info(&self, id: &SymbolRef) -> Option<Alias<Symbol, RcType>> {
self.stack_types
.get(id)
.map(|&(_, ref alias)| alias.clone())
.or_else(|| self.environment.find_type_info(id))
}
}
impl<'a> PrimitiveEnv for Environment<'a> {
fn get_bool(&self) -> ArcType {
self.environment.get_bool()
}
}
impl<'a> MetadataEnv for Environment<'a> {
fn get_metadata(&self, id: &SymbolRef) -> Option<Arc<Metadata>> {
self.environment.get_metadata(id)
}
}
impl Environment<'_> {
fn find_mod_type(&self, id: &SymbolRef) -> Option<ModType> {
self.stack
.get(id)
.map(|bind| bind.typ.clone())
.or_else(|| self.environment.find_type(id).map(ModType::rigid))
}
}
pub struct Typecheck<'a, 'ast> {
pub(crate) environment: Environment<'a>,
symbols: SymbolModule<'a>,
pub(crate) subs: Substitution<RcType>,
named_variables: FnvMap<Symbol, RcType>,
pub(crate) errors: Errors<SpannedTypeError<Symbol, RcType<Symbol>>>,
kind_cache: KindCache,
pub(crate) implicit_resolver: implicits::ImplicitResolver<'a>,
unbound_variables: ScopedMap<Symbol, ArcKind>,
refined_variables: ScopedMap<u32, ()>,
pub(crate) ast_arena: ast::ArenaRef<'a, 'ast, Symbol>,
}
impl<'a> TypeContext<Symbol, RcType> for Typecheck<'a, '_> {
gluon_base::forward_type_interner_methods!(Symbol, RcType, self_, &self_.subs);
}
pub type Error = Errors<SpannedTypeError<Symbol>>;
pub use implicits::{Error as ImplicitError, ErrorKind as ImplicitErrorKind};
impl<'a, 'ast> Typecheck<'a, 'ast> {
pub fn new(
module: String,
symbols: &'a mut Symbols,
environment: &'a (dyn TypecheckEnv<Type = ArcType> + 'a),
interner: &TypeCache<Symbol, ArcType>,
metadata: &'a mut FnvMap<Symbol, Arc<Metadata>>,
ast_arena: ast::ArenaRef<'a, 'ast, Symbol>,
) -> Self {
let symbols = SymbolModule::new(module, symbols);
let subs = Substitution::new(interner.kind_cache.typ(), interner.clone());
Typecheck {
environment: Environment {
environment,
stack: ScopedMap::new(),
stack_types: ScopedMap::new(),
kind_cache: interner.kind_cache.clone(),
skolem_variables: ScopedMap::new(),
type_variables: ScopedMap::new(),
},
symbols: symbols,
named_variables: FnvMap::default(),
errors: Errors::new(),
kind_cache: interner.kind_cache.clone(),
implicit_resolver: crate::implicits::ImplicitResolver::new(environment, metadata),
unbound_variables: ScopedMap::new(),
refined_variables: ScopedMap::new(),
subs,
ast_arena,
}
}
pub(crate) fn error<E>(&mut self, span: Span<BytePos>, error: E) -> RcType
where
E: Into<HelpError<Symbol, RcType>>,
{
let error = error.into();
debug!("Error: {}", error);
self.errors.push(Spanned {
span: span,
value: error,
});
self.subs.error()
}
fn bool(&mut self) -> RcType {
let typ = self.environment.get_bool().clone();
self.translate_arc_type(&typ)
}
fn find_at(&mut self, span: Span<BytePos>, id: &Symbol) -> ModType {
match self.find(id) {
Ok(typ) => typ,
Err(err) => ModType::wobbly(self.error(span, err)),
}
}
fn find(&mut self, id: &Symbol) -> TcResult<ModType> {
match self.environment.find_mod_type(id).map(|t| t.to_owned()) {
Some(typ) => {
self.named_variables.clear();
debug!("Find {} : {}", self.symbols.string(id), typ);
Ok(typ)
}
None => {
if id.is_global() {
Ok(ModType::wobbly(self.subs.new_var()))
} else {
info!("Undefined variable {}", id);
Err(TypeError::UndefinedVariable(id.clone()))
}
}
}
}
fn find_type_info_at(&mut self, span: Span<BytePos>, id: &Symbol) -> Alias<Symbol, RcType> {
match self.find_type_info(id).map(|alias| alias.clone()) {
Ok(alias) => alias,
Err(err) => {
self.errors.push(Spanned {
span: span,
value: err.into(),
});
let hole = self.subs.hole();
self.subs.new_alias(id.clone(), Vec::new(), hole)
}
}
}
fn find_type_info(&self, id: &Symbol) -> TcResult<Alias<Symbol, RcType>> {
self.environment
.find_type_info(id)
.ok_or_else(|| TypeError::UndefinedType(id.clone()))
}
fn stack_var(&mut self, id: Symbol, typ: RcType) {
let modifier = if typ
.flags()
.intersects(Flags::HAS_VARIABLES | Flags::HAS_FORALL)
{
TypeModifier::Wobbly
} else {
TypeModifier::Rigid
};
debug!("Insert {} : {:?} {}", id, modifier, typ);
self.implicit_resolver.on_stack_var(&self.subs, &id, &typ);
self.environment.stack.insert(
id,
StackBinding {
typ: ModType::new(modifier, typ),
},
);
}
fn stack_type(&mut self, id: Symbol, alias: &Alias<Symbol, RcType>) {
let aliased_type = alias.typ(&mut &self.subs);
let canonical_alias_type = resolve::AliasRemover::new()
.canonical_alias(&self.environment, &mut &self.subs, &aliased_type, |alias| {
match **alias.unresolved_type() {
Type::Variant(_) => true,
_ => false,
}
})
.unwrap_or_else(|_err| {
aliased_type.clone()
});
let (outer_params, canonical_alias, inner_type) =
alias.unpack_canonical_alias(&canonical_alias_type, |a| a.typ(&mut &self.subs));
if let Type::Variant(ref variants) = **inner_type {
for field in variants.row_iter().cloned() {
let a = self.intern(Type::Alias(canonical_alias.clone()));
let params = canonical_alias
.params()
.iter()
.map(|g| self.generic(g.clone()))
.collect();
let variant_type = self.app(a.clone(), params);
let ctor_type =
types::walk_move_type(field.typ.clone(), &mut |typ: &ArcType| match &**typ {
Type::Function(ArgType::Constructor, arg, ret) => {
Some(Type::function(Some(arg.clone()), ret.clone()))
}
Type::Ident(id) if canonical_alias.name == id.name => Some(a.clone()),
Type::Opaque => Some(variant_type.clone()),
_ => None,
});
let typ = self.forall(
canonical_alias
.params()
.iter()
.chain(outer_params.iter())
.cloned()
.collect(),
ctor_type,
);
let symbol = self.symbols.symbols().simple_symbol(field.name.as_str());
self.stack_var(symbol, typ);
}
}
let generic_args = alias
.params()
.iter()
.cloned()
.map(|g| self.generic(g))
.collect();
let typ = self.subs.app(alias.as_ref().clone(), generic_args);
{
self.environment
.stack_types
.insert(alias.name.clone(), (typ.clone(), alias.clone()));
}
self.environment
.stack_types
.insert(id, (typ, alias.clone()));
}
fn enter_scope(&mut self) {
self.environment.stack.enter_scope();
self.environment.stack_types.enter_scope();
self.implicit_resolver.enter_scope();
}
fn exit_scope(&mut self) {
self.environment.stack.exit_scope();
self.environment.stack_types.exit_scope();
self.implicit_resolver.exit_scope();
}
fn generalize_binding(
&mut self,
level: u32,
resolved_type: &mut RcType,
binding: &mut ValueBinding<'ast, Symbol>,
) {
let mut generalizer = TypeGeneralizer::new(level, self, resolved_type, binding.name.span);
generalize_binding(&mut generalizer, resolved_type, binding);
}
fn generalize_variables<'i>(
&mut self,
level: u32,
args: &mut dyn Iterator<Item = &'i mut SpannedIdent<Symbol>>,
expr: &mut SpannedExpr<Symbol>,
) {
let typ = self.subs.hole();
TypeGeneralizer::new(level, self, &typ, expr.span).generalize_variables(args, expr)
}
fn generalize_type_errors(&mut self, errors: &mut Errors<SpannedTypeError<Symbol, RcType>>) {
self.environment.skolem_variables.enter_scope();
for err in errors {
use self::TypeError::*;
match err.value.error {
UndefinedVariable(_)
| UndefinedType(_)
| DuplicateTypeDefinition(_)
| DuplicateField(_)
| UndefinedRecord { .. }
| EmptyCase
| KindError(_)
| RecursionCheck(_)
| Message(_) => (),
NotAFunction(ref mut typ)
| UndefinedField(ref mut typ, _)
| PatternError {
constructor_type: ref mut typ,
..
}
| InvalidProjection(ref mut typ)
| TypeConstructorReturnsWrongType {
actual: ref mut typ,
..
} => self.generalize_type(0, typ, err.span),
UnableToResolveImplicit(ref mut inner_err) => {
use crate::implicits::ErrorKind::*;
match inner_err.kind {
MissingImplicit(ref mut typ) => {
self.generalize_type(0, typ, err.span);
}
AmbiguousImplicit(ref mut xs) => {
for entry in xs {
self.generalize_type(0, &mut entry.typ, err.span);
}
}
LoopInImplicitResolution(..) => (),
}
let err_span = err.span;
inner_err.reason = inner_err
.reason
.iter()
.map(|typ| {
let mut typ = typ.clone();
self.generalize_type(0, &mut typ, err_span);
typ
})
.collect();
}
Unification(ref mut expected, ref mut actual, ref mut errors) => {
self.generalize_type_without_forall(0, expected, err.span);
self.generalize_type_without_forall(0, actual, err.span);
for unify_err in errors {
match *unify_err {
unify::Error::TypeMismatch(ref mut l, ref mut r) => {
self.generalize_type_without_forall(0, l, err.span);
self.generalize_type_without_forall(0, r, err.span);
}
unify::Error::Substitution(ref mut occurs_err) => match *occurs_err {
substitution::Error::Occurs(_, ref mut typ) => {
self.generalize_type_without_forall(0, typ, err.span);
}
},
unify::Error::Other(ref mut other_err) => {
if let unify_type::TypeError::MissingFields(ref mut typ, _) =
*other_err
{
self.generalize_type_without_forall(0, typ, err.span);
}
}
}
}
}
}
}
self.environment.skolem_variables.exit_scope();
}
pub fn typecheck_expr(
&mut self,
expr: &mut SpannedExpr<'ast, Symbol>,
) -> Result<ArcType, Error> {
self.typecheck_expr_expected(expr, None)
}
pub fn typecheck_expr_expected(
&mut self,
expr: &mut SpannedExpr<'ast, Symbol>,
expected_type: Option<&ArcType>,
) -> Result<ArcType, Error> {
let expected_type = expected_type.map(|t| self.translate_arc_type(t));
self.typecheck_expr_expected_(expr, expected_type.as_ref())
.map(|t| self.translate_rc_type(&t))
}
fn typecheck_expr_expected_(
&mut self,
expr: &mut SpannedExpr<'ast, Symbol>,
expected_type: Option<&RcType>,
) -> Result<RcType, Error> {
fn tail_expr<'e, 'ast>(
e: &'e mut SpannedExpr<'ast, Symbol>,
) -> &'e mut SpannedExpr<'ast, Symbol> {
match e.value {
Expr::LetBindings(_, ref mut b) | Expr::TypeBindings(_, ref mut b) => tail_expr(b),
_ => e,
}
}
info!("Typechecking {}", self.symbols.module());
self.environment.stack.clear();
if let Err(err) = crate::recursion_check::check_expr(expr) {
self.errors.extend(
err.into_iter()
.map(|err| pos::spanned(err.span, TypeError::from(err.value).into())),
);
}
let temp = expected_type.and_then(|expected| self.create_unifiable_signature(expected));
let expected_type = temp.as_ref().or(expected_type);
let mut typ = if let Some(expected_type) = expected_type {
self.skolemize_in(
expr.span,
ModType::rigid(&expected_type),
|self_, expected_type| {
self_.typecheck_bindings(true, expr, Some(ModType::rigid(&expected_type)))
},
)
} else {
self.typecheck_bindings(true, expr, None)
};
{
if let Some(expected_type) = expected_type {
let mut type_cache = &self.subs;
self.environment.skolem_variables.extend(
expected_type
.forall_params()
.map(|param| (param.id.clone(), type_cache.hole())),
);
}
let tail = tail_expr(expr);
crate::implicits::resolve(self, tail);
self.generalize_type(0, &mut typ, tail.span);
self.generalize_variables(0, &mut [].iter_mut(), tail);
}
{
struct ReplaceVisitor<'a: 'b, 'b, 'ast> {
tc: &'b mut Typecheck<'a, 'ast>,
}
impl<'a, 'b, 'd> MutVisitor<'d, '_> for ReplaceVisitor<'a, 'b, '_> {
type Ident = Symbol;
fn visit_typ(&mut self, typ: &mut ArcType) {
*typ = if let Type::Variable(var) = &**typ {
let typ = self
.tc
.subs
.find_type_for_var(var.id)
.cloned()
.unwrap_or_else(|| self.tc.subs.error());
self.tc.translate_rc_type(&typ)
} else {
return;
}
}
}
{
let mut visitor = ReplaceVisitor { tc: self };
visitor.visit_expr(expr);
}
}
if self.errors.has_errors() {
let mut errors = mem::replace(&mut self.errors, Errors::new());
let l = errors.len();
debug!("Generalize type errors");
self.generalize_type_errors(&mut errors);
while errors.len() > l {
errors.pop();
}
Err(errors
.into_iter()
.map(|spanned| {
spanned.map(|err| crate::base::error::Help {
error: err.error.map_t(&mut |t| self.translate_rc_type(&t)),
help: err.help,
})
})
.collect())
} else {
debug!("Typecheck result: {}", typ);
Ok(typ.concrete)
}
}
fn infer_expr(&mut self, expr: &mut SpannedExpr<'ast, Symbol>) -> ModType {
self.typecheck_opt(expr, None)
}
fn typecheck(
&mut self,
expr: &mut SpannedExpr<'ast, Symbol>,
expected_type: ModTypeRef,
) -> ModType {
self.typecheck_opt(expr, Some(expected_type))
}
fn typecheck_opt(
&mut self,
expr: &mut SpannedExpr<'ast, Symbol>,
mut expected_type: Option<ModTypeRef>,
) -> ModType {
let returned_type;
match self.typecheck_(expr, &mut expected_type) {
Ok((typ, args)) => {
if !args.is_empty() {
match expr.value {
Expr::App {
ref mut implicit_args,
..
} => {
if implicit_args.is_empty() {
*implicit_args = self.ast_arena.alloc_extend(args);
} else {
*implicit_args = self.ast_arena.alloc_extend(
implicit_args.iter_mut().map(mem::take).chain(args),
);
}
}
_ => {
let func = mem::take(&mut expr.value);
expr.value = Expr::App {
func: self.ast_arena.alloc(pos::spanned(expr.span, func)),
implicit_args: self.ast_arena.alloc_extend(args),
args: &mut [],
}
}
}
}
returned_type = match expected_type {
Some(expected_type) => ModType::new(
expected_type.modifier,
self.subsumes_expr(expr.span, &typ, expected_type.concrete.clone(), expr),
),
None => typ,
};
}
Err(err) => {
returned_type = ModType::wobbly(self.subs.error());
self.errors.push(Spanned {
span: expr_check_span(expr),
value: err.into(),
});
}
}
returned_type
}
fn typecheck_(
&mut self,
expr: &mut SpannedExpr<'ast, Symbol>,
expected_type: &mut Option<ModTypeRef>,
) -> TcResult<(ModType, Vec<SpannedExpr<'ast, Symbol>>)> {
if let Some(result) = self.check_macro(expr) {
return Ok((result?, Vec::new()));
}
match expr.value {
Expr::Ident(ref mut id) => {
let typ = self.find(&id.name)?;
let modifier = typ.modifier;
let (args, typ) = self.instantiate_sigma(
expr.span,
&typ,
&mut expected_type.take().map(|t| t.concrete),
);
id.typ = self.subs.bind_arc(&typ);
Ok((ModType::new(modifier, typ), args))
}
Expr::Literal(ref lit) => Ok((
ModType::rigid(match *lit {
Literal::Int(_) => self.subs.int(),
Literal::Byte(_) => self.subs.byte(),
Literal::Float(_) => self.subs.float(),
Literal::String(_) => self.subs.string(),
Literal::Char(_) => self.subs.char(),
}),
Vec::new(),
)),
Expr::App {
ref mut func,
ref mut implicit_args,
ref mut args,
} => {
let func_type = self.infer_expr(func);
let mut implicit_vec = CowVec::Borrowed(implicit_args);
let typ = self.typecheck_application(
expr.span,
func_type,
&mut implicit_vec,
&mut **args,
);
if let CowVec::Owned(implicit_vec) = implicit_vec {
*implicit_args = self.ast_arena.alloc_extend(implicit_vec);
}
typ
}
Expr::IfElse(ref mut pred, ref mut if_true, ref mut if_false) => {
let bool_type = self.bool();
let pred_type = self.typecheck(&mut **pred, ModType::rigid(&bool_type));
self.unify_span(expr_check_span(pred), &bool_type, pred_type.concrete);
let true_type = self.typecheck_opt(&mut **if_true, expected_type.clone());
let false_type = self.typecheck_opt(&mut **if_false, expected_type.take());
let modifier = true_type.modifier | false_type.modifier;
let true_type = self.instantiate_generics(&true_type);
let false_type = self.instantiate_generics(&false_type);
self.unify(&true_type, false_type)
.map(|t| (ModType::new(modifier, t), Vec::new()))
}
Expr::Infix {
ref mut lhs,
ref mut op,
ref mut rhs,
ref mut implicit_args,
} => {
let op_name = String::from(self.symbols.string(&op.value.name));
let func_type = if op_name.starts_with('#') {
let op_type = op_name.trim_matches(|c: char| !c.is_alphabetic());
let builtin_type = op_type.parse().map_err(|_| {
TypeError::Message("Invalid builtin type for operator".to_string())
})?;
let prim_type = self.subs.builtin_type(builtin_type);
let return_type = match &op_name[1 + op_type.len()..] {
"+" | "-" | "*" | "/" => prim_type.clone(),
"==" | "<" => self.bool(),
_ => return Err(TypeError::UndefinedVariable(op.value.name.clone())),
};
ModType::rigid(self.subs.function(
vec![prim_type.clone(), prim_type.clone()],
return_type.clone(),
))
} else {
match &*op_name {
"&&" | "||" => {
let b = self.bool();
ModType::rigid(self.subs.function(vec![b.clone(), b.clone()], b))
}
_ => self.find_at(op.span, &op.value.name),
}
};
let func_type =
ModType::new(func_type.modifier, self.instantiate_generics(&func_type));
op.value.typ = self.subs.bind_arc(&func_type);
let mut implicit_vec = CowVec::Borrowed(implicit_args);
let typ = self.typecheck_application(
op.span,
func_type,
&mut implicit_vec,
[&mut **lhs, &mut **rhs].iter_mut().map(|expr| &mut **expr),
);
if let CowVec::Owned(implicit_vec) = implicit_vec {
*implicit_args = self.ast_arena.alloc_extend(implicit_vec);
}
typ
}
Expr::Tuple {
ref mut typ,
elems: ref mut exprs,
} => {
let new_type = match exprs.len() {
0 => ModType::rigid(self.unit()),
1 => self.typecheck_opt(&mut exprs[0], expected_type.take()),
_ => {
let mut modifier = TypeModifier::Rigid;
let fields = exprs
.iter_mut()
.enumerate()
.map(|(i, expr)| {
let typ = self.infer_expr(expr);
modifier |= typ.modifier;
Field {
name: self.symbols.simple_symbol(format!("_{}", i)),
typ: typ.concrete,
}
})
.collect();
ModType::new(modifier, self.record(vec![], fields))
}
};
*typ = self.subs.bind_arc(&new_type);
Ok((new_type, Vec::new()))
}
Expr::Match(ref mut expr, ref mut alts) => {
let mut scrutinee_type = self.infer_expr(&mut **expr);
let modifier = scrutinee_type.modifier;
let expected_type = expected_type.take().map(|t| t.to_owned());
let mut unaliased_scrutinee_type = match alts.first().map(|alt| &alt.pattern.value)
{
Some(Pattern::Constructor(..)) => {
let typ = self.remove_aliases(scrutinee_type.concrete.clone());
ModType::new(modifier, self.instantiate_generics(&typ))
}
_ => scrutinee_type.clone(),
};
let mut expr_type: Option<ModType> = None;
let original_scrutinee_type = scrutinee_type.clone();
for alt in alts.iter_mut() {
self.enter_scope();
self.refined_variables.enter_scope();
self.typecheck_pattern(
&mut alt.pattern,
original_scrutinee_type.clone(),
scrutinee_type.concrete.clone(),
);
let mut alt_type = self
.typecheck_opt(&mut alt.expr, expected_type.as_ref().map(|t| t.as_ref()));
alt_type.concrete = self.instantiate_generics(&alt_type);
match expr_type {
Some(ref expr_type) if expected_type.is_none() => {
alt_type.concrete =
self.unify_span(alt.expr.span, expr_type, alt_type.concrete);
}
_ => (),
}
for (var, _) in self.refined_variables.exit_scope() {
self.subs.reset(var);
}
self.exit_scope();
{
*unaliased_scrutinee_type = self.subs.zonk(&unaliased_scrutinee_type);
let replaced = match (&alt.pattern.value, &**unaliased_scrutinee_type) {
(Pattern::Constructor(id, _), Type::Variant(row)) => {
let mut variant_iter = row.row_iter();
let variants = variant_iter
.by_ref()
.filter(|variant| variant.name != id.name)
.cloned()
.collect();
if let Type::EmptyRow = **variant_iter.current_type() {
false
} else {
let rest = self.subs.new_var();
scrutinee_type.concrete = self.poly_variant(variants, rest);
true
}
}
_ => false,
};
if replaced {
unaliased_scrutinee_type = scrutinee_type.clone();
}
}
expr_type = Some(alt_type);
}
expr_type
.ok_or(TypeError::EmptyCase)
.map(|typ| (typ, Vec::new()))
}
Expr::TypeBindings(..) | Expr::LetBindings(..) => Ok((
self.typecheck_bindings(false, expr, expected_type.take()),
Vec::new(),
)),
Expr::Projection(ref mut expr, ref field_id, ref mut ast_field_typ) => {
let mut expr_typ = self.infer_expr(&mut **expr);
let modifier = expr_typ.modifier;
debug!(
"Projection {} . {:?}",
&expr_typ,
self.symbols.string(field_id)
);
self.subs.make_real(&mut expr_typ);
expr_typ.concrete = self.instantiate_generics(&expr_typ);
let record = self.remove_aliases(expr_typ.concrete.clone());
match *record {
Type::Variable(_) | Type::Record(_) => {
let field_type = record
.row_iter()
.find(|field| field.name.name_eq(field_id))
.map(|field| field.typ.clone());
let mut implicit_args = Vec::new();
let new_ast_field_type = match field_type {
Some(typ) => {
let (args, typ) = self.instantiate_sigma(
expr.span,
&typ,
&mut expected_type.take().map(|t| t.concrete),
);
implicit_args = args;
typ
}
None => {
let field_var = self.subs.new_var();
let field = Field::new(field_id.clone(), field_var.clone());
let record_type =
self.poly_record(vec![], vec![field], self.subs.new_var());
self.unify(&record_type, record)?;
field_var
}
};
*ast_field_typ = self.subs.bind_arc(&new_ast_field_type);
Ok((ModType::new(modifier, new_ast_field_type), implicit_args))
}
Type::Error => Ok((ModType::new(modifier, record.clone()), Vec::new())),
_ => Err(TypeError::InvalidProjection(record)),
}
}
Expr::Array(ref mut array) => {
let mut expected_element_type = ModType::rigid(self.subs.new_var());
let array_type = self.subs.array(expected_element_type.concrete.clone());
array.typ = self.subs.bind_arc(&array_type);
if let Some(expected_type) = expected_type.take() {
self.unify_span(expr.span, &expected_type, array_type.clone());
}
for expr in &mut *array.exprs {
expected_element_type |=
self.typecheck(expr, ModType::wobbly(&expected_element_type));
}
Ok((ModType::wobbly(array_type), Vec::new()))
}
Expr::Lambda(ref mut lambda) => {
let level = self.subs.var_id();
let function_type = expected_type
.take()
.map(|t| t.to_owned())
.unwrap_or_else(|| ModType::wobbly(self.subs.new_var()));
let start = expr.span.start();
let mut typ =
self.skolemize_in(expr.span, function_type.as_ref(), |self_, function_type| {
self_.typecheck_lambda(
function_type,
start,
&mut lambda.args,
&mut lambda.body,
)
});
self.generalize_type(level, &mut typ, expr.span);
lambda.id.typ = self.subs.bind_arc(&typ);
Ok((typ.clone(), Vec::new()))
}
Expr::Record {
ref mut typ,
ref mut types,
exprs: ref mut fields,
ref mut base,
} => {
let level = self.subs.var_id();
let mut modifier = expected_type
.as_ref()
.map(|t| t.modifier)
.unwrap_or_default();
let expected_record_type = expected_type.and_then(|expected_type| {
let expected_type = self.subs.real(&expected_type).clone();
let typ = resolve::remove_aliases_cow(
&self.environment,
&mut &self.subs,
&expected_type,
);
match **typ {
Type::Record(_) => Some(typ.into_owned()),
_ => None,
}
});
let expected_type = match &expected_record_type {
Some(expected_record_type) => {
let mut expected_fields: FnvSet<_> = expected_record_type
.row_iter()
.map(|f| &f.name)
.chain(expected_record_type.type_field_iter().map(|f| &f.name))
.collect();
let expected_fields_matches = fields
.iter()
.map(|f| &f.name.value)
.chain(types.iter().map(|f| &f.name.value))
.all(|name| expected_fields.remove(&name))
&& expected_fields.is_empty();
if expected_fields_matches {
expected_type.take();
}
Some(expected_record_type)
}
None => None,
};
let mut base_record_types = FnvMap::default();
let mut base_record_fields = FnvMap::default();
let mut base_types: Vec<Field<_, _>> = Vec::new();
let mut base_fields: Vec<Field<_, RcType>> = Vec::new();
if let Some(ref mut base) = *base {
let base_type = self.infer_expr(base);
let base_type = self.remove_aliases(base_type.concrete);
let record_type = self.poly_record(vec![], vec![], self.subs.new_var());
let base_type = self.unify_span(base.span, &record_type, base_type);
let base_type = self.subs.zonk(&base_type);
base_types.extend(base_type.type_field_iter().cloned());
base_fields.extend(base_type.row_iter().cloned());
base_record_types.extend(
base_types
.iter()
.map(|field| field.name.declared_name().to_string())
.enumerate()
.map(|(i, n)| (n, i)),
);
base_record_fields.extend(
base_fields
.iter()
.map(|field| field.name.declared_name().to_string())
.enumerate()
.map(|(i, n)| (n, i)),
);
}
let mut duplicated_fields = FnvSet::default();
let mut new_types: Vec<Field<_, _>> = Vec::with_capacity(types.len());
for field in &mut **types {
if let Some(ref mut typ) = field.value {
let rc_type = self.translate_arc_type(typ);
if let Some(new_type) = self.create_unifiable_signature(&rc_type) {
*typ = self.translate_rc_type(&new_type);
}
}
let alias = self.find_type_info_at(field.name.span, &field.name.value);
if self.error_on_duplicated_field(&mut duplicated_fields, &field.name) {
match base_record_types.get(field.name.value.declared_name()) {
Some(&i) => base_types[i].typ = alias,
None => new_types.push(Field::new(field.name.value.clone(), alias)),
}
}
}
let mut new_fields: Vec<Field<_, RcType>> = Vec::with_capacity(fields.len());
for field in &mut **fields {
let name = &field.name.value;
let expected_field_type = expected_type
.as_ref()
.and_then(|expected_type| {
expected_type
.row_iter()
.find(|expected_field| expected_field.name.name_eq(&name))
})
.map(|field| ModType::new(modifier, &field.typ));
let mut typ = match field.value {
Some(ref mut expr) => self.typecheck_opt(expr, expected_field_type),
None => {
let typ = self.find_at(field.name.span, &field.name.value);
let modifier = typ.modifier;
match expected_field_type {
Some(expected_field_type) => {
let mut implicit_args = Vec::new();
let typ = self.subsumes_implicit(
field.name.span,
ErrorOrder::ExpectedActual,
&expected_field_type.concrete,
typ.concrete,
&mut |implicit_arg| {
implicit_args
.push(pos::spanned(field.name.span, implicit_arg));
},
);
if !implicit_args.is_empty() {
field.value = Some(pos::spanned(
field.name.span,
Expr::App {
func: self.ast_arena.alloc(pos::spanned(
field.name.span,
Expr::Ident(TypedIdent {
name: field.name.value.clone(),
typ: self.subs.bind_arc(&typ),
}),
)),
implicit_args: self
.ast_arena
.alloc_extend(implicit_args),
args: &mut [],
},
));
}
ModType::new(modifier, typ)
}
None => typ,
}
}
};
self.generalize_type(level, &mut typ, field.name.span);
if self.error_on_duplicated_field(&mut duplicated_fields, &field.name) {
match base_record_fields.get(field.name.value.declared_name()) {
Some(&i) => base_fields[i].typ = typ.concrete,
None => {
new_fields.push(Field::new(field.name.value.clone(), typ.concrete))
}
}
}
modifier |= typ.modifier;
}
new_types.extend(base_types);
new_fields.extend(base_fields);
let new_type = self.subs.record(new_types, new_fields);
*typ = self.subs.bind_arc(&new_type);
Ok((ModType::new(modifier, new_type), Vec::new()))
}
Expr::Block(ref mut exprs) => {
let (last, exprs) = exprs.split_last_mut().expect("Expr in block");
for expr in exprs {
self.infer_expr(expr);
}
Ok((self.typecheck_opt(last, expected_type.take()), Vec::new()))
}
Expr::Do(Do {
ref mut id,
ref mut typ,
ref mut bound,
ref mut body,
ref mut flat_map_id,
}) => {
let do_span = expr.span.subspan(0.into(), 2.into());
let flat_map_type = match flat_map_id
.as_mut()
.expect("flat_map inserted during renaming")
.value
{
Expr::Ident(ref mut flat_map) => match self.find(&flat_map.name) {
Ok(x) => x,
Err(error) => {
self.error(
do_span,
crate::base::error::Help {
error,
help: Some(Help::UndefinedFlatMapInDo),
},
);
ModType::wobbly(self.subs.error())
}
},
_ => ice!("flat_map_id not inserted during renaming"),
};
let flat_map_type = self.instantiate_generics(&flat_map_type);
let flat_map_type = match *flat_map_type {
Type::Function(ArgType::Implicit, ref arg_type, ref r) => {
let name = self.implicit_resolver.make_implicit_ident(arg_type);
*flat_map_id = Some(self.ast_arena.alloc(pos::spanned(
do_span,
Expr::App {
func: flat_map_id.take().unwrap(),
args: self.ast_arena.alloc_extend(Some(pos::spanned(
do_span,
Expr::Ident(TypedIdent {
name,
typ: self.subs.bind_arc(&arg_type),
}),
))),
implicit_args: &mut [],
},
)));
r.clone()
}
_ => flat_map_type.clone(),
};
let id_type = self.resolve_type_signature(typ.as_mut());
let arg1 = self
.subs
.function(Some(id_type.concrete.clone()), self.subs.new_var());
let arg2 = self.subs.new_var();
let ret = expected_type
.as_ref()
.map(|t| t.to_owned())
.unwrap_or_else(|| ModType::wobbly(self.subs.new_var()));
let func_type = self
.subs
.function(vec![arg1.clone(), arg2.clone()], ret.concrete.clone());
self.typecheck(bound, ModType::wobbly(&arg2));
self.unify_span(do_span, &flat_map_type, func_type);
if let Some(ref mut id) = *id {
self.typecheck_pattern(id, id_type.clone(), id_type.concrete);
}
let body_type = self.typecheck(body, ret.as_ref());
let ret = self.unify_span(body.span, &ret, body_type.concrete.clone());
Ok((ModType::wobbly(ret), Vec::new()))
}
Expr::MacroExpansion {
ref mut replacement,
..
} => self.typecheck_(replacement, expected_type),
Expr::Annotated(ref mut expr, ref mut typ) => {
let mut typ = self.translate_arc_type(typ);
if let Some(new) = self.create_unifiable_signature(&typ) {
typ = new;
}
self.typecheck_(expr, &mut Some(ModType::rigid(&typ)))
}
Expr::Error(ref typ) => Ok((
ModType::wobbly(
typ.as_ref()
.map(|typ| self.translate_arc_type(typ))
.unwrap_or_else(|| self.subs.new_var()),
),
Vec::new(),
)),
}
}
fn typecheck_application<'e, I>(
&mut self,
span: Span<BytePos>,
func_type: ModType,
implicit_args: &mut CowVec<SpannedExpr<'ast, Symbol>>,
args: I,
) -> TcResult<(ModType, Vec<SpannedExpr<'ast, Symbol>>)>
where
I: IntoIterator<Item = &'e mut SpannedExpr<'ast, Symbol>>,
I::IntoIter: ExactSizeIterator,
'ast: 'e,
{
self.typecheck_application_(span, func_type, implicit_args, &mut args.into_iter())
.map(|typ| (typ, Vec::new()))
}
fn typecheck_application_<'e>(
&mut self,
span: Span<BytePos>,
func_type: ModType,
implicit_args: &mut CowVec<SpannedExpr<'ast, Symbol>>,
args: &mut dyn ExactSizeIterator<Item = &'e mut SpannedExpr<'ast, Symbol>>,
) -> TcResult<ModType>
where
'ast: 'e,
{
fn attach_extra_argument_help<F, R>(self_: &mut Typecheck, actual: u32, f: F) -> R
where
F: FnOnce(&mut Typecheck) -> R,
{
let errors_before = self_.errors.len();
let t = f(self_);
if errors_before != self_.errors.len() {
let len = self_.errors.len();
let expected_type = match self_.errors[len - 1].value.error {
TypeError::Unification(ref expected_type, ..) => expected_type.clone(),
_ => return t,
};
let extra = function_arg_iter(self_, expected_type).count() as u32;
self_.errors[len - 1].value.help =
Some(Help::ExtraArgument(actual - extra, actual));
}
t
}
let args_len = args.len() as u32;
let original_func_type = func_type.concrete.clone();
let mut func_type = self.instantiate_generics(&func_type);
let mut return_variables = FnvSet::default();
for arg in &mut **implicit_args {
let (arg_typ, ret_typ) = self.subsume_function(
arg.span.start(),
arg.span,
ArgType::Implicit,
func_type.clone(),
&mut |_| unreachable!(),
);
let arg_typ = self.typecheck(arg, ModType::wobbly(&arg_typ));
if arg_typ.modifier == TypeModifier::Rigid {
types::walk_type(&self.subs.zonk(&arg_typ), &mut |typ: &RcType| {
if let Type::Variable(var) = &**typ {
return_variables.insert(var.id);
}
});
}
func_type = ret_typ;
}
let mut not_a_function_index = None;
let mut prev_arg_end = implicit_args.last().map_or(span, |arg| arg.span).end();
for arg in args.map(|arg| arg.borrow_mut()) {
let errors_before = self.errors.len();
let (arg_ty, ret_ty) = self.subsume_function(
prev_arg_end,
arg.span,
ArgType::Explicit,
func_type.clone(),
&mut |expr| implicit_args.as_owned().push(expr),
);
if errors_before != self.errors.len() {
self.errors.pop();
not_a_function_index = Some(arg);
break;
}
let arg_ty = self.typecheck(arg, ModType::wobbly(&arg_ty));
if arg_ty.modifier == TypeModifier::Rigid {
types::walk_type(&self.subs.zonk(&arg_ty), &mut |typ: &RcType| {
if let Type::Variable(var) = &**typ {
return_variables.insert(var.id);
}
});
}
func_type = ret_ty;
prev_arg_end = arg.span.end();
}
if let Some(arg) = not_a_function_index {
let span_start = arg.span.start();
let extra_args = Some(arg).into_iter().chain(args);
let mut span_end = BytePos::default();
let arg_types = extra_args
.map(|arg| {
span_end = arg.span.end();
self.infer_expr(arg.borrow_mut()).concrete
})
.collect::<Vec<_>>();
let expected = self.subs.function(arg_types, self.subs.new_var());
let span = Span::new(span_start, span_end);
attach_extra_argument_help(self, args_len, |self_| {
self_.subsumes(
span,
ErrorOrder::ExpectedActual,
&expected,
func_type.clone(),
)
});
func_type = expected;
}
let mut modifier = TypeModifier::Rigid;
types::FlagsVisitor(Flags::HAS_VARIABLES, |typ: &RcType| {
if modifier == TypeModifier::Rigid {
if let Type::Variable(var) = &**typ {
if !return_variables.contains(&var.id) {
modifier = TypeModifier::Wobbly;
}
}
}
})
.walk(&self.subs.zonk(&original_func_type));
Ok(ModType::new(modifier, func_type))
}
fn typecheck_lambda(
&mut self,
function_type: ModType,
before_args_pos: BytePos,
args_ref: &mut &'ast mut [Argument<SpannedIdent<Symbol>>],
body: &mut SpannedExpr<'ast, Symbol>,
) -> ModType {
debug!("Checking lambda {}", function_type);
debug!("Checking lambda {:#?}", self.environment.skolem_variables);
self.enter_scope();
let mut args = CowVec::Borrowed(*args_ref);
let mut arg_types = Vec::new();
let body_type = {
let mut return_type = function_type.clone();
let mut i = 0;
while i < args.len()
|| return_type
.as_function_with_type()
.map_or(false, |(arg_type, _, _)| arg_type == ArgType::Implicit)
{
let span = args
.get(i)
.map(|a| a.name.span)
.unwrap_or_else(|| pos::Span::new(before_args_pos, before_args_pos));
let (type_implicit, arg_type, ret_type) =
self.unify_function(span, return_type.concrete.clone());
match type_implicit {
ArgType::Implicit => {
let arg = match args.get(i).map(|t| t.arg_type) {
Some(ArgType::Implicit) => {
i += 1;
&mut args[i - 1].name.value
}
_ => {
let id = Symbol::from("__implicit_arg");
let pos = if i == 0 {
before_args_pos
} else {
args.get(i - 1)
.map(|arg| arg.name.span.end())
.unwrap_or(before_args_pos)
};
args.as_owned().insert(
i,
Argument::implicit(pos::spanned2(
pos,
pos,
TypedIdent {
typ: self.subs.bind_arc(&arg_type),
name: id.clone(),
},
)),
);
i += 1;
&mut args[i - 1].name.value
}
};
arg.typ = self.subs.bind_arc(&arg_type);
arg_types.push(arg_type.clone());
self.stack_var(arg.name.clone(), arg_type.clone());
}
ArgType::Explicit => match args.get_mut(i) {
Some(&mut Argument {
arg_type: ArgType::Implicit,
name: ref arg,
}) => {
i += 1;
self.error(
arg.span,
TypeError::Message(format!(
"Expected implicit argument but an explicit argument was specified"
)),
);
}
Some(&mut Argument {
arg_type: ArgType::Explicit,
name: ref mut arg,
}) => {
i += 1;
let arg = &mut arg.value;
arg.typ = self.subs.bind_arc(&arg_type);
arg_types.push(arg_type.clone());
self.stack_var(arg.name.clone(), arg_type);
}
_ => break,
},
ArgType::Constructor => unreachable!(),
}
return_type = ModType::new(function_type.modifier, ret_type);
}
return_type
};
if let CowVec::Owned(args) = args {
*args_ref = self.ast_arena.alloc_extend(args);
}
let body_type = self.typecheck(body, body_type.as_ref());
self.exit_scope();
let f = self.subs.function(arg_types, body_type.concrete);
let done = self.with_forall(&function_type, ModType::new(body_type.modifier, f));
debug!("Checked lambda {}", done);
done
}
fn typecheck_let_pattern(
&mut self,
pattern: &mut SpannedPattern<Symbol>,
match_type: RcType,
) -> RcType {
match pattern.value {
Pattern::Constructor(ref id, _) | Pattern::Ident(ref id)
if id.name.declared_name().starts_with(char::is_uppercase) =>
{
self.error(
pattern.span,
TypeError::Message(format!("Unexpected type constructor `{}`", id.name)),
)
}
_ => self.typecheck_pattern(pattern, ModType::wobbly(match_type.clone()), match_type),
}
}
fn typecheck_pattern(
&mut self,
pattern: &mut SpannedPattern<Symbol>,
mut match_type: ModType,
partial_match_type: RcType,
) -> RcType {
let span = pattern.span;
match &mut pattern.value {
Pattern::As(id, pat) => {
self.stack_var(id.value.clone(), partial_match_type.clone());
self.typecheck_pattern(pat, match_type.clone(), partial_match_type.clone());
partial_match_type
}
Pattern::Constructor(id, args) => {
match_type.concrete = self.subs.real(&match_type).clone();
match_type.concrete = self.instantiate_generics(&match_type);
match_type.concrete = self.subs.zonk(&match_type);
let ctor_type = self.find_at(span, &id.name);
id.typ = self.subs.bind_arc(&ctor_type);
debug!("Wobbly check {:?}: {}", match_type.modifier, match_type);
let wobbly = match_type.modifier == TypeModifier::Wobbly;
let ctor_type = if wobbly {
self.instantiate_generics(&ctor_type)
} else {
self.skolemize(&ctor_type)
};
let return_type = ctor_return_type(&ctor_type);
if wobbly {
self.subsumes(
span,
ErrorOrder::ExpectedActual,
&return_type,
match_type.concrete,
);
} else {
self.refines(
span,
ErrorOrder::ExpectedActual,
&return_type,
match_type.concrete,
);
}
match self.typecheck_pattern_rec(args, &ctor_type) {
Ok(return_type) => return_type,
Err(err) => self.error(span, err),
}
}
Pattern::Record {
typ: curr_typ,
fields,
implicit_import,
} => {
let uninstantiated_match_type = match_type.clone();
match_type.concrete = self.instantiate_generics(&match_type);
*curr_typ = self.subs.bind_arc(&match_type);
let mut pattern_fields = Vec::with_capacity(fields.len());
let mut duplicated_fields = FnvSet::default();
{
let all_fields = fields.iter().map(|field| match field {
PatternField::Type { name } | PatternField::Value { name, .. } => name,
});
for field in all_fields {
if self.error_on_duplicated_field(&mut duplicated_fields, &field) {
pattern_fields.push(field.value.clone());
}
}
}
let record_match_type = self.remove_alias(match_type.concrete.clone());
let mut missing_fields_from_match_type = Vec::new();
for (name, value) in ast::pattern_values_mut(fields) {
let name = &name.value;
let field_type = record_match_type
.row_iter()
.find(|f| f.name.name_eq(name))
.map(|f| f.typ.clone())
.unwrap_or_else(|| {
let typ = self.subs.new_var();
missing_fields_from_match_type.push(Field {
name: name.clone(),
typ: typ.clone(),
});
typ
});
match value {
Some(pattern) => {
self.typecheck_pattern(
pattern,
ModType::new(match_type.modifier, field_type.clone()),
field_type,
);
}
None => {
self.stack_var(name.clone(), field_type);
}
}
}
for name in ast::pattern_types(fields) {
let span = name.span;
let name = name.value.clone();
let field_type = record_match_type
.type_field_iter()
.find(|field| field.name.name_eq(&name));
let alias;
let alias = match field_type {
Some(field_type) => {
if let Some(meta) = self.implicit_resolver.metadata.remove(&name) {
self.implicit_resolver
.metadata
.insert(field_type.typ.name.clone(), meta);
}
&field_type.typ
}
None => {
self.error(
span,
TypeError::UndefinedField(
match_type.concrete.clone(),
name.clone(),
),
);
let hole = self.subs.error();
alias = self.new_alias(name.clone(), Vec::new(), hole);
&alias
}
};
self.stack_type(name, &alias);
}
if !missing_fields_from_match_type.is_empty() {
let expected = self.subs.poly_record(
vec![],
missing_fields_from_match_type,
self.subs.new_var(),
);
self.unify_span(pattern.span, &expected, match_type.concrete.clone());
}
if let Some(ref implicit_import) = *implicit_import {
self.implicit_resolver.add_implicits_of_record(
&self.subs,
&implicit_import.value,
&uninstantiated_match_type,
);
}
match_type.concrete
}
Pattern::Tuple { typ, elems } => {
let tuple_type = {
let subs = &mut self.subs;
(&*subs).tuple(&mut self.symbols, (0..elems.len()).map(|_| subs.new_var()))
};
let new_type = self.unify_span(span, &tuple_type, match_type.concrete);
*typ = self.subs.bind_arc(&new_type);
for (elem, field) in elems.iter_mut().zip(tuple_type.row_iter()) {
self.typecheck_pattern(
elem,
ModType::new(match_type.modifier, field.typ.clone()),
field.typ.clone(),
);
}
tuple_type
}
Pattern::Ident(id) => {
self.stack_var(id.name.clone(), partial_match_type.clone());
id.typ = self.subs.bind_arc(&partial_match_type);
partial_match_type
}
Pattern::Literal(l) => {
let typ = l.env_type_of(&self.environment);
let typ = self.translate_arc_type(&typ);
self.unify_span(span, &match_type, typ);
match_type.concrete
}
Pattern::Error => self.subs.new_var(),
}
}
fn typecheck_pattern_rec(
&mut self,
args: &mut [SpannedPattern<Symbol>],
typ: &RcType,
) -> TcResult<RcType> {
let pattern_args = args.len();
let mut pattern_iter = args.iter_mut();
let mut type_iter = typ.arg_iter();
loop {
match (pattern_iter.next(), type_iter.next()) {
(Some(arg_pattern), Some(arg)) => {
self.typecheck_pattern(arg_pattern, ModType::wobbly(arg.clone()), arg.clone());
}
(None, Some(_)) | (Some(_), None) => {
return Err(TypeError::PatternError {
constructor_type: typ.clone(),
pattern_args,
})
}
(None, None) => break,
}
}
Ok(typ.clone())
}
fn translate_projected_type(&mut self, id: &[Symbol]) -> TcResult<RcType> {
translate_projected_type(&self.environment, &mut self.symbols, &mut &self.subs, id)
}
fn translate_arc_type(&mut self, arc_type: &ArcType) -> RcType {
arc_type.clone()
}
fn translate_rc_type(&mut self, rc_type: &RcType) -> ArcType {
rc_type.clone()
}
fn translate_ast_type(&mut self, ast_type: &AstType<Symbol>) -> RcType {
use crate::base::pos::HasSpan;
match **ast_type {
Type::Alias(ref alias) => match **alias.unresolved_type() {
Type::Generic(ref gen) if gen.id == alias.name => self.ident(KindedIdent {
name: alias.name.clone(),
typ: alias.kind(&self.kind_cache).into_owned(),
}),
_ => types::translate_type_with(self, ast_type, |self_, typ| {
self_.translate_ast_type(typ)
}),
},
Type::ExtendTypeRow {
ref types,
ref rest,
} => {
let types = types
.iter()
.map(|field| Field {
name: field.name.value.clone(),
typ: if let Type::Hole = **field.typ.unresolved_type() {
self.find_type_info_at(
field.typ.unresolved_type().span(),
&field.name.value,
)
} else {
let alias_data =
types::translate_alias(self, &field.typ, |self_, typ| {
self_.translate_ast_type(typ)
});
self.new_data_alias(alias_data)
},
})
.collect();
let rest = self.translate_ast_type(rest);
self.extend_type_row(types, rest)
}
Type::Projection(ref ids) => match self.translate_projected_type(ids) {
Ok(typ) => typ,
Err(err) => self.error(ast_type.span(), err),
},
_ => types::translate_type_with(self, ast_type, |self_, typ| {
self_.translate_ast_type(typ)
}),
}
}
fn typecheck_bindings(
&mut self,
top_level: bool,
mut expr: &mut SpannedExpr<'ast, Symbol>,
expected_type: Option<ModTypeRef>,
) -> ModType {
let mut scope_count = 0;
let level = self.subs.var_id();
loop {
match expr.value {
Expr::LetBindings(ref mut bindings, ref mut body) => {
self.typecheck_let_bindings(bindings);
scope_count += 1;
if top_level {
self.generalize_and_clear_subs(level, bindings);
}
expr = body
}
Expr::TypeBindings(ref mut bindings, ref mut body) => {
self.typecheck_type_bindings(bindings, body);
scope_count += 1;
expr = body;
}
_ => {
let typ = self.typecheck_opt(expr, expected_type);
for _ in 0..scope_count {
self.exit_scope();
}
return typ;
}
}
}
}
fn resolve_type_signature(
&mut self,
mut signature: Option<&mut AstType<'_, Symbol>>,
) -> ModType {
let mut mod_type = if let Some(ref mut typ) = signature {
self.kindcheck(typ);
let rc_type = self.translate_ast_type(typ);
ModType::rigid(rc_type)
} else {
ModType::wobbly(self.subs.hole())
};
if let Some(typ) = self.create_unifiable_signature(&mod_type) {
mod_type.concrete = typ;
}
mod_type
}
fn typecheck_let_bindings(&mut self, bindings: &mut ValueBindings<'ast, Symbol>) {
self.enter_scope();
self.environment.skolem_variables.enter_scope();
self.environment.type_variables.enter_scope();
let level = self.subs.var_id();
let is_recursive = bindings.is_recursive();
let mut resolved_types = AppVec::new();
if is_recursive {
for (i, bind) in bindings.iter_mut().enumerate() {
let typ = {
resolved_types.push(self.resolve_type_signature(bind.typ.as_mut()));
resolved_types[i].concrete.clone()
};
self.typecheck_let_pattern(&mut bind.name, typ);
}
}
let mut types = Vec::new();
for (i, bind) in bindings.iter_mut().enumerate() {
let typ = if !is_recursive {
if let Some(ref mut typ) = bind.typ {
self.kindcheck(typ);
let rc_type = self.translate_ast_type(typ);
resolved_types.push(ModType::rigid(rc_type));
} else {
resolved_types.push(ModType::wobbly(self.subs.hole()));
}
let typ = self.create_unifiable_signature(&resolved_types[i]);
if let Some(typ) = typ {
resolved_types[i].concrete = typ;
}
let typ = resolved_types[i].as_ref();
self.skolemize_in(bind.expr.span, typ, |self_, typ| {
self_
.environment
.type_variables
.extend(self_.named_variables.drain());
self_.typecheck_lambda(
typ,
bind.name.span.end(),
&mut bind.args,
&mut bind.expr,
)
})
} else {
let typ = match bind.name.value {
Pattern::Ident(ref id) => {
let mut type_cache = &self.subs;
self.environment
.stack
.get(&id.name)
.map_or_else(|| ModType::wobbly(type_cache.error()), |b| b.typ.clone())
}
_ => ModType::wobbly(self.subs.error()),
};
self.skolemize_in_no_scope(bind.expr.span, typ.as_ref(), |self_, function_type| {
self_
.environment
.type_variables
.extend(self_.named_variables.drain());
self_.typecheck_lambda(
function_type,
bind.name.span.end(),
&mut bind.args,
&mut bind.expr,
)
})
};
debug!("let {:?} : {}", bind.name, typ);
if !is_recursive {
let resolved_type = &mut resolved_types[i].concrete;
bind.resolved_type = self.subs.bind_arc(&resolved_type);
debug!("Generalize at {} = {}", level, resolved_type);
self.generalize_binding(level, resolved_type, bind);
debug!("Generalized mid {}", resolved_type);
self.typecheck_let_pattern(&mut bind.name, resolved_type.clone());
debug!("Generalized to {}", bind.resolved_type);
self.finish_pattern(level, &mut bind.name, &resolved_type);
} else {
types.push(typ);
}
}
if is_recursive {
let hole = self.subs.hole();
{
let mut generalizer =
TypeGeneralizer::new(level, self, &hole, bindings[0].name.span);
debug!("Generalize recursive at {}", level);
for (bind, resolved_type) in bindings.iter_mut().zip(&mut resolved_types) {
bind.resolved_type = generalizer.tc.subs.bind_arc(&resolved_type);
debug!(
"Generalize {}: {}",
match bind.name.value {
ast::Pattern::Ident(ref id) => id.name.declared_name(),
_ => "",
},
resolved_type
);
generalize_binding(&mut generalizer, resolved_type, bind);
debug!("Generalize mid {}", resolved_type);
generalizer
.tc
.finish_pattern(level, &mut bind.name, &resolved_type);
debug!("Generalized to {}", resolved_type);
}
}
debug!("End generalize recursive");
}
debug!("Typecheck `in`");
self.environment.type_variables.exit_scope();
self.environment.skolem_variables.exit_scope();
}
fn typecheck_type_bindings(
&mut self,
bindings: &mut [TypeBinding<Symbol>],
expr: &SpannedExpr<'ast, Symbol>,
) {
self.enter_scope();
for bind in bindings.iter_mut() {
self.environment.skolem_variables.enter_scope();
self.environment.type_variables.enter_scope();
{
let mut type_cache = &self.subs;
for (k, v) in bind
.alias
.value
.params()
.iter()
.map(|param| (param.id.clone(), type_cache.hole()))
{
self.environment
.skolem_variables
.insert(k.clone(), v.clone());
self.environment.type_variables.insert(k, v);
}
}
self.check_type_binding(&bind.alias.value.name, bind.alias.value.unresolved_type());
self.environment.type_variables.exit_scope();
self.environment.skolem_variables.exit_scope();
}
{
let mut check = KindCheck::new(
&self.environment,
&mut self.symbols,
self.kind_cache.clone(),
);
for bind in &mut *bindings {
let mut id_kind = check.type_kind();
for generic in bind.alias.value.params_mut().iter_mut().rev() {
check.instantiate_kinds(&mut generic.kind);
id_kind = Kind::function(generic.kind.clone(), id_kind);
}
check.add_local(bind.alias.value.name.clone(), id_kind);
}
for bind in &mut *bindings {
check.enter_scope_with(
bind.alias
.value
.params()
.iter()
.map(|g| (g.id.clone(), g.kind.clone())),
);
let typ = bind
.alias
.value
.unresolved_type_mut()
.remove_single_forall();
if let Err(errors) = check.kindcheck_type(typ) {
self.errors.extend(
errors
.into_iter()
.map(|err| pos::spanned(err.span, TypeError::from(err.value).into())),
);
}
check.exit_scope();
}
for bind in &mut *bindings {
{
let typ = bind.alias.value.unresolved_type_mut();
check.finalize_type(typ);
}
for arg in bind.alias.value.params_mut() {
*arg = check.finalize_generic(arg);
}
}
}
let mut resolved_aliases = Vec::new();
for bind in &mut *bindings {
self.environment.skolem_variables.enter_scope();
self.environment.type_variables.enter_scope();
let mut alias = types::translate_alias(self, &bind.alias.value, |self_, typ| {
self_.translate_ast_type(typ)
});
alias.is_implicit = bind.metadata.get_attribute("implicit").is_some();
let replacement = self.create_unifiable_signature_with(
alias
.params()
.iter()
.map(|param| (param.id.clone(), alias.unresolved_type().clone())),
alias.unresolved_type(),
);
if let Some(typ) = replacement {
*alias.unresolved_type_mut() = typ;
}
resolved_aliases.push(alias);
self.environment.type_variables.exit_scope();
self.environment.skolem_variables.exit_scope();
}
let arc_alias_group = Alias::group(
resolved_aliases
.iter()
.map(|a| types::translate_alias(self, &a, |self_, t| self_.translate_rc_type(t)))
.collect(),
);
let alias_group = self.subs.alias_group(resolved_aliases);
for (bind, alias) in bindings.iter_mut().zip(arc_alias_group) {
bind.finalized_alias = Some(alias);
}
for (bind, alias) in bindings.iter().zip(&alias_group) {
if self.environment.stack_types.get(&bind.name.value).is_some() {
self.errors.push(Spanned {
span: expr_check_span(expr),
value: TypeError::DuplicateTypeDefinition(bind.name.value.clone()).into(),
});
} else {
self.stack_type(bind.name.value.clone(), alias);
}
}
}
fn kindcheck(&mut self, typ: &mut AstType<Symbol>) {
let result = {
let mut check = KindCheck::new(
&self.environment,
&mut self.symbols,
self.kind_cache.clone(),
);
check.kindcheck_type(typ)
};
if let Err(errors) = result {
self.errors.extend(
errors
.into_iter()
.map(|err| pos::spanned(err.span, TypeError::from(err.value).into())),
);
}
}
fn check_type_binding(&mut self, alias_name: &Symbol, typ: &AstType<'_, Symbol>) {
use crate::base::pos::HasSpan;
match &**typ {
Type::Generic(id) => {
if !self.environment.type_variables.contains_key(&id.id) {
info!("Undefined type variable {}", id.id);
self.error(typ.span(), TypeError::UndefinedVariable(id.id.clone()));
}
}
Type::Variant(row) => {
for field in types::row_iter(row) {
let spine = ctor_return_type(&field.typ).spine();
match &**spine {
Type::Ident(id) if id.name == *alias_name => (),
Type::Opaque => (),
_ => {
let actual = self.translate_ast_type(spine);
self.error(
spine.span(),
TypeError::TypeConstructorReturnsWrongType {
expected: alias_name.clone(),
actual,
},
);
}
}
self.check_type_binding(alias_name, &field.typ);
}
}
Type::Record(_) => {
}
_ => {
if let Type::Forall(params, ..) = &**typ {
let mut type_cache = &self.subs;
self.environment
.type_variables
.extend(params.iter().map(|gen| (gen.id.clone(), type_cache.hole())));
}
types::walk_type_(
typ,
&mut types::ControlVisitation(|typ: &AstType<'_, _>| {
self.check_type_binding(alias_name, typ)
}),
);
}
}
}
fn update_var(&mut self, id: &Symbol, typ: &RcType) {
if let Some(bind) = self.environment.stack.get_mut(id) {
if let Type::Variable(_) = **bind.typ {
self.implicit_resolver.on_stack_var(&self.subs, id, typ);
}
bind.typ.concrete = typ.clone();
}
let id = self.symbols.simple_symbol(id.declared_name());
if let Some(bind) = self.environment.stack.get_mut(&id) {
bind.typ.concrete = typ.clone();
}
}
fn finish_pattern(
&mut self,
level: u32,
pattern: &mut SpannedPattern<Symbol>,
final_type: &RcType,
) {
match pattern.value {
Pattern::As(ref mut id, ref mut pat) => {
self.finish_pattern(level, pat, &final_type);
self.update_var(&id.value, &final_type);
debug!("{}: {}", self.symbols.string(&id.value), final_type);
}
Pattern::Ident(ref mut id) => {
id.typ = self.subs.bind_arc(&final_type);
self.update_var(&id.name, &final_type);
debug!("{}: {}", self.symbols.string(&id.name), id.typ);
}
Pattern::Record {
ref mut typ,
ref mut fields,
..
} => {
*typ = self.subs.bind_arc(final_type);
let mut typ = final_type.clone();
debug!("{{ .. }}: {}", final_type);
self.generalize_type(level, &mut typ, pattern.span);
let typ = self.instantiate_generics(&typ);
let record_type = self.remove_alias(typ.clone());
for (field_name, binding, field_type) in with_pattern_types(fields, &record_type) {
let mut field_type = field_type.cloned().unwrap_or_else(|| self.subs.error());
self.generalize_type(level, &mut field_type, field_name.span);
match *binding {
Some(ref mut pat) => {
self.finish_pattern(level, pat, &field_type);
}
None => {
self.update_var(&field_name.value, &field_type);
debug!("{}: {}", field_name.value, field_type);
}
}
}
}
Pattern::Tuple {
ref mut typ,
ref mut elems,
} => {
*typ = self.subs.bind_arc(final_type);
let typ = final_type.clone();
let typ = self.instantiate_generics(&typ);
for (elem, field) in elems.iter_mut().zip(typ.row_iter()) {
let mut field_type = field.typ.clone();
self.generalize_type(level, &mut field_type, elem.span);
self.finish_pattern(level, elem, &field_type);
}
}
Pattern::Constructor(ref mut id, ref mut args) => {
debug!("{}: {}", self.symbols.string(&id.name), final_type);
let len = args.len();
let iter = args.iter_mut().zip(
function_arg_iter(self, final_type.clone())
.map(|t| t.1)
.take(len)
.collect::<Vec<_>>(),
);
for (arg, arg_type) in iter {
self.finish_pattern(level, arg, &arg_type);
}
}
Pattern::Literal(_) | Pattern::Error => (),
}
}
fn generalize_and_clear_subs(&mut self, level: u32, binds: &mut ValueBindings<Symbol>) {
debug!("Clearing from: {}", level);
{
let hole = self.subs.hole();
let mut generalizer = TypeGeneralizer::new(level, self, &hole, binds[0].span());
for bind in &mut *binds {
generalize::ReplaceVisitor {
generalizer: &mut generalizer,
}
.visit_pattern(&mut bind.name);
generalizer.generalize_variables(
&mut bind.args.iter_mut().map(|arg| &mut arg.name),
&mut bind.expr,
);
generalizer.generalize_type_mut(&mut bind.resolved_type);
}
}
let mut errors = mem::replace(&mut self.errors, Default::default());
self.generalize_type_errors(&mut errors);
self.errors = errors;
self.named_variables.clear();
self.implicit_resolver.implicit_vars.clear();
self.subs.clear_from(level);
}
fn generalize_type(&mut self, level: u32, typ: &mut RcType, span: Span<BytePos>) {
debug!("Start generalize {:#?}", self.environment.skolem_variables);
debug!("Start generalize {} >> {}", level, typ);
let mut generalizer = TypeGeneralizer::new(level, self, typ, span);
generalizer.generalize_type_top(typ);
}
fn generalize_type_without_forall(
&mut self,
level: u32,
typ: &mut RcType,
span: Span<BytePos>,
) {
self.environment.skolem_variables.enter_scope();
let mut generalizer = TypeGeneralizer::new(level, self, typ, span);
let result_type = generalizer.generalize_type(typ);
generalizer.environment.skolem_variables.exit_scope();
if let Some(finished) = result_type {
*typ = finished;
}
}
fn create_unifiable_signature(&mut self, typ: &RcType) -> Option<RcType> {
self.create_unifiable_signature_with(None, typ)
}
fn create_unifiable_signature_with(
&mut self,
scope: impl IntoIterator<Item = (Symbol, RcType)>,
typ: &RcType,
) -> Option<RcType> {
debug!("Creating signature: {:#?}", typ);
for (k, v) in scope {
self.environment
.skolem_variables
.insert(k.clone(), v.clone());
self.environment.type_variables.insert(k, v);
}
let opt = self.create_unifiable_signature2(typ);
debug!("Created signature: {:#?}", opt.as_ref().unwrap_or(typ));
opt
}
fn create_unifiable_signature2(&mut self, typ: &RcType) -> Option<RcType> {
debug!("Signature scope: {}", typ);
self.unbound_variables.enter_scope();
let result_type = self.create_unifiable_signature_(typ);
let mut params = self
.unbound_variables
.exit_scope()
.map(|(id, kind)| Generic::new(id, kind))
.collect::<Vec<_>>();
params.retain(|generic| !self.unbound_variables.contains_key(&generic.id));
if params.is_empty() {
result_type
} else {
let result = self.intern(Type::Forall(
params,
result_type.unwrap_or_else(|| typ.clone()),
));
debug!("Signature scope END: {}", result);
Some(result)
}
}
fn create_unifiable_signature_(&mut self, typ: &RcType) -> Option<RcType> {
match **typ {
Type::Ident(ref id) => {
self.environment
.find_type_info(&id.name)
.map(|alias| alias.clone().into_type())
}
Type::Alias(ref alias) => {
self.environment
.find_type_info(&alias.name)
.map(|alias| alias.clone().into_type())
}
Type::Variant(ref row) => {
let replacement = types::visit_type_opt(
row,
&mut types::InternerVisitor::control(self, |self_: &mut Self, typ: &RcType| {
self_.create_unifiable_signature_(typ)
}),
);
replacement
.clone()
.map(|row| self.intern(Type::Variant(row)))
}
Type::Hole => Some(self.subs.new_var()),
Type::ExtendRow {
ref fields,
ref rest,
} => {
let new_fields = types::walk_move_types(&mut (), fields, |_, field| {
self.create_unifiable_signature2(&field.typ)
.map(|typ| Field::new(field.name.clone(), typ))
});
let new_rest = self.create_unifiable_signature_(rest);
merge::merge(fields, new_fields, rest, new_rest, |fields, rest| {
self.intern(Type::ExtendRow { fields, rest })
})
}
Type::ExtendTypeRow {
ref types,
ref rest,
} => {
let new_types = types::walk_move_types(&mut (), types, |_, field| {
let typ = self
.create_unifiable_signature_with(
field.typ.params().iter().map(|param| {
(param.id.clone(), field.typ.unresolved_type().clone())
}),
field.typ.unresolved_type(),
)
.unwrap_or_else(|| field.typ.unresolved_type().clone());
Some(Field::new(
field.name.clone(),
self.new_alias(field.typ.name.clone(), field.typ.params().to_owned(), typ),
))
});
let new_rest = self.create_unifiable_signature_(rest);
merge::merge(types, new_types, rest, new_rest, |types, rest| {
self.intern(Type::ExtendTypeRow { types, rest })
})
}
Type::Forall(ref params, ref typ) => {
self.environment.type_variables.enter_scope();
let mut subs = &self.subs;
self.environment
.type_variables
.extend(params.iter().map(|param| (param.id.clone(), subs.hole())));
let result = self.create_unifiable_signature_(typ);
self.environment.type_variables.exit_scope();
result.map(|typ| self.intern(Type::Forall(params.clone(), typ)))
}
Type::Generic(ref generic) => {
if let Some(typ) = self.environment.type_variables.get(&generic.id) {
match **typ {
Type::Skolem(_) => Some(typ.clone()),
_ => None,
}
} else {
self.unbound_variables
.entry(generic.id.clone())
.or_insert_with(|| generic.kind.clone());
None
}
}
_ => types::walk_move_type_opt(
typ,
&mut types::InternerVisitor::control(self, |self_: &mut Self, typ: &RcType| {
self_.create_unifiable_signature_(typ)
}),
),
}
}
fn subsumes_expr(
&mut self,
span: Span<BytePos>,
l: &RcType,
r: RcType,
expr: &mut SpannedExpr<'ast, Symbol>,
) -> RcType {
let mut implicit_args = match &mut expr.value {
Expr::App { implicit_args, .. } => implicit_args.iter_mut().map(mem::take).collect(),
_ => Vec::new(),
};
let new = self.subsumes_implicit(
span,
ErrorOrder::ExpectedActual,
&r,
l.clone(),
&mut |arg| {
implicit_args.push(pos::spanned(expr.span, arg));
},
);
match &mut expr.value {
Expr::App {
implicit_args: current,
..
} => *current = self.ast_arena.alloc_extend(implicit_args),
_ => {
if !implicit_args.is_empty() {
let func = mem::take(&mut expr.value);
expr.value = Expr::App {
func: self.ast_arena.alloc(pos::spanned(expr.span, func)),
implicit_args: self.ast_arena.alloc_extend(implicit_args),
args: &mut [],
}
}
}
}
if let Type::Forall(..) = *new {
let temp = mem::replace(expr, Default::default());
*expr = Expr::annotated(self.ast_arena, temp, self.subs.bind_arc(&new));
}
new
}
fn subsumes_implicit(
&mut self,
span: Span<BytePos>,
error_order: ErrorOrder,
expected: &RcType,
actual: RcType,
receiver: &mut dyn FnMut(Expr<'ast, Symbol>),
) -> RcType {
debug!("Subsume expr {} <=> {}", expected, actual);
self.environment.skolem_variables.enter_scope();
let state = unify_type::State::new(&self.environment, &self.subs);
let implicit_resolver = &mut self.implicit_resolver;
let mut receiver = |implicit_type: &RcType| {
let name = implicit_resolver.make_implicit_ident(implicit_type);
receiver(Expr::Ident(TypedIdent {
name,
typ: implicit_type.clone(),
}));
};
let typ = match unify_type::subsumes_implicit(
&self.subs,
state,
&expected,
&actual,
&mut receiver,
) {
Ok(typ) => typ,
Err((typ, mut errors)) => {
let expected = expected.clone();
debug!(
"Error '{}' between:\n>> {}\n>> {}",
errors, expected, actual
);
let err = match error_order {
ErrorOrder::ExpectedActual => {
TypeError::Unification(expected, actual, errors.into())
}
ErrorOrder::ActualExpected => {
for err in &mut errors {
match err {
unify::Error::TypeMismatch(l, r) => mem::swap(l, r),
unify::Error::Other(unify_type::TypeError::FieldMismatch(l, r)) => {
mem::swap(l, r)
}
_ => (),
}
}
TypeError::Unification(actual, expected, errors.into())
}
};
self.errors.push(Spanned {
span: span,
value: err.into(),
});
typ
}
};
self.environment.skolem_variables.exit_scope();
typ
}
fn subsumes(
&mut self,
span: Span<BytePos>,
error_order: ErrorOrder,
expected: &RcType,
actual: RcType,
) -> RcType {
debug!("Merge {} : {}", expected, actual);
let state = unify_type::State::new(&self.environment, &self.subs);
match unify_type::subsumes(&self.subs, state, &expected, &actual) {
Ok(typ) => typ,
Err((typ, mut errors)) => {
let expected = expected.clone();
debug!(
"Error '{}' between:\n>> {}\n>> {}",
errors, expected, actual
);
let err = match error_order {
ErrorOrder::ExpectedActual => {
TypeError::Unification(expected, actual, errors.into())
}
ErrorOrder::ActualExpected => {
for err in &mut errors {
match err {
unify::Error::TypeMismatch(l, r) => mem::swap(l, r),
unify::Error::Other(unify_type::TypeError::FieldMismatch(l, r)) => {
mem::swap(l, r)
}
_ => (),
}
}
TypeError::Unification(actual, expected, errors.into())
}
};
self.errors.push(Spanned {
span: span,
value: err.into(),
});
typ
}
}
}
fn refines(
&mut self,
span: Span<BytePos>,
error_order: ErrorOrder,
expected: &RcType,
actual: RcType,
) -> RcType {
debug!("Refine {} : {}", expected, actual);
types::walk_type(&actual, &mut |typ: &RcType| {
if let Type::Skolem(skolem) = &**self.subs.real(typ) {
self.refined_variables.entry(skolem.id).or_insert(());
}
});
let state = unify_type::State::with_refinement(&self.environment, &self.subs, true);
match unify_type::subsumes(&self.subs, state, &expected, &actual) {
Ok(typ) => typ,
Err((typ, mut errors)) => {
let expected = expected.clone();
debug!(
"Error '{}' between:\n>> {}\n>> {}",
errors, expected, actual
);
let err = match error_order {
ErrorOrder::ExpectedActual => {
TypeError::Unification(expected, actual, errors.into())
}
ErrorOrder::ActualExpected => {
for err in &mut errors {
match err {
unify::Error::TypeMismatch(l, r) => mem::swap(l, r),
unify::Error::Other(unify_type::TypeError::FieldMismatch(l, r)) => {
mem::swap(l, r)
}
_ => (),
}
}
TypeError::Unification(actual, expected, errors.into())
}
};
self.errors.push(Spanned {
span: span,
value: err.into(),
});
typ
}
}
}
fn instantiate_sigma(
&mut self,
span: Span<BytePos>,
typ: &RcType,
expected_type: &mut Option<&RcType>,
) -> (Vec<SpannedExpr<'ast, Symbol>>, RcType) {
match expected_type.take() {
Some(expected_type) => {
debug!("Instantiate sigma: {} <> {}", expected_type, typ);
let mut implicit_args = Vec::new();
let t = self.subsumes_implicit(
span,
ErrorOrder::ExpectedActual,
&expected_type,
typ.clone(),
&mut |implicit_arg| {
implicit_args.push(pos::spanned(span, implicit_arg));
},
);
(implicit_args, t)
}
None => {
debug!("Instantiate sigma: {}", typ);
(Vec::new(), self.instantiate_generics(typ))
}
}
}
fn subsume_function(
&mut self,
prev_arg_end: BytePos,
span: Span<BytePos>,
arg_type: ArgType,
actual: RcType,
implicit_args: &mut dyn FnMut(SpannedExpr<'ast, Symbol>),
) -> (RcType, RcType) {
let (_, a, r) = self.merge_function(Some(arg_type), actual, &mut |self_, f, actual| {
self_.subsumes_implicit(
span,
ErrorOrder::ExpectedActual,
&f,
actual,
&mut |implicit_arg| {
implicit_args(pos::spanned2(prev_arg_end, span.start(), implicit_arg))
},
);
});
(a, r)
}
fn unify_function(&mut self, span: Span<BytePos>, actual: RcType) -> (ArgType, RcType, RcType) {
self.merge_function(None, actual, &mut |self_, f, actual| {
self_.unify_span(span, &f, actual);
})
}
fn merge_function(
&mut self,
function_arg_type: Option<ArgType>,
actual: RcType,
merge_fn: &mut dyn FnMut(&mut Self, &RcType, RcType),
) -> (ArgType, RcType, RcType) {
let actual = self.remove_aliases(actual);
match actual.as_function_with_type() {
Some((found_arg_type, arg, ret))
if function_arg_type == Some(found_arg_type) || function_arg_type == None =>
{
return (found_arg_type, arg.clone(), ret.clone());
}
_ => (),
}
let arg = self.subs.new_var();
let ret = self.subs.new_var();
let arg_type = function_arg_type.unwrap_or(ArgType::Explicit);
let f = self
.subs
.function_type(arg_type, Some(arg.clone()), ret.clone());
merge_fn(self, &f, actual);
(arg_type, arg, ret)
}
fn unify_span(&mut self, span: Span<BytePos>, expected: &RcType, actual: RcType) -> RcType {
match self.unify(expected, actual) {
Ok(typ) => typ,
Err(err) => {
self.errors.push(Spanned {
span: span,
value: err.into(),
});
self.subs.error()
}
}
}
fn unify(&self, expected: &RcType, actual: RcType) -> TcResult<RcType> {
debug!("Unify start {} <=> {}", expected, actual);
let state = unify_type::State::new(&self.environment, &self.subs);
match unify::unify(&self.subs, state, expected, &actual) {
Ok(typ) => Ok(typ),
Err(errors) => {
debug!(
"Error '{:?}' between:\n>> {}\n>> {}",
errors, expected, actual
);
Err(TypeError::Unification(
expected.clone(),
actual,
errors.into(),
))
}
}
}
fn remove_alias(&self, typ: RcType) -> RcType {
resolve::remove_alias(&self.environment, &mut &self.subs, &typ)
.unwrap_or(None)
.unwrap_or(typ)
}
fn remove_aliases(&self, typ: RcType) -> RcType {
resolve::remove_aliases(&self.environment, &mut &self.subs, typ)
}
fn with_forall(&mut self, from: &RcType, to: ModType) -> ModType {
let mut params = Vec::new();
for param in from.forall_params() {
params.push(param.clone());
}
ModType::new(to.modifier, self.forall(params, to.concrete))
}
fn skolemize_in(
&mut self,
span: Span<BytePos>,
original_type: ModTypeRef,
f: impl FnOnce(&mut Self, ModType) -> ModType,
) -> ModType {
self.environment.skolem_variables.enter_scope();
self.environment.type_variables.enter_scope();
let t = self.skolemize_in_no_scope(span, original_type, f);
self.environment.type_variables.exit_scope();
self.environment.skolem_variables.exit_scope();
t
}
fn skolemize_in_no_scope(
&mut self,
span: Span<BytePos>,
original_type: ModTypeRef,
f: impl FnOnce(&mut Self, ModType) -> ModType,
) -> ModType {
let skolemized = self.skolemize(&original_type);
let new_type = f(self, ModType::new(original_type.modifier, skolemized));
let original_type = self.subs.zonk(&original_type);
types::FlagsVisitor(Flags::HAS_SKOLEMS, |typ: &RcType| {
if let Type::Skolem(skolem) = &**typ {
if !self.environment.skolem_variables.contains_key(&skolem.name) {
self.error(
span,
TypeError::Message(format!(
"Skolem variable `{}` would escape as it is not bound in `{}`",
skolem.name, original_type
)),
);
}
}
})
.walk(&original_type);
self.with_forall(&original_type, new_type)
}
fn skolemize(&mut self, typ: &RcType) -> RcType {
self.named_variables.clear();
self.named_variables.extend(
self.environment
.skolem_variables
.iter()
.map(|(k, v)| (k.clone(), v.clone())),
);
let new_type = typ.skolemize(&mut &self.subs, &mut self.named_variables);
for (id, typ) in self.named_variables.iter() {
match self.environment.skolem_variables.entry(id.clone()) {
scoped_map::Entry::Vacant(e) => {
e.insert(typ.clone());
}
scoped_map::Entry::Occupied(mut e) => {
if e.get() != typ {
e.insert(typ.clone());
}
}
}
}
new_type
}
pub(crate) fn instantiate_generics(&mut self, typ: &RcType) -> RcType {
self.named_variables.clear();
typ.instantiate_generics(&mut &self.subs, &mut self.named_variables)
}
fn error_on_duplicated_field<'s>(
&mut self,
duplicated_fields: &mut FnvSet<&'s str>,
new_name: &'s Spanned<Symbol, BytePos>,
) -> bool {
let span = new_name.span;
duplicated_fields
.replace(new_name.value.definition_name())
.map_or(true, |name| {
self.errors.push(Spanned {
span: span,
value: TypeError::DuplicateField(self.symbols.symbols().simple_symbol(name))
.into(),
});
false
})
}
fn check_macro(&mut self, expr: &mut SpannedExpr<'ast, Symbol>) -> Option<TcResult<ModType>> {
let (replacement, typ) = match expr.value {
Expr::App {
ref mut func,
ref mut args,
..
} => match func.value {
Expr::Ident(ref id) => match id.name.declared_name() {
"convert_effect!" => {
let (name, typ) = match args.len() {
1 => (None, self.infer_expr(&mut args[0]).concrete),
2 => (
Some(match args[0].value {
Expr::Ident(ref id) => id.name.clone(),
_ => unreachable!(),
}),
self.infer_expr(&mut args[1]).concrete,
),
_ => unreachable!(),
};
let unaliased = self.remove_aliases(typ.clone());
let valid_type = match &*unaliased {
Type::Variant(variant) => {
let mut iter = variant.row_iter();
for _ in iter.by_ref() {}
match **iter.current_type() {
Type::EmptyRow => false,
_ => true,
}
}
_ => false,
};
if !valid_type {
return Some(Err(TypeError::Message(format!("Invalid form for the type. Expect the type to be of the form `type Effect r a = | Variant X | r` but found `{}`", unaliased))));
}
let f = self.subs.new_var();
let row_arg = self.subs.new_var();
let arg = self.subs.new_var();
let expected_shape =
self.app(f.clone(), collect![row_arg.clone(), arg.clone()]);
self.unify_span(expr.span, &expected_shape, typ);
let eff = self.poly_effect(
name.map(|name| Field {
name,
typ: self.subs.real(&f).clone(),
})
.into_iter()
.collect(),
row_arg,
);
(
mem::take(args.last_mut().unwrap()),
self.app(eff, collect![self.subs.real(&arg).clone()]),
)
}
"convert_variant!" => {
let typ = self.infer_expr(&mut args[0]).concrete;
let unaliased = self.remove_aliases(typ);
let variant_type = match *unaliased {
Type::App(ref f, ref type_args) if type_args.len() == 1 => {
let f = self.subs.real(f).clone();
match *f {
Type::Effect(ref row) => {
let variant_type = row.row_iter().fold(
self.poly_variant(vec![], self.subs.new_var()),
|variant, field| {
let typ = self.app(
field.typ.clone(),
collect![
self.subs.new_var(),
type_args[0].clone()
],
);
let typ = self.remove_alias(typ);
let typ = self.instantiate_generics(&typ);
self.subsumes(
args[0].span,
ErrorOrder::ActualExpected,
&variant,
typ,
)
},
);
let variant_type = self.subs.zonk(&variant_type);
let effect_row_rest = {
let mut iter = row.row_iter();
for _ in &mut iter {}
iter.current_type().clone()
};
let variant_row_rest = {
let mut iter = variant_type.row_iter();
for _ in &mut iter {}
iter.current_type().clone()
};
self.subsumes(
args[0].span,
ErrorOrder::ActualExpected,
&variant_row_rest,
effect_row_rest,
);
variant_type
}
_ => {
return Some(Err(TypeError::Message(format!(
"Expected an effect type, found `{}`",
unaliased
))));
}
}
}
_ => {
return Some(Err(TypeError::Message(format!(
"Expected an effect type, found `{}`",
unaliased
))));
}
};
(mem::take(args.last_mut().unwrap()), variant_type)
}
_ => return None,
},
_ => return None,
},
_ => return None,
};
*expr = Expr::annotated(self.ast_arena, replacement, self.subs.bind_arc(&typ));
Some(Ok(ModType::wobbly(typ)))
}
}
pub fn translate_projected_type(
env: &dyn TypeEnv<Type = RcType>,
symbols: &mut dyn IdentEnv<Ident = Symbol>,
interner: &mut impl TypeContext<Symbol, RcType>,
ids: &[Symbol],
) -> TcResult<RcType> {
let mut lookup_type: Option<RcType> = None;
for symbol in &ids[..ids.len() - 1] {
lookup_type = match lookup_type {
Some(typ) => {
let aliased_type = resolve::remove_aliases(env, interner, typ.clone());
Some(
aliased_type
.type_field_iter()
.filter_map(|field| {
if field.name.name_eq(&symbol) {
Some(field.typ.clone().into_type())
} else {
None
}
})
.chain(aliased_type.row_iter().filter_map(|field| {
if field.name.name_eq(&symbol) {
Some(field.typ.clone())
} else {
None
}
}))
.next()
.ok_or_else(|| TypeError::UndefinedField(typ, symbol.clone()))?,
)
}
None => Some(
env.find_type(&symbol)
.or_else(|| {
env.find_type_info(&symbol)
.map(|alias| alias.typ(interner).into_owned())
})
.ok_or_else(|| TypeError::UndefinedVariable(symbol.clone()))?,
),
};
}
let typ = lookup_type.unwrap();
let type_symbol = symbols.from_str(ids.last().expect("Non-empty ids").name().name().as_str());
resolve::remove_aliases(env, interner, typ.clone())
.type_field_iter()
.find(|field| field.name.name_eq(&type_symbol))
.map(|field| field.typ.clone().into_type())
.ok_or_else(|| TypeError::UndefinedField(typ, type_symbol))
}
fn with_pattern_types<'a: 'b, 'b, 'ast>(
fields: &'a mut [PatternField<'ast, Symbol>],
typ: &'b RcType,
) -> impl Iterator<
Item = (
&'a Spanned<Symbol, BytePos>,
&'a mut Option<SpannedPattern<'ast, Symbol>>,
Option<&'b RcType>,
),
>
where
'ast: 'a,
{
ast::pattern_values_mut(fields).map(move |(name, value)| {
let opt = typ
.row_iter()
.find(|type_field| type_field.name.name_eq(&name.value));
(
&*name,
value,
opt.map(move |associated_type| &associated_type.typ),
)
})
}
pub fn extract_generics(args: &[RcType]) -> Vec<Generic<Symbol>> {
args.iter()
.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()
}
fn get_alias_app<'a>(
env: &'a dyn TypeEnv<Type = RcType>,
typ: &'a RcType,
) -> Option<(AliasRef<Symbol, RcType>, Cow<'a, [RcType]>)> {
match **typ {
Type::Alias(ref alias) => Some((alias.clone(), Cow::Borrowed(&[][..]))),
Type::App(ref alias, ref args) => match **alias {
Type::Alias(ref alias) => Some((alias.clone(), Cow::Borrowed(&args[..]))),
_ => None,
},
_ => typ.alias_ident().and_then(|id| {
env.find_type_info(id)
.map(|alias| ((*alias).clone(), typ.unapplied_args()))
}),
}
}
struct FunctionArgIter<'a, 'b: 'a, 'ast> {
tc: &'a mut Typecheck<'b, 'ast>,
typ: RcType,
}
impl<'a, 'b> Iterator for FunctionArgIter<'a, 'b, '_> {
type Item = (ArgType, RcType);
fn next(&mut self) -> Option<Self::Item> {
let mut last_alias = None;
loop {
self.typ = self.tc.skolemize(&self.typ);
let (arg, new) = match self.typ.as_function_with_type() {
Some((arg_type, arg, ret)) => (Some((arg_type, arg.clone())), ret.clone()),
None => match get_alias_app(&self.tc.environment, &self.typ) {
Some((alias, args)) => {
if Some(&alias.name) == last_alias.as_ref() {
return None;
}
last_alias = Some(alias.name.clone());
self.tc.named_variables.clear();
match alias.typ(&mut &self.tc.subs).apply_args(
alias.params(),
&args,
&mut &self.tc.subs,
&mut self.tc.named_variables,
) {
Some(typ) => (None, typ.clone()),
None => return None,
}
}
None => return None,
},
};
self.typ = new;
if let Some(arg) = arg {
return Some(arg);
}
}
}
}
fn function_arg_iter<'a, 'b, 'ast>(
tc: &'a mut Typecheck<'b, 'ast>,
typ: RcType,
) -> FunctionArgIter<'a, 'b, 'ast> {
FunctionArgIter { tc, typ }
}
fn expr_check_span(e: &SpannedExpr<Symbol>) -> Span<BytePos> {
match e.value {
Expr::LetBindings(_, ref b) | Expr::TypeBindings(_, ref b) => expr_check_span(b),
_ => e.span,
}
}
fn generalize_binding<'ast>(
generalizer: &mut TypeGeneralizer<'_, '_, 'ast>,
resolved_type: &mut RcType,
binding: &mut ValueBinding<'ast, Symbol>,
) {
crate::implicits::resolve(generalizer.tc, &mut binding.expr);
generalizer.generalize_type_top(resolved_type);
}
fn ctor_return_type<'a, Id, T>(typ: &'a T) -> &'a T
where
T: TypePtr<Id = Id>,
Id: 'a,
{
match &**typ {
Type::Forall(_, typ) | Type::Function(_, _, typ) => ctor_return_type(typ),
_ => typ,
}
}
enum CowVec<'a, T> {
Borrowed(&'a mut [T]),
Owned(Vec<T>),
}
impl<T> std::ops::Deref for CowVec<'_, T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
match self {
CowVec::Owned(v) => v,
CowVec::Borrowed(v) => v,
}
}
}
impl<T> std::ops::DerefMut for CowVec<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
match self {
CowVec::Owned(v) => v,
CowVec::Borrowed(v) => v,
}
}
}
impl<T> CowVec<'_, T>
where
T: Default,
{
fn as_owned(&mut self) -> &mut Vec<T> {
let v = match self {
CowVec::Owned(v) => return v,
CowVec::Borrowed(b) => b.iter_mut().map(mem::take).collect(),
};
*self = CowVec::Owned(v);
self.as_owned()
}
}