mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 07:14:46 +00:00
remove uniqueness alias lifting
This commit is contained in:
parent
4bd723b353
commit
6c578440e0
1 changed files with 1 additions and 124 deletions
|
@ -15,7 +15,7 @@ use roc_types::boolean_algebra::Bool;
|
||||||
use roc_types::subs::{VarStore, Variable};
|
use roc_types::subs::{VarStore, Variable};
|
||||||
use roc_types::types::AnnotationSource::{self, *};
|
use roc_types::types::AnnotationSource::{self, *};
|
||||||
use roc_types::types::Type::{self, *};
|
use roc_types::types::Type::{self, *};
|
||||||
use roc_types::types::{Alias, Category, PReason, Reason, RecordField};
|
use roc_types::types::{Category, PReason, Reason, RecordField};
|
||||||
use roc_uniq::builtins::{attr_type, empty_list_type, list_type, str_type};
|
use roc_uniq::builtins::{attr_type, empty_list_type, list_type, str_type};
|
||||||
use roc_uniq::sharing::{self, FieldAccess, Mark, Usage, VarUsage};
|
use roc_uniq::sharing::{self, FieldAccess, Mark, Usage, VarUsage};
|
||||||
|
|
||||||
|
@ -2133,39 +2133,6 @@ fn annotation_to_attr_type_many(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn aliases_to_attr_type(var_store: &mut VarStore, aliases: &mut SendMap<Symbol, Alias>) {
|
|
||||||
for alias in aliases.iter_mut() {
|
|
||||||
// ensure
|
|
||||||
//
|
|
||||||
// Identity a : [ Identity a ]
|
|
||||||
//
|
|
||||||
// does not turn into
|
|
||||||
//
|
|
||||||
// Identity a : [ Identity (Attr u a) ]
|
|
||||||
//
|
|
||||||
// That would give a double attr wrapper on the type arguments.
|
|
||||||
// The `change_var_kind` flag set to false ensures type variables remain of kind *
|
|
||||||
let (_, new) = annotation_to_attr_type(var_store, &alias.typ, &mut ImSet::default(), false);
|
|
||||||
// remove the outer Attr, because when this occurs in a signature it'll already be wrapped in one
|
|
||||||
match new {
|
|
||||||
Type::Apply(Symbol::ATTR_ATTR, args) => {
|
|
||||||
alias.typ = args[1].clone();
|
|
||||||
if let Type::Boolean(b) = args[0].clone() {
|
|
||||||
alias.uniqueness = Some(b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => unreachable!("`annotation_to_attr_type` always gives back an Attr"),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that if the alias is a recursive tag union, all structures containing the
|
|
||||||
// recursion variable get the same uniqueness as the recursion variable (and thus as the
|
|
||||||
// recursive tag union itself)
|
|
||||||
if let Some(b) = &alias.uniqueness {
|
|
||||||
fix_mutual_recursive_alias(&mut alias.typ, b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn constrain_def(
|
fn constrain_def(
|
||||||
env: &Env,
|
env: &Env,
|
||||||
var_store: &mut VarStore,
|
var_store: &mut VarStore,
|
||||||
|
@ -2567,93 +2534,3 @@ fn constrain_field_update(
|
||||||
|
|
||||||
(var, field_type, con)
|
(var, field_type, con)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fix uniqueness attributes on mutually recursive type aliases.
|
|
||||||
/// Given aliases
|
|
||||||
///
|
|
||||||
/// > ListA a b : [ Cons a (ListB b a), Nil ]
|
|
||||||
/// > ListB a b : [ Cons a (ListA b a), Nil ]
|
|
||||||
///
|
|
||||||
/// We get the lifted alias:
|
|
||||||
///
|
|
||||||
/// > `Test.ListB`: Alias {
|
|
||||||
/// > ...,
|
|
||||||
/// > uniqueness: Some(
|
|
||||||
/// > Container(
|
|
||||||
/// > 118,
|
|
||||||
/// > {},
|
|
||||||
/// > ),
|
|
||||||
/// > ),
|
|
||||||
/// > typ: [ Global('Cons') <9> (`#Attr.Attr` Container(119, {}) Alias `Test.ListA` <10> <9>[ but actually [ Global('Cons') <10> (`#Attr.Attr` Container(118, {}) <13>), Global('Nil') ] ]), Global('Nil') ] as <13>,
|
|
||||||
/// > },
|
|
||||||
///
|
|
||||||
/// Note that the alias will get uniqueness variable <118>, but the contained `ListA` gets variable
|
|
||||||
/// <119>. But, 119 is contained in 118, and 118 in 119, so we need <119> >= <118> >= <119> >= <118> ...
|
|
||||||
/// That can only be true if they are the same. Type inference will not find that, so we must do it
|
|
||||||
/// ourselves in user-defined aliases.
|
|
||||||
fn fix_mutual_recursive_alias(typ: &mut Type, attribute: &Bool) {
|
|
||||||
use Type::*;
|
|
||||||
if let RecursiveTagUnion(rec, tags, _ext) = typ {
|
|
||||||
for (_, args) in tags {
|
|
||||||
for mut arg in args {
|
|
||||||
fix_mutual_recursive_alias_help(*rec, &Type::Boolean(attribute.clone()), &mut arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fix_mutual_recursive_alias_help(rec_var: Variable, attribute: &Type, into_type: &mut Type) {
|
|
||||||
if into_type.contains_variable(rec_var) {
|
|
||||||
if let Type::Apply(Symbol::ATTR_ATTR, args) = into_type {
|
|
||||||
args[0] = attribute.clone();
|
|
||||||
|
|
||||||
fix_mutual_recursive_alias_help_help(rec_var, attribute, &mut args[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn fix_mutual_recursive_alias_help_help(rec_var: Variable, attribute: &Type, into_type: &mut Type) {
|
|
||||||
use Type::*;
|
|
||||||
|
|
||||||
match into_type {
|
|
||||||
Function(args, closure, ret) => {
|
|
||||||
fix_mutual_recursive_alias_help(rec_var, attribute, ret);
|
|
||||||
fix_mutual_recursive_alias_help(rec_var, attribute, closure);
|
|
||||||
args.iter_mut()
|
|
||||||
.for_each(|arg| fix_mutual_recursive_alias_help(rec_var, attribute, arg));
|
|
||||||
}
|
|
||||||
RecursiveTagUnion(_, tags, ext) | TagUnion(tags, ext) => {
|
|
||||||
fix_mutual_recursive_alias_help(rec_var, attribute, ext);
|
|
||||||
|
|
||||||
for (_tag, args) in tags.iter_mut() {
|
|
||||||
for arg in args.iter_mut() {
|
|
||||||
fix_mutual_recursive_alias_help(rec_var, attribute, arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Record(fields, ext) => {
|
|
||||||
fix_mutual_recursive_alias_help(rec_var, attribute, ext);
|
|
||||||
|
|
||||||
for field in fields.iter_mut() {
|
|
||||||
let arg = match field {
|
|
||||||
RecordField::Required(arg) => arg,
|
|
||||||
RecordField::Optional(arg) => arg,
|
|
||||||
RecordField::Demanded(arg) => arg,
|
|
||||||
};
|
|
||||||
|
|
||||||
fix_mutual_recursive_alias_help(rec_var, attribute, arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Alias(_, _, actual_type) => {
|
|
||||||
// call help_help, because actual_type is not wrapped in ATTR
|
|
||||||
fix_mutual_recursive_alias_help_help(rec_var, attribute, actual_type);
|
|
||||||
}
|
|
||||||
Apply(_, args) => {
|
|
||||||
args.iter_mut()
|
|
||||||
.for_each(|arg| fix_mutual_recursive_alias_help(rec_var, attribute, arg));
|
|
||||||
}
|
|
||||||
EmptyRec | EmptyTagUnion | Erroneous(_) | Variable(_) | Boolean(_) => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue