mirror of
https://github.com/roc-lang/roc.git
synced 2024-11-10 10:02:38 +03:00
remove uniqueness alias lifting
This commit is contained in:
parent
4bd723b353
commit
6c578440e0
@ -15,7 +15,7 @@ use roc_types::boolean_algebra::Bool;
|
||||
use roc_types::subs::{VarStore, Variable};
|
||||
use roc_types::types::AnnotationSource::{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::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(
|
||||
env: &Env,
|
||||
var_store: &mut VarStore,
|
||||
@ -2567,93 +2534,3 @@ fn constrain_field_update(
|
||||
|
||||
(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…
Reference in New Issue
Block a user