write Aliases implementation

This commit is contained in:
Folkert 2022-03-15 22:02:04 +01:00
parent a66d23f93d
commit 7d8409f6a6
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
7 changed files with 175 additions and 35 deletions

View file

@ -1390,7 +1390,7 @@ fn adjust_rank_content(
Alias(_, args, real_var, _) => { Alias(_, args, real_var, _) => {
let mut rank = Rank::toplevel(); let mut rank = Rank::toplevel();
for var_index in args.variables() { for var_index in args.all_variables() {
let var = subs[var_index]; let var = subs[var_index];
rank = rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, var)); rank = rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, var));
} }
@ -1548,7 +1548,7 @@ fn instantiate_rigids_help(
} }
Alias(_, args, real_type_var, _) => { Alias(_, args, real_type_var, _) => {
for var_index in args.variables() { for var_index in args.all_variables() {
let var = subs[var_index]; let var = subs[var_index];
instantiate_rigids_help(subs, max_rank, pools, var); instantiate_rigids_help(subs, max_rank, pools, var);
} }
@ -1798,9 +1798,9 @@ fn deep_copy_var_help(
} }
Alias(symbol, mut args, real_type_var, kind) => { Alias(symbol, mut args, real_type_var, kind) => {
let mut new_args = Vec::with_capacity(args.variables().len()); let mut new_args = Vec::with_capacity(args.all_variables().len());
for var_index in args.variables() { for var_index in args.all_variables() {
let var = subs[var_index]; let var = subs[var_index];
let new_var = deep_copy_var_help(subs, max_rank, pools, var); let new_var = deep_copy_var_help(subs, max_rank, pools, var);
new_args.push(new_var); new_args.push(new_var);

View file

@ -8446,7 +8446,7 @@ pub fn num_argument_to_int_or_float(
debug_assert!(args.len() == 1); debug_assert!(args.len() == 1);
// Recurse on the second argument // Recurse on the second argument
let var = subs[args.variables().into_iter().next().unwrap()]; let var = subs[args.all_variables().into_iter().next().unwrap()];
num_argument_to_int_or_float(subs, target_info, var, false) num_argument_to_int_or_float(subs, target_info, var, false)
} }
@ -8464,7 +8464,7 @@ pub fn num_argument_to_int_or_float(
debug_assert!(args.len() == 1); debug_assert!(args.len() == 1);
// Recurse on the second argument // Recurse on the second argument
let var = subs[args.variables().into_iter().next().unwrap()]; let var = subs[args.all_variables().into_iter().next().unwrap()];
num_argument_to_int_or_float(subs, target_info, var, true) num_argument_to_int_or_float(subs, target_info, var, true)
} }

View file

@ -2670,7 +2670,7 @@ fn unwrap_num_tag<'a>(
Content::Alias(Symbol::NUM_INTEGER, args, _, _) => { Content::Alias(Symbol::NUM_INTEGER, args, _, _) => {
debug_assert!(args.len() == 1); debug_assert!(args.len() == 1);
let precision_var = subs[args.variables().into_iter().next().unwrap()]; let precision_var = subs[args.all_variables().into_iter().next().unwrap()];
let precision = subs.get_content_without_compacting(precision_var); let precision = subs.get_content_without_compacting(precision_var);
@ -2706,7 +2706,7 @@ fn unwrap_num_tag<'a>(
Content::Alias(Symbol::NUM_FLOATINGPOINT, args, _, _) => { Content::Alias(Symbol::NUM_FLOATINGPOINT, args, _, _) => {
debug_assert!(args.len() == 1); debug_assert!(args.len() == 1);
let precision_var = subs[args.variables().into_iter().next().unwrap()]; let precision_var = subs[args.all_variables().into_iter().next().unwrap()];
let precision = subs.get_content_without_compacting(precision_var); let precision = subs.get_content_without_compacting(precision_var);

View file

@ -78,27 +78,142 @@ pub enum TypeError {
use roc_types::types::Alias; use roc_types::types::Alias;
#[derive(Debug, Clone, Copy)]
struct DelayedAliasVariables {
start: u32,
type_variables_len: u8,
lambda_set_variables_len: u8,
recursion_variables_len: u8,
}
impl DelayedAliasVariables {
fn recursion_variables(self, variables: &mut [Variable]) -> &mut [Variable] {
let start = self.start as usize
+ (self.type_variables_len + self.lambda_set_variables_len) as usize;
let length = self.recursion_variables_len as usize;
&mut variables[start..][..length]
}
fn lambda_set_variables(self, variables: &mut [Variable]) -> &mut [Variable] {
let start = self.start as usize + self.type_variables_len as usize;
let length = self.lambda_set_variables_len as usize;
&mut variables[start..][..length]
}
fn type_variables(self, variables: &mut [Variable]) -> &mut [Variable] {
let start = self.start as usize;
let length = self.type_variables_len as usize;
&mut variables[start..][..length]
}
}
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct Aliases { pub struct Aliases {
aliases: MutMap<Symbol, Alias>, aliases: Vec<(Symbol, Type, DelayedAliasVariables)>,
variables: Vec<Variable>,
} }
impl Aliases { impl Aliases {
fn instantiate_alias( pub fn insert(&mut self, symbol: Symbol, alias: Alias) {
&self, // debug_assert!(self.get(&symbol).is_none());
let alias_variables =
{
let start = self.variables.len() as _;
self.variables
.extend(alias.type_variables.iter().map(|x| x.value.1));
self.variables.extend(alias.lambda_set_variables.iter().map(
|x| match x.as_inner() {
Type::Variable(v) => *v,
_ => unreachable!("lambda set type is not a variable"),
},
));
let recursion_variables_len = alias.recursion_variables.len() as _;
self.variables.extend(alias.recursion_variables);
DelayedAliasVariables {
start,
type_variables_len: alias.type_variables.len() as _,
lambda_set_variables_len: alias.lambda_set_variables.len() as _,
recursion_variables_len,
}
};
self.aliases.push((symbol, alias.typ, alias_variables));
}
fn instantiate(
&mut self,
subs: &mut Subs, subs: &mut Subs,
rank: Rank, rank: Rank,
pools: &mut Pools, pools: &mut Pools,
arena: &bumpalo::Bump, _arena: &bumpalo::Bump,
symbol: Symbol, symbol: Symbol,
alias_variables: AliasVariables, alias_variables: AliasVariables,
) -> Result<Variable, ()> { ) -> Result<Variable, ()> {
match self.aliases.get(&symbol) { let (typ, delayed_variables) = match self.aliases.iter_mut().find(|(s, _, _)| *s == symbol)
None => Err(()), {
Some(alias) => { None => return Err(()),
todo!() Some((_, typ, delayed_variables)) => (typ, delayed_variables),
};
let mut substitutions: MutMap<_, _> = Default::default();
for rec_var in delayed_variables
.recursion_variables(&mut self.variables)
.iter_mut()
{
let new_var = subs.fresh_unnamed_flex_var();
substitutions.insert(*rec_var, new_var);
*rec_var = new_var;
}
let old_type_variables = delayed_variables.type_variables(&mut self.variables);
let new_type_variables = &subs.variables[alias_variables.type_variables().indices()];
for (old, new) in old_type_variables.iter_mut().zip(new_type_variables) {
substitutions.insert(*old, *new);
*old = *new;
}
let old_lambda_set_variables = delayed_variables.lambda_set_variables(&mut self.variables);
let new_lambda_set_variables =
&subs.variables[alias_variables.lambda_set_variables().indices()];
for (old, new) in old_lambda_set_variables
.iter_mut()
.zip(new_lambda_set_variables)
{
substitutions.insert(*old, *new);
*old = *new;
}
typ.substitute_variables(&substitutions);
// assumption: an alias does not (transitively) syntactically contain itself
// (if it did it would have to be a recursive tag union)
let mut t = Type::EmptyRec;
std::mem::swap(typ, &mut t);
let alias_variable = type_to_var(subs, rank, pools, self, &t);
{
match self.aliases.iter_mut().find(|(s, _, _)| *s == symbol) {
None => unreachable!(),
Some((_, typ, _)) => {
std::mem::swap(typ, &mut t);
}
} }
} }
Ok(alias_variable)
} }
} }
@ -932,7 +1047,7 @@ fn type_to_var(
subs: &mut Subs, subs: &mut Subs,
rank: Rank, rank: Rank,
pools: &mut Pools, pools: &mut Pools,
aliases: &Aliases, aliases: &mut Aliases,
typ: &Type, typ: &Type,
) -> Variable { ) -> Variable {
if let Type::Variable(var) = typ { if let Type::Variable(var) = typ {
@ -1020,7 +1135,7 @@ fn type_to_variable<'a>(
rank: Rank, rank: Rank,
pools: &mut Pools, pools: &mut Pools,
arena: &'a bumpalo::Bump, arena: &'a bumpalo::Bump,
aliases: &Aliases, aliases: &mut Aliases,
typ: &Type, typ: &Type,
) -> Variable { ) -> Variable {
use bumpalo::collections::Vec; use bumpalo::collections::Vec;
@ -1226,7 +1341,7 @@ fn type_to_variable<'a>(
}; };
let instantiated = let instantiated =
aliases.instantiate_alias(subs, rank, pools, arena, *symbol, alias_variables); aliases.instantiate(subs, rank, pools, arena, *symbol, alias_variables);
let alias_variable = match instantiated { let alias_variable = match instantiated {
Err(_) => panic!("Alias {:?} is not available", symbol), Err(_) => panic!("Alias {:?} is not available", symbol),
@ -1943,7 +2058,7 @@ fn adjust_rank_content(
Alias(_, args, real_var, _) => { Alias(_, args, real_var, _) => {
let mut rank = Rank::toplevel(); let mut rank = Rank::toplevel();
for var_index in args.variables() { for var_index in args.all_variables() {
let var = subs[var_index]; let var = subs[var_index];
rank = rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, var)); rank = rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, var));
} }
@ -2089,7 +2204,7 @@ fn instantiate_rigids_help(subs: &mut Subs, max_rank: Rank, initial: Variable) {
let var = *var; let var = *var;
let args = *args; let args = *args;
stack.extend(var_slice!(args.variables())); stack.extend(var_slice!(args.all_variables()));
stack.push(var); stack.push(var);
} }
@ -2338,7 +2453,9 @@ fn deep_copy_var_help(
Alias(symbol, arguments, real_type_var, kind) => { Alias(symbol, arguments, real_type_var, kind) => {
let new_variables = let new_variables =
SubsSlice::reserve_into_subs(subs, arguments.all_variables_len as _); SubsSlice::reserve_into_subs(subs, arguments.all_variables_len as _);
for (target_index, var_index) in (new_variables.indices()).zip(arguments.variables()) { for (target_index, var_index) in
(new_variables.indices()).zip(arguments.all_variables())
{
let var = subs[var_index]; let var = subs[var_index];
let copy_var = deep_copy_var_help(subs, max_rank, pools, visited, var); let copy_var = deep_copy_var_help(subs, max_rank, pools, visited, var);
subs.variables[target_index] = copy_var; subs.variables[target_index] = copy_var;

View file

@ -427,7 +427,7 @@ fn subs_fmt_content(this: &Content, subs: &Subs, f: &mut fmt::Formatter) -> fmt:
} => write!(f, "Recursion({:?}, {:?})", structure, opt_name), } => write!(f, "Recursion({:?}, {:?})", structure, opt_name),
Content::Structure(flat_type) => subs_fmt_flat_type(flat_type, subs, f), Content::Structure(flat_type) => subs_fmt_flat_type(flat_type, subs, f),
Content::Alias(name, arguments, actual, kind) => { Content::Alias(name, arguments, actual, kind) => {
let slice = subs.get_subs_slice(arguments.variables()); let slice = subs.get_subs_slice(arguments.all_variables());
let wrap = match kind { let wrap = match kind {
AliasKind::Structural => "Alias", AliasKind::Structural => "Alias",
AliasKind::Opaque => "Opaque", AliasKind::Opaque => "Opaque",
@ -1775,10 +1775,21 @@ pub struct AliasVariables {
} }
impl AliasVariables { impl AliasVariables {
pub const fn variables(&self) -> VariableSubsSlice { pub const fn all_variables(&self) -> VariableSubsSlice {
SubsSlice::new(self.variables_start, self.all_variables_len) SubsSlice::new(self.variables_start, self.all_variables_len)
} }
pub const fn type_variables(&self) -> VariableSubsSlice {
SubsSlice::new(self.variables_start, self.type_variables_len)
}
pub const fn lambda_set_variables(&self) -> VariableSubsSlice {
SubsSlice::new(
self.variables_start + self.type_variables_len as u32,
self.all_variables_len - self.type_variables_len,
)
}
pub const fn len(&self) -> usize { pub const fn len(&self) -> usize {
self.type_variables_len as usize self.type_variables_len as usize
} }
@ -1802,13 +1813,13 @@ impl AliasVariables {
} }
pub fn named_type_arguments(&self) -> impl Iterator<Item = SubsIndex<Variable>> { pub fn named_type_arguments(&self) -> impl Iterator<Item = SubsIndex<Variable>> {
self.variables() self.all_variables()
.into_iter() .into_iter()
.take(self.type_variables_len as usize) .take(self.type_variables_len as usize)
} }
pub fn unnamed_type_arguments(&self) -> impl Iterator<Item = SubsIndex<Variable>> { pub fn unnamed_type_arguments(&self) -> impl Iterator<Item = SubsIndex<Variable>> {
self.variables() self.all_variables()
.into_iter() .into_iter()
.skip(self.type_variables_len as usize) .skip(self.type_variables_len as usize)
} }
@ -1850,7 +1861,7 @@ impl IntoIterator for AliasVariables {
type IntoIter = <VariableSubsSlice as IntoIterator>::IntoIter; type IntoIter = <VariableSubsSlice as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter {
self.variables().into_iter() self.all_variables().into_iter()
} }
} }
@ -3298,7 +3309,7 @@ fn restore_help(subs: &mut Subs, initial: Variable) {
Erroneous(_) => (), Erroneous(_) => (),
}, },
Alias(_, args, var, _) => { Alias(_, args, var, _) => {
stack.extend(var_slice(args.variables())); stack.extend(var_slice(args.all_variables()));
stack.push(*var); stack.push(*var);
} }
@ -3333,6 +3344,14 @@ impl StorageSubs {
Self { subs } Self { subs }
} }
pub fn fresh_unnamed_flex_var(&mut self) -> Variable {
self.subs.fresh_unnamed_flex_var()
}
pub fn as_inner_mut(&mut self) -> &mut Subs {
&mut self.subs
}
pub fn extend_with_variable(&mut self, source: &mut Subs, variable: Variable) -> Variable { pub fn extend_with_variable(&mut self, source: &mut Subs, variable: Variable) -> Variable {
deep_copy_var_to(source, &mut self.subs, variable) deep_copy_var_to(source, &mut self.subs, variable)
} }
@ -3867,7 +3886,9 @@ fn deep_copy_var_to_help<'a>(env: &mut DeepCopyVarToEnv<'a>, var: Variable) -> V
Alias(symbol, arguments, real_type_var, kind) => { Alias(symbol, arguments, real_type_var, kind) => {
let new_variables = let new_variables =
SubsSlice::reserve_into_subs(env.target, arguments.all_variables_len as _); SubsSlice::reserve_into_subs(env.target, arguments.all_variables_len as _);
for (target_index, var_index) in (new_variables.indices()).zip(arguments.variables()) { for (target_index, var_index) in
(new_variables.indices()).zip(arguments.all_variables())
{
let var = env.source[var_index]; let var = env.source[var_index];
let copy_var = deep_copy_var_to_help(env, var); let copy_var = deep_copy_var_to_help(env, var);
env.target.variables[target_index] = copy_var; env.target.variables[target_index] = copy_var;
@ -4284,7 +4305,9 @@ fn copy_import_to_help(env: &mut CopyImportEnv<'_>, max_rank: Rank, var: Variabl
Alias(symbol, arguments, real_type_var, kind) => { Alias(symbol, arguments, real_type_var, kind) => {
let new_variables = let new_variables =
SubsSlice::reserve_into_subs(env.target, arguments.all_variables_len as _); SubsSlice::reserve_into_subs(env.target, arguments.all_variables_len as _);
for (target_index, var_index) in (new_variables.indices()).zip(arguments.variables()) { for (target_index, var_index) in
(new_variables.indices()).zip(arguments.all_variables())
{
let var = env.source[var_index]; let var = env.source[var_index];
let copy_var = copy_import_to_help(env, max_rank, var); let copy_var = copy_import_to_help(env, max_rank, var);
env.target.variables[target_index] = copy_var; env.target.variables[target_index] = copy_var;
@ -4389,7 +4412,7 @@ where
Erroneous(_) | EmptyRecord | EmptyTagUnion => {} Erroneous(_) | EmptyRecord | EmptyTagUnion => {}
}, },
Alias(_, arguments, real_type_var, _) => { Alias(_, arguments, real_type_var, _) => {
push_var_slice!(arguments.variables()); push_var_slice!(arguments.all_variables());
stack.push(*real_type_var); stack.push(*real_type_var);
} }
RangedNumber(typ, vars) => { RangedNumber(typ, vars) => {

View file

@ -160,8 +160,8 @@ impl RecordField<Type> {
pub struct LambdaSet(pub Type); pub struct LambdaSet(pub Type);
impl LambdaSet { impl LambdaSet {
fn substitute(&mut self, substitutions: &ImMap<Variable, Type>) { pub fn as_inner(&self) -> &Type {
self.0.substitute(substitutions); &self.0
} }
fn as_inner_mut(&mut self) -> &mut Type { fn as_inner_mut(&mut self) -> &mut Type {

View file

@ -322,9 +322,9 @@ fn unify_alias(
if args.len() == other_args.len() { if args.len() == other_args.len() {
let mut problems = Vec::new(); let mut problems = Vec::new();
let it = args let it = args
.variables() .all_variables()
.into_iter() .into_iter()
.zip(other_args.variables().into_iter()); .zip(other_args.all_variables().into_iter());
for (l, r) in it { for (l, r) in it {
let l_var = subs[l]; let l_var = subs[l];