Replacing rather than mutating produces better type trees
This reverts commit
@@ -1013,8 +1013,10 @@ fn generalise_statement(
let typ = function.type_.clone();
// Generalise the function if not already done so
- if environment.ungeneralised_functions.remove(&name) {
- generalise(&typ)
+ let typ = if environment.ungeneralised_functions.remove(&name) {
+ generalise(typ)
+ } else {
+ typ
};
// Insert the function into the module's interface
@@ -1073,7 +1075,6 @@ fn infer_statement(
end_position: end_location,
..
} => {
- dbg!(("fn", &name));
let preregistered_fn = environment
.get_variable(&name)
.expect("Could not find preregistered type for function");
@@ -1111,7 +1112,7 @@ fn infer_statement(
// Generalise the function if safe to do so
let typ = if safe_to_generalise {
let _ = environment.ungeneralised_functions.remove(&name);
- generalise(&typ);
+ let typ = generalise(typ);
environment.insert_variable(
name.clone(),
ValueConstructorVariant::ModuleFn {
@@ -1568,29 +1569,35 @@ fn match_fun_type(
Err(MatchFunTypeError::NotFn { typ })
}
-fn generalise(t: &Type) {
+fn generalise(t: Arc<Type>) -> Arc<Type> {
match t.deref() {
- Type::Var { type_: typ } => {
- let id = match typ.borrow().deref() {
- TypeVar::Link { type_: typ } => return generalise(&typ),
- TypeVar::Generic { .. } => return,
- TypeVar::Unbound { id } => *id,
- };
- *typ.borrow_mut() = TypeVar::Generic { id }
- }
+ Type::Var { type_: typ } => match typ.borrow().deref() {
+ TypeVar::Unbound { id } => generic_var(*id),
+ TypeVar::Link { type_: typ } => generalise(typ.clone()),
+ TypeVar::Generic { .. } => Arc::new(Type::Var { type_: typ.clone() }),
+ },
- Type::Tuple { elems: types } | Type::App { args: types, .. } => {
- for t in types {
- generalise(&t);
- }
+ Type::App {
+ public,
+ module,
+ name,
+ args,
+ } => {
+ let args = args.iter().map(|t| generalise(t.clone())).collect();
+ Arc::new(Type::App {
+ public: *public,
+ module: module.clone(),
+ name: name.clone(),
+ args,
+ })
}
- Type::Fn { args, retrn } => {
- for t in args {
- generalise(&t);
- }
- generalise(&retrn);
- }
+ Type::Fn { args, retrn } => fn_(
+ args.iter().map(|t| generalise(t.clone())).collect(),
+ generalise(retrn.clone()),
+ ),
+
+ Type::Tuple { elems } => tuple(elems.iter().map(|t| generalise(t.clone())).collect()),
}
}
