mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 13:59:08 +00:00
Merge branch 'delay-instantiating-aliases-fix-limitations' into builtins-in-roc
This commit is contained in:
commit
35e5a36ea4
6 changed files with 256 additions and 92 deletions
|
@ -343,12 +343,8 @@ fn can_annotation_help(
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For now, aliases of function types cannot be delayed.
|
|
||||||
// This is a limitation of the current implementation,
|
|
||||||
// and this totally should be possible in the future.
|
|
||||||
let is_import = !symbol.is_builtin() && (env.home != symbol.module_id());
|
|
||||||
let is_structural = alias.kind == AliasKind::Structural;
|
let is_structural = alias.kind == AliasKind::Structural;
|
||||||
if !is_import && is_structural && alias.lambda_set_variables.is_empty() {
|
if is_structural {
|
||||||
let mut type_var_to_arg = Vec::new();
|
let mut type_var_to_arg = Vec::new();
|
||||||
|
|
||||||
for (loc_var, arg_ann) in alias.type_variables.iter().zip(args) {
|
for (loc_var, arg_ann) in alias.type_variables.iter().zip(args) {
|
||||||
|
@ -357,10 +353,21 @@ fn can_annotation_help(
|
||||||
type_var_to_arg.push((name, arg_ann));
|
type_var_to_arg.push((name, arg_ann));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut lambda_set_variables =
|
||||||
|
Vec::with_capacity(alias.lambda_set_variables.len());
|
||||||
|
|
||||||
|
for _ in 0..alias.lambda_set_variables.len() {
|
||||||
|
let lvar = var_store.fresh();
|
||||||
|
|
||||||
|
introduced_variables.insert_lambda_set(lvar);
|
||||||
|
|
||||||
|
lambda_set_variables.push(LambdaSet(Type::Variable(lvar)));
|
||||||
|
}
|
||||||
|
|
||||||
Type::DelayedAlias(AliasCommon {
|
Type::DelayedAlias(AliasCommon {
|
||||||
symbol,
|
symbol,
|
||||||
type_arguments: type_var_to_arg,
|
type_arguments: type_var_to_arg,
|
||||||
lambda_set_variables: alias.lambda_set_variables.clone(),
|
lambda_set_variables,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
let (type_arguments, lambda_set_variables, actual) =
|
let (type_arguments, lambda_set_variables, actual) =
|
||||||
|
|
|
@ -22,6 +22,7 @@ use roc_problem::can::{CycleEntry, Problem, RuntimeError};
|
||||||
use roc_region::all::{Loc, Region};
|
use roc_region::all::{Loc, Region};
|
||||||
use roc_types::subs::{VarStore, Variable};
|
use roc_types::subs::{VarStore, Variable};
|
||||||
use roc_types::types::AliasKind;
|
use roc_types::types::AliasKind;
|
||||||
|
use roc_types::types::LambdaSet;
|
||||||
use roc_types::types::{Alias, Type};
|
use roc_types::types::{Alias, Type};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
@ -1703,12 +1704,21 @@ fn correct_mutual_recursive_type_alias<'a>(
|
||||||
let alias = pending_aliases.get_mut(&rec).unwrap();
|
let alias = pending_aliases.get_mut(&rec).unwrap();
|
||||||
// Don't try to instantiate the alias itself in its definition.
|
// Don't try to instantiate the alias itself in its definition.
|
||||||
let original_alias_def = to_instantiate.remove(&rec).unwrap();
|
let original_alias_def = to_instantiate.remove(&rec).unwrap();
|
||||||
|
|
||||||
|
let mut new_lambda_sets = ImSet::default();
|
||||||
alias.typ.instantiate_aliases(
|
alias.typ.instantiate_aliases(
|
||||||
alias.region,
|
alias.region,
|
||||||
&to_instantiate,
|
&to_instantiate,
|
||||||
var_store,
|
var_store,
|
||||||
&mut ImSet::default(),
|
&mut new_lambda_sets,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
for lambda_set_var in new_lambda_sets {
|
||||||
|
alias
|
||||||
|
.lambda_set_variables
|
||||||
|
.push(LambdaSet(Type::Variable(lambda_set_var)));
|
||||||
|
}
|
||||||
|
|
||||||
to_instantiate.insert(rec, original_alias_def);
|
to_instantiate.insert(rec, original_alias_def);
|
||||||
|
|
||||||
// Now mark the alias recursive, if it needs to be.
|
// Now mark the alias recursive, if it needs to be.
|
||||||
|
|
|
@ -548,7 +548,7 @@ pub fn canonicalize_module_defs<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ModuleOutput {
|
let output = ModuleOutput {
|
||||||
scope,
|
scope,
|
||||||
aliases,
|
aliases,
|
||||||
rigid_variables,
|
rigid_variables,
|
||||||
|
@ -559,7 +559,9 @@ pub fn canonicalize_module_defs<'a>(
|
||||||
problems: env.problems,
|
problems: env.problems,
|
||||||
lookups,
|
lookups,
|
||||||
ident_ids: env.ident_ids,
|
ident_ids: env.ident_ids,
|
||||||
})
|
};
|
||||||
|
|
||||||
|
Ok(output)
|
||||||
}
|
}
|
||||||
(Err(runtime_error), _) => Err(runtime_error),
|
(Err(runtime_error), _) => Err(runtime_error),
|
||||||
}
|
}
|
||||||
|
|
|
@ -4577,6 +4577,8 @@ fn canonicalize_and_constrain<'a>(
|
||||||
..
|
..
|
||||||
} = parsed;
|
} = parsed;
|
||||||
|
|
||||||
|
let before = roc_types::types::get_type_clone_count();
|
||||||
|
|
||||||
let mut var_store = VarStore::default();
|
let mut var_store = VarStore::default();
|
||||||
let canonicalized = canonicalize_module_defs(
|
let canonicalized = canonicalize_module_defs(
|
||||||
arena,
|
arena,
|
||||||
|
@ -4592,6 +4594,16 @@ fn canonicalize_and_constrain<'a>(
|
||||||
&mut var_store,
|
&mut var_store,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let after = roc_types::types::get_type_clone_count();
|
||||||
|
|
||||||
|
log!(
|
||||||
|
"canonicalize of {:?} cloned Type {} times ({} -> {})",
|
||||||
|
module_id,
|
||||||
|
after - before,
|
||||||
|
before,
|
||||||
|
after
|
||||||
|
);
|
||||||
|
|
||||||
let canonicalize_end = SystemTime::now();
|
let canonicalize_end = SystemTime::now();
|
||||||
|
|
||||||
module_timing.canonicalize = canonicalize_end.duration_since(canonicalize_start).unwrap();
|
module_timing.canonicalize = canonicalize_end.duration_since(canonicalize_start).unwrap();
|
||||||
|
@ -4605,7 +4617,7 @@ fn canonicalize_and_constrain<'a>(
|
||||||
ModuleNameEnum::App(_) => None,
|
ModuleNameEnum::App(_) => None,
|
||||||
ModuleNameEnum::Interface(name) | ModuleNameEnum::Hosted(name) => {
|
ModuleNameEnum::Interface(name) | ModuleNameEnum::Hosted(name) => {
|
||||||
let docs = crate::docs::generate_module_docs(
|
let docs = crate::docs::generate_module_docs(
|
||||||
module_output.scope,
|
module_output.scope.clone(),
|
||||||
name.as_str().into(),
|
name.as_str().into(),
|
||||||
&module_output.ident_ids,
|
&module_output.ident_ids,
|
||||||
parsed_defs,
|
parsed_defs,
|
||||||
|
@ -4615,17 +4627,46 @@ fn canonicalize_and_constrain<'a>(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let before = roc_types::types::get_type_clone_count();
|
||||||
|
|
||||||
let mut constraints = Constraints::new();
|
let mut constraints = Constraints::new();
|
||||||
|
|
||||||
let constraint =
|
let constraint =
|
||||||
constrain_module(&mut constraints, &module_output.declarations, module_id);
|
constrain_module(&mut constraints, &module_output.declarations, module_id);
|
||||||
|
|
||||||
|
let after = roc_types::types::get_type_clone_count();
|
||||||
|
|
||||||
|
log!(
|
||||||
|
"constraint gen of {:?} cloned Type {} times ({} -> {})",
|
||||||
|
module_id,
|
||||||
|
after - before,
|
||||||
|
before,
|
||||||
|
after
|
||||||
|
);
|
||||||
|
|
||||||
|
// scope has imported aliases, but misses aliases from inner scopes
|
||||||
|
// module_output.aliases does have those aliases, so we combine them
|
||||||
|
let mut aliases = module_output.aliases;
|
||||||
|
for (name, alias) in module_output.scope.aliases {
|
||||||
|
match aliases.entry(name) {
|
||||||
|
Occupied(_) => {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
Vacant(vacant) => {
|
||||||
|
if !name.is_builtin() {
|
||||||
|
vacant.insert(alias);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let module = Module {
|
let module = Module {
|
||||||
module_id,
|
module_id,
|
||||||
exposed_imports: module_output.exposed_imports,
|
exposed_imports: module_output.exposed_imports,
|
||||||
exposed_symbols,
|
exposed_symbols,
|
||||||
referenced_values: module_output.referenced_values,
|
referenced_values: module_output.referenced_values,
|
||||||
referenced_types: module_output.referenced_types,
|
referenced_types: module_output.referenced_types,
|
||||||
aliases: module_output.aliases,
|
aliases,
|
||||||
rigid_variables: module_output.rigid_variables,
|
rigid_variables: module_output.rigid_variables,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1908,6 +1908,35 @@ fn wildcard_rigid() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm"))]
|
||||||
|
fn alias_of_alias_with_type_arguments() {
|
||||||
|
assert_non_opt_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
app "test" provides [ main ] to "./platform"
|
||||||
|
|
||||||
|
Effect a : [ @Effect a ]
|
||||||
|
|
||||||
|
Task a err : Effect (Result a err)
|
||||||
|
|
||||||
|
always : a -> Task a *
|
||||||
|
always = \x ->
|
||||||
|
inner = (Ok x)
|
||||||
|
|
||||||
|
@Effect inner
|
||||||
|
|
||||||
|
|
||||||
|
main : Task {} (Float *)
|
||||||
|
main = always {}
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
0,
|
||||||
|
i64,
|
||||||
|
|_| 0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm"))]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
|
|
|
@ -886,7 +886,11 @@ impl Type {
|
||||||
TypeExtension::Closed => Ok(()),
|
TypeExtension::Closed => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DelayedAlias(AliasCommon { type_arguments, .. }) => {
|
DelayedAlias(AliasCommon {
|
||||||
|
type_arguments,
|
||||||
|
lambda_set_variables: _no_aliases_in_lambda_sets,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
for (_, ta) in type_arguments {
|
for (_, ta) in type_arguments {
|
||||||
ta.substitute_alias(rep_symbol, rep_args, actual)?;
|
ta.substitute_alias(rep_symbol, rep_args, actual)?;
|
||||||
}
|
}
|
||||||
|
@ -966,12 +970,16 @@ impl Type {
|
||||||
DelayedAlias(AliasCommon {
|
DelayedAlias(AliasCommon {
|
||||||
symbol,
|
symbol,
|
||||||
type_arguments,
|
type_arguments,
|
||||||
|
lambda_set_variables,
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
symbol == &rep_symbol
|
symbol == &rep_symbol
|
||||||
|| type_arguments
|
|| type_arguments
|
||||||
.iter()
|
.iter()
|
||||||
.any(|v| v.1.contains_symbol(rep_symbol))
|
.any(|v| v.1.contains_symbol(rep_symbol))
|
||||||
|
|| lambda_set_variables
|
||||||
|
.iter()
|
||||||
|
.any(|v| v.0.contains_symbol(rep_symbol))
|
||||||
}
|
}
|
||||||
Alias {
|
Alias {
|
||||||
symbol: alias_symbol,
|
symbol: alias_symbol,
|
||||||
|
@ -1055,41 +1063,41 @@ impl Type {
|
||||||
region: Region,
|
region: Region,
|
||||||
aliases: &ImMap<Symbol, Alias>,
|
aliases: &ImMap<Symbol, Alias>,
|
||||||
var_store: &mut VarStore,
|
var_store: &mut VarStore,
|
||||||
introduced: &mut ImSet<Variable>,
|
new_lambda_set_variables: &mut ImSet<Variable>,
|
||||||
) {
|
) {
|
||||||
use Type::*;
|
use Type::*;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Function(args, closure, ret) => {
|
Function(args, closure, ret) => {
|
||||||
for arg in args {
|
for arg in args {
|
||||||
arg.instantiate_aliases(region, aliases, var_store, introduced);
|
arg.instantiate_aliases(region, aliases, var_store, new_lambda_set_variables);
|
||||||
}
|
}
|
||||||
closure.instantiate_aliases(region, aliases, var_store, introduced);
|
closure.instantiate_aliases(region, aliases, var_store, new_lambda_set_variables);
|
||||||
ret.instantiate_aliases(region, aliases, var_store, introduced);
|
ret.instantiate_aliases(region, aliases, var_store, new_lambda_set_variables);
|
||||||
}
|
}
|
||||||
FunctionOrTagUnion(_, _, ext) => {
|
FunctionOrTagUnion(_, _, ext) => {
|
||||||
if let TypeExtension::Open(ext) = ext {
|
if let TypeExtension::Open(ext) = ext {
|
||||||
ext.instantiate_aliases(region, aliases, var_store, introduced);
|
ext.instantiate_aliases(region, aliases, var_store, new_lambda_set_variables);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RecursiveTagUnion(_, tags, ext) | TagUnion(tags, ext) => {
|
RecursiveTagUnion(_, tags, ext) | TagUnion(tags, ext) => {
|
||||||
for (_, args) in tags {
|
for (_, args) in tags {
|
||||||
for x in args {
|
for x in args {
|
||||||
x.instantiate_aliases(region, aliases, var_store, introduced);
|
x.instantiate_aliases(region, aliases, var_store, new_lambda_set_variables);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let TypeExtension::Open(ext) = ext {
|
if let TypeExtension::Open(ext) = ext {
|
||||||
ext.instantiate_aliases(region, aliases, var_store, introduced);
|
ext.instantiate_aliases(region, aliases, var_store, new_lambda_set_variables);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Record(fields, ext) => {
|
Record(fields, ext) => {
|
||||||
for (_, x) in fields.iter_mut() {
|
for (_, x) in fields.iter_mut() {
|
||||||
x.instantiate_aliases(region, aliases, var_store, introduced);
|
x.instantiate_aliases(region, aliases, var_store, new_lambda_set_variables);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let TypeExtension::Open(ext) = ext {
|
if let TypeExtension::Open(ext) = ext {
|
||||||
ext.instantiate_aliases(region, aliases, var_store, introduced);
|
ext.instantiate_aliases(region, aliases, var_store, new_lambda_set_variables);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DelayedAlias(AliasCommon { .. }) => {
|
DelayedAlias(AliasCommon { .. }) => {
|
||||||
|
@ -1109,98 +1117,145 @@ impl Type {
|
||||||
} => {
|
} => {
|
||||||
for arg in type_args {
|
for arg in type_args {
|
||||||
arg.1
|
arg.1
|
||||||
.instantiate_aliases(region, aliases, var_store, introduced);
|
.instantiate_aliases(region, aliases, var_store, new_lambda_set_variables);
|
||||||
}
|
}
|
||||||
|
|
||||||
for arg in lambda_set_variables {
|
for arg in lambda_set_variables {
|
||||||
arg.instantiate_aliases(region, aliases, var_store, introduced);
|
arg.instantiate_aliases(region, aliases, var_store, new_lambda_set_variables);
|
||||||
}
|
}
|
||||||
|
|
||||||
actual_type.instantiate_aliases(region, aliases, var_store, introduced);
|
actual_type.instantiate_aliases(
|
||||||
|
region,
|
||||||
|
aliases,
|
||||||
|
var_store,
|
||||||
|
new_lambda_set_variables,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Apply(symbol, args, _) => {
|
Apply(symbol, args, _) => {
|
||||||
if let Some(alias) = aliases.get(symbol) {
|
if let Some(alias) = aliases.get(symbol) {
|
||||||
if args.len() != alias.type_variables.len() {
|
// TODO switch to this, but we still need to check for recursion with the
|
||||||
*self = Type::Erroneous(Problem::BadTypeArguments {
|
// `else` branch
|
||||||
|
if false {
|
||||||
|
let mut type_var_to_arg = Vec::new();
|
||||||
|
|
||||||
|
for (loc_var, arg_ann) in alias.type_variables.iter().zip(args) {
|
||||||
|
let name = loc_var.value.0.clone();
|
||||||
|
|
||||||
|
type_var_to_arg.push((name, arg_ann.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut lambda_set_variables =
|
||||||
|
Vec::with_capacity(alias.lambda_set_variables.len());
|
||||||
|
|
||||||
|
for _ in 0..alias.lambda_set_variables.len() {
|
||||||
|
let lvar = var_store.fresh();
|
||||||
|
|
||||||
|
new_lambda_set_variables.insert(lvar);
|
||||||
|
|
||||||
|
lambda_set_variables.push(LambdaSet(Type::Variable(lvar)));
|
||||||
|
}
|
||||||
|
|
||||||
|
let alias = Type::DelayedAlias(AliasCommon {
|
||||||
symbol: *symbol,
|
symbol: *symbol,
|
||||||
region,
|
type_arguments: type_var_to_arg,
|
||||||
type_got: args.len() as u8,
|
lambda_set_variables,
|
||||||
alias_needs: alias.type_variables.len() as u8,
|
|
||||||
});
|
});
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut actual = alias.typ.clone();
|
*self = alias;
|
||||||
|
} else {
|
||||||
let mut named_args = Vec::with_capacity(args.len());
|
if args.len() != alias.type_variables.len() {
|
||||||
let mut substitution = ImMap::default();
|
*self = Type::Erroneous(Problem::BadTypeArguments {
|
||||||
|
symbol: *symbol,
|
||||||
// TODO substitute further in args
|
region,
|
||||||
for (
|
type_got: args.len() as u8,
|
||||||
Loc {
|
alias_needs: alias.type_variables.len() as u8,
|
||||||
value: (lowercase, placeholder),
|
});
|
||||||
..
|
return;
|
||||||
},
|
|
||||||
filler,
|
|
||||||
) in alias.type_variables.iter().zip(args.iter())
|
|
||||||
{
|
|
||||||
let mut filler = filler.clone();
|
|
||||||
filler.instantiate_aliases(region, aliases, var_store, introduced);
|
|
||||||
named_args.push((lowercase.clone(), filler.clone()));
|
|
||||||
substitution.insert(*placeholder, filler);
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure hidden variables are freshly instantiated
|
|
||||||
let mut lambda_set_variables =
|
|
||||||
Vec::with_capacity(alias.lambda_set_variables.len());
|
|
||||||
for typ in alias.lambda_set_variables.iter() {
|
|
||||||
if let Type::Variable(var) = typ.0 {
|
|
||||||
let fresh = var_store.fresh();
|
|
||||||
introduced.insert(fresh);
|
|
||||||
substitution.insert(var, Type::Variable(fresh));
|
|
||||||
lambda_set_variables.push(LambdaSet(Type::Variable(fresh)));
|
|
||||||
} else {
|
|
||||||
unreachable!("at this point there should be only vars in there");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
actual.instantiate_aliases(region, aliases, var_store, introduced);
|
|
||||||
|
|
||||||
actual.substitute(&substitution);
|
|
||||||
|
|
||||||
// instantiate recursion variable!
|
|
||||||
if let Type::RecursiveTagUnion(rec_var, mut tags, mut ext) = actual {
|
|
||||||
let new_rec_var = var_store.fresh();
|
|
||||||
substitution.clear();
|
|
||||||
substitution.insert(rec_var, Type::Variable(new_rec_var));
|
|
||||||
|
|
||||||
for typ in tags.iter_mut().map(|v| v.1.iter_mut()).flatten() {
|
|
||||||
typ.substitute(&substitution);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let TypeExtension::Open(ext) = &mut ext {
|
let mut actual = alias.typ.clone();
|
||||||
ext.substitute(&substitution);
|
|
||||||
|
let mut named_args = Vec::with_capacity(args.len());
|
||||||
|
let mut substitution = ImMap::default();
|
||||||
|
|
||||||
|
// TODO substitute further in args
|
||||||
|
for (
|
||||||
|
Loc {
|
||||||
|
value: (lowercase, placeholder),
|
||||||
|
..
|
||||||
|
},
|
||||||
|
filler,
|
||||||
|
) in alias.type_variables.iter().zip(args.iter())
|
||||||
|
{
|
||||||
|
let mut filler = filler.clone();
|
||||||
|
filler.instantiate_aliases(
|
||||||
|
region,
|
||||||
|
aliases,
|
||||||
|
var_store,
|
||||||
|
new_lambda_set_variables,
|
||||||
|
);
|
||||||
|
named_args.push((lowercase.clone(), filler.clone()));
|
||||||
|
substitution.insert(*placeholder, filler);
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = Type::RecursiveTagUnion(new_rec_var, tags, ext);
|
// make sure hidden variables are freshly instantiated
|
||||||
}
|
let mut lambda_set_variables =
|
||||||
|
Vec::with_capacity(alias.lambda_set_variables.len());
|
||||||
|
for typ in alias.lambda_set_variables.iter() {
|
||||||
|
if let Type::Variable(var) = typ.0 {
|
||||||
|
let fresh = var_store.fresh();
|
||||||
|
new_lambda_set_variables.insert(fresh);
|
||||||
|
substitution.insert(var, Type::Variable(fresh));
|
||||||
|
lambda_set_variables.push(LambdaSet(Type::Variable(fresh)));
|
||||||
|
} else {
|
||||||
|
unreachable!("at this point there should be only vars in there");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
*self = Type::Alias {
|
actual.instantiate_aliases(
|
||||||
symbol: *symbol,
|
region,
|
||||||
type_arguments: named_args,
|
aliases,
|
||||||
lambda_set_variables,
|
var_store,
|
||||||
actual: Box::new(actual),
|
new_lambda_set_variables,
|
||||||
kind: alias.kind,
|
);
|
||||||
};
|
|
||||||
|
actual.substitute(&substitution);
|
||||||
|
|
||||||
|
// instantiate recursion variable!
|
||||||
|
if let Type::RecursiveTagUnion(rec_var, mut tags, mut ext) = actual {
|
||||||
|
let new_rec_var = var_store.fresh();
|
||||||
|
substitution.clear();
|
||||||
|
substitution.insert(rec_var, Type::Variable(new_rec_var));
|
||||||
|
|
||||||
|
for typ in tags.iter_mut().map(|v| v.1.iter_mut()).flatten() {
|
||||||
|
typ.substitute(&substitution);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let TypeExtension::Open(ext) = &mut ext {
|
||||||
|
ext.substitute(&substitution);
|
||||||
|
}
|
||||||
|
|
||||||
|
actual = Type::RecursiveTagUnion(new_rec_var, tags, ext);
|
||||||
|
}
|
||||||
|
let alias = Type::Alias {
|
||||||
|
symbol: *symbol,
|
||||||
|
type_arguments: named_args,
|
||||||
|
lambda_set_variables,
|
||||||
|
actual: Box::new(actual),
|
||||||
|
kind: alias.kind,
|
||||||
|
};
|
||||||
|
|
||||||
|
*self = alias;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// one of the special-cased Apply types.
|
// one of the special-cased Apply types.
|
||||||
for x in args {
|
for x in args {
|
||||||
x.instantiate_aliases(region, aliases, var_store, introduced);
|
x.instantiate_aliases(region, aliases, var_store, new_lambda_set_variables);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RangedNumber(typ, _) => {
|
RangedNumber(typ, _) => {
|
||||||
typ.instantiate_aliases(region, aliases, var_store, introduced);
|
typ.instantiate_aliases(region, aliases, var_store, new_lambda_set_variables);
|
||||||
}
|
}
|
||||||
EmptyRec | EmptyTagUnion | ClosureTag { .. } | Erroneous(_) | Variable(_) => {}
|
EmptyRec | EmptyTagUnion | ClosureTag { .. } | Erroneous(_) | Variable(_) => {}
|
||||||
}
|
}
|
||||||
|
@ -1406,10 +1461,18 @@ fn variables_help(tipe: &Type, accum: &mut ImSet<Variable>) {
|
||||||
// this rec var doesn't need to be in flex_vars or rigid_vars
|
// this rec var doesn't need to be in flex_vars or rigid_vars
|
||||||
accum.remove(rec);
|
accum.remove(rec);
|
||||||
}
|
}
|
||||||
DelayedAlias(AliasCommon { type_arguments, .. }) => {
|
DelayedAlias(AliasCommon {
|
||||||
|
type_arguments,
|
||||||
|
lambda_set_variables,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
for (_, arg) in type_arguments {
|
for (_, arg) in type_arguments {
|
||||||
variables_help(arg, accum);
|
variables_help(arg, accum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for lambda_set in lambda_set_variables {
|
||||||
|
variables_help(&lambda_set.0, accum);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Alias {
|
Alias {
|
||||||
type_arguments,
|
type_arguments,
|
||||||
|
@ -1530,10 +1593,22 @@ fn variables_help_detailed(tipe: &Type, accum: &mut VariableDetail) {
|
||||||
|
|
||||||
accum.recursion_variables.insert(*rec);
|
accum.recursion_variables.insert(*rec);
|
||||||
}
|
}
|
||||||
DelayedAlias(AliasCommon { type_arguments, .. }) => {
|
DelayedAlias(AliasCommon {
|
||||||
|
type_arguments,
|
||||||
|
lambda_set_variables,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
for (_, arg) in type_arguments {
|
for (_, arg) in type_arguments {
|
||||||
variables_help_detailed(arg, accum);
|
variables_help_detailed(arg, accum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for lambda_set in lambda_set_variables {
|
||||||
|
if let Type::Variable(v) = lambda_set.0 {
|
||||||
|
accum.lambda_set_variables.push(v);
|
||||||
|
} else {
|
||||||
|
variables_help_detailed(&lambda_set.0, accum);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Alias {
|
Alias {
|
||||||
type_arguments,
|
type_arguments,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue