Support OIOP for type aliases

This commit is contained in:
Ayaz Hafiz 2022-10-26 15:21:28 -05:00
parent 6ee2fb496d
commit debe6332c5
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
21 changed files with 452 additions and 115 deletions

View file

@ -802,12 +802,12 @@ fn subs_fmt_content(this: &Content, subs: &Subs, f: &mut fmt::Formatter) -> fmt:
};
write!(f, "Flex({})", name)
}
Content::FlexAbleVar(name, symbol) => {
Content::FlexAbleVar(name, symbols) => {
let name = match name {
Some(index) => subs[*index].as_str(),
None => "_",
};
write!(f, "FlexAble({}, {:?})", name, symbol)
write!(f, "FlexAble({}, {:?})", name, subs.get_subs_slice(*symbols))
}
Content::RigidVar(name) => write!(f, "Rigid({:?})", name),
Content::RigidAbleVar(name, symbol) => write!(f, "RigidAble({:?}, {:?})", name, symbol),
@ -1437,7 +1437,7 @@ fn integer_type(
// define the type `Num.Integer Num.Signed64 := Num.Signed64`
{
let vars = AliasVariables::insert_into_subs(subs, [signed64], []);
let vars = AliasVariables::insert_into_subs(subs, [signed64], [], []);
subs.set_content(integer_signed64, {
Content::Alias(Symbol::NUM_INTEGER, vars, signed64, AliasKind::Opaque)
});
@ -1445,7 +1445,7 @@ fn integer_type(
// define the type `Num.Num (Num.Integer Num.Signed64) := Num.Integer Num.Signed64`
{
let vars = AliasVariables::insert_into_subs(subs, [integer_signed64], []);
let vars = AliasVariables::insert_into_subs(subs, [integer_signed64], [], []);
subs.set_content(num_integer_signed64, {
Content::Alias(Symbol::NUM_NUM, vars, integer_signed64, AliasKind::Opaque)
});
@ -1605,7 +1605,7 @@ fn float_type(
// define the type `Num.Float Num.Binary64 := Num.Binary64`
{
let vars = AliasVariables::insert_into_subs(subs, [binary64], []);
let vars = AliasVariables::insert_into_subs(subs, [binary64], [], []);
subs.set_content(float_binary64, {
Content::Alias(Symbol::NUM_FLOATINGPOINT, vars, binary64, AliasKind::Opaque)
});
@ -1613,7 +1613,7 @@ fn float_type(
// define the type `Num.Num (Num.Float Num.Binary64) := Num.Float Num.Binary64`
{
let vars = AliasVariables::insert_into_subs(subs, [float_binary64], []);
let vars = AliasVariables::insert_into_subs(subs, [float_binary64], [], []);
subs.set_content(num_float_binary64, {
Content::Alias(Symbol::NUM_NUM, vars, float_binary64, AliasKind::Opaque)
});
@ -2269,8 +2269,8 @@ impl From<Content> for Descriptor {
}
roc_error_macros::assert_sizeof_all!(Content, 4 * 8);
roc_error_macros::assert_sizeof_all!((Symbol, AliasVariables, Variable), 2 * 8 + 4);
roc_error_macros::assert_sizeof_all!(AliasVariables, 8);
roc_error_macros::assert_sizeof_all!((Symbol, AliasVariables, Variable), 8 + 12 + 4);
roc_error_macros::assert_sizeof_all!(AliasVariables, 12);
roc_error_macros::assert_sizeof_all!(FlatType, 3 * 8);
roc_error_macros::assert_sizeof_all!(LambdaSet, 3 * 8 + 4);
@ -2358,8 +2358,11 @@ pub struct LambdaSet {
pub struct AliasVariables {
pub variables_start: u32,
pub all_variables_len: u16,
pub lambda_set_variables_len: u16,
/// an alias has type variables and lambda set variables
/// an alias has type variables, lambda set variables, and infer-ext-in-output-position variables.
/// They are arranged as
/// [ type variables | lambda set variables | infer ext variables ]
pub type_variables_len: u16,
}
@ -2373,10 +2376,16 @@ impl AliasVariables {
}
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,
)
let start = self.variables_start + self.type_variables_len as u32;
SubsSlice::new(start, self.lambda_set_variables_len)
}
pub const fn infer_ext_in_output_variables(&self) -> VariableSubsSlice {
let infer_ext_vars_offset =
self.type_variables_len as u32 + self.lambda_set_variables_len as u32;
let start = self.variables_start + infer_ext_vars_offset;
let infer_ext_vars_len = self.all_variables_len - infer_ext_vars_offset as u16;
SubsSlice::new(start, infer_ext_vars_len)
}
pub const fn len(&self) -> usize {
@ -2407,20 +2416,23 @@ impl AliasVariables {
.take(self.type_variables_len as usize)
}
pub fn unnamed_type_arguments(&self) -> impl Iterator<Item = SubsIndex<Variable>> {
pub fn iter_lambda_set_variables(&self) -> impl Iterator<Item = SubsIndex<Variable>> {
self.all_variables()
.into_iter()
.skip(self.type_variables_len as usize)
.take(self.lambda_set_variables_len as _)
}
pub fn insert_into_subs<I1, I2>(
pub fn insert_into_subs<I1, I2, I3>(
subs: &mut Subs,
type_arguments: I1,
unnamed_arguments: I2,
lambda_set_vars: I2,
infer_ext_in_output_vars: I3,
) -> Self
where
I1: IntoIterator<Item = Variable>,
I2: IntoIterator<Item = Variable>,
I3: IntoIterator<Item = Variable>,
{
let variables_start = subs.variables.len() as u32;
@ -2428,13 +2440,33 @@ impl AliasVariables {
let type_variables_len = (subs.variables.len() as u32 - variables_start) as u16;
subs.variables.extend(unnamed_arguments);
let lambda_set_variables_len = {
let start = subs.variables.len() as u32;
subs.variables.extend(lambda_set_vars);
(subs.variables.len() as u32 - start) as u16
};
let _infer_ext_in_output_vars_len = {
let start = subs.variables.len() as u32;
subs.variables.extend(infer_ext_in_output_vars);
(subs.variables.len() as u32 - start) as u16
};
let all_variables_len = (subs.variables.len() as u32 - variables_start) as u16;
debug_assert_eq!(
type_variables_len + lambda_set_variables_len + _infer_ext_in_output_vars_len,
all_variables_len
);
Self {
variables_start,
type_variables_len,
lambda_set_variables_len,
all_variables_len,
}
}
@ -3800,7 +3832,7 @@ fn content_to_err_type(
let mut err_args = Vec::with_capacity(args.len());
for var_index in args.into_iter() {
for var_index in args.type_variables() {
let var = subs[var_index];
let arg = var_to_err_type(subs, state, var, pol);

View file

@ -172,19 +172,18 @@ impl RecordField<Type> {
region: Region,
aliases: &'a F,
var_store: &mut VarStore,
introduced: &mut ImSet<Variable>,
new_lambda_sets: &mut ImSet<Variable>,
new_infer_ext_vars: &mut ImSet<Variable>,
) where
F: Fn(Symbol) -> Option<&'a Alias>,
{
use RecordField::*;
match self {
Optional(typ) => typ.instantiate_aliases(region, aliases, var_store, introduced),
Required(typ) => typ.instantiate_aliases(region, aliases, var_store, introduced),
Demanded(typ) => typ.instantiate_aliases(region, aliases, var_store, introduced),
RigidRequired(typ) => typ.instantiate_aliases(region, aliases, var_store, introduced),
RigidOptional(typ) => typ.instantiate_aliases(region, aliases, var_store, introduced),
}
self.as_inner_mut().instantiate_aliases(
region,
aliases,
var_store,
new_lambda_sets,
new_infer_ext_vars,
)
}
pub fn contains_symbol(&self, rep_symbol: Symbol) -> bool {
@ -228,12 +227,18 @@ impl LambdaSet {
region: Region,
aliases: &'a F,
var_store: &mut VarStore,
introduced: &mut ImSet<Variable>,
new_lambda_sets: &mut ImSet<Variable>,
new_infer_ext_vars: &mut ImSet<Variable>,
) where
F: Fn(Symbol) -> Option<&'a Alias>,
{
self.0
.instantiate_aliases(region, aliases, var_store, introduced)
self.0.instantiate_aliases(
region,
aliases,
var_store,
new_lambda_sets,
new_infer_ext_vars,
)
}
}
@ -242,6 +247,7 @@ pub struct AliasCommon {
pub symbol: Symbol,
pub type_arguments: Vec<Loc<OptAbleType>>,
pub lambda_set_variables: Vec<LambdaSet>,
pub infer_ext_in_output_types: Vec<Type>,
}
/// Represents a collection of abilities bound to a type variable.
@ -394,6 +400,7 @@ pub enum Type {
symbol: Symbol,
type_arguments: Vec<OptAbleType>,
lambda_set_variables: Vec<LambdaSet>,
infer_ext_in_output_types: Vec<Type>,
actual: Box<Type>,
kind: AliasKind,
},
@ -476,12 +483,14 @@ impl Clone for Type {
symbol,
type_arguments,
lambda_set_variables,
infer_ext_in_output_types: infer_ext_in_output_variables,
actual,
kind,
} => Self::Alias {
symbol: *symbol,
type_arguments: type_arguments.clone(),
lambda_set_variables: lambda_set_variables.clone(),
infer_ext_in_output_types: infer_ext_in_output_variables.clone(),
actual: actual.clone(),
kind: *kind,
},
@ -631,6 +640,7 @@ impl fmt::Debug for Type {
symbol,
type_arguments,
lambda_set_variables,
infer_ext_in_output_types,
}) => {
write!(f, "(DelayedAlias {:?}", symbol)?;
@ -644,6 +654,10 @@ impl fmt::Debug for Type {
write!(f, " {}@{:?}", greek_letter, lambda_set.0)?;
}
for (i, infer_ext) in infer_ext_in_output_types.iter().enumerate() {
write!(f, " `{}@{:?}", i, infer_ext)?;
}
write!(f, ")")?;
Ok(())
@ -916,6 +930,7 @@ impl Type {
Type::DelayedAlias(AliasCommon {
type_arguments,
lambda_set_variables,
infer_ext_in_output_types,
..
}) => {
for value in type_arguments.iter_mut() {
@ -925,10 +940,15 @@ impl Type {
for lambda_set in lambda_set_variables.iter_mut() {
stack.push(lambda_set.as_inner_mut());
}
for infer_ext in infer_ext_in_output_types.iter_mut() {
stack.push(infer_ext);
}
}
Alias {
type_arguments,
lambda_set_variables,
infer_ext_in_output_types: infer_ext_in_output_variables,
actual,
..
} => {
@ -940,6 +960,10 @@ impl Type {
stack.push(lambda_set.as_inner_mut());
}
for infer_ext in infer_ext_in_output_variables.iter_mut() {
stack.push(infer_ext);
}
stack.push(actual);
}
HostExposedAlias {
@ -1038,6 +1062,7 @@ impl Type {
Type::DelayedAlias(AliasCommon {
type_arguments,
lambda_set_variables,
infer_ext_in_output_types,
..
}) => {
for value in type_arguments.iter_mut() {
@ -1047,10 +1072,15 @@ impl Type {
for lambda_set in lambda_set_variables.iter_mut() {
stack.push(lambda_set.as_inner_mut());
}
for typ in infer_ext_in_output_types.iter_mut() {
stack.push(typ);
}
}
Alias {
type_arguments,
lambda_set_variables,
infer_ext_in_output_types,
actual,
..
} => {
@ -1060,6 +1090,9 @@ impl Type {
for lambda_set in lambda_set_variables.iter_mut() {
stack.push(lambda_set.as_inner_mut());
}
for typ in infer_ext_in_output_types.iter_mut() {
stack.push(typ);
}
stack.push(actual);
}
@ -1144,6 +1177,7 @@ impl Type {
DelayedAlias(AliasCommon {
type_arguments,
lambda_set_variables: _no_aliases_in_lambda_sets,
infer_ext_in_output_types: _no_aliases_in_infer_ext_types,
..
}) => {
for ta in type_arguments {
@ -1231,6 +1265,7 @@ impl Type {
symbol,
type_arguments,
lambda_set_variables,
infer_ext_in_output_types: _,
..
}) => {
symbol == &rep_symbol
@ -1347,6 +1382,7 @@ impl Type {
aliases: &'a F,
var_store: &mut VarStore,
new_lambda_set_variables: &mut ImSet<Variable>,
new_infer_ext_vars: &mut ImSet<Variable>,
) where
F: Fn(Symbol) -> Option<&'a Alias>,
{
@ -1355,50 +1391,103 @@ impl Type {
match self {
Function(args, closure, ret) => {
for arg in args {
arg.instantiate_aliases(region, aliases, var_store, new_lambda_set_variables);
arg.instantiate_aliases(
region,
aliases,
var_store,
new_lambda_set_variables,
new_infer_ext_vars,
);
}
closure.instantiate_aliases(region, aliases, var_store, new_lambda_set_variables);
ret.instantiate_aliases(region, aliases, var_store, new_lambda_set_variables);
closure.instantiate_aliases(
region,
aliases,
var_store,
new_lambda_set_variables,
new_infer_ext_vars,
);
ret.instantiate_aliases(
region,
aliases,
var_store,
new_lambda_set_variables,
new_infer_ext_vars,
);
}
FunctionOrTagUnion(_, _, ext) => {
if let TypeExtension::Open(ext) = ext {
ext.instantiate_aliases(region, aliases, var_store, new_lambda_set_variables);
ext.instantiate_aliases(
region,
aliases,
var_store,
new_lambda_set_variables,
new_infer_ext_vars,
);
}
}
RecursiveTagUnion(_, tags, ext) | TagUnion(tags, ext) => {
for (_, args) in tags {
for x in args {
x.instantiate_aliases(region, aliases, var_store, new_lambda_set_variables);
x.instantiate_aliases(
region,
aliases,
var_store,
new_lambda_set_variables,
new_infer_ext_vars,
);
}
}
if let TypeExtension::Open(ext) = ext {
ext.instantiate_aliases(region, aliases, var_store, new_lambda_set_variables);
ext.instantiate_aliases(
region,
aliases,
var_store,
new_lambda_set_variables,
new_infer_ext_vars,
);
}
}
Record(fields, ext) => {
for (_, x) in fields.iter_mut() {
x.instantiate_aliases(region, aliases, var_store, new_lambda_set_variables);
x.instantiate_aliases(
region,
aliases,
var_store,
new_lambda_set_variables,
new_infer_ext_vars,
);
}
if let TypeExtension::Open(ext) = ext {
ext.instantiate_aliases(region, aliases, var_store, new_lambda_set_variables);
ext.instantiate_aliases(
region,
aliases,
var_store,
new_lambda_set_variables,
new_infer_ext_vars,
);
}
}
DelayedAlias(AliasCommon {
type_arguments,
lambda_set_variables,
infer_ext_in_output_types,
symbol: _,
}) => {
debug_assert!(lambda_set_variables
.iter()
.all(|lambda_set| matches!(lambda_set.0, Type::Variable(..))));
debug_assert!(infer_ext_in_output_types
.iter()
.all(|t| matches!(t, Type::Variable(..) | Type::EmptyTagUnion)));
type_arguments.iter_mut().for_each(|t| {
t.value.typ.instantiate_aliases(
region,
aliases,
var_store,
new_lambda_set_variables,
new_infer_ext_vars,
)
});
}
@ -1409,11 +1498,23 @@ impl Type {
..
} => {
for arg in type_args {
arg.instantiate_aliases(region, aliases, var_store, new_lambda_set_variables);
arg.instantiate_aliases(
region,
aliases,
var_store,
new_lambda_set_variables,
new_infer_ext_vars,
);
}
for arg in lambda_set_variables {
arg.instantiate_aliases(region, aliases, var_store, new_lambda_set_variables);
arg.instantiate_aliases(
region,
aliases,
var_store,
new_lambda_set_variables,
new_infer_ext_vars,
);
}
actual_type.instantiate_aliases(
@ -1421,6 +1522,7 @@ impl Type {
aliases,
var_store,
new_lambda_set_variables,
new_infer_ext_vars,
);
}
Alias {
@ -1435,11 +1537,18 @@ impl Type {
aliases,
var_store,
new_lambda_set_variables,
new_infer_ext_vars,
);
}
for arg in lambda_set_variables {
arg.instantiate_aliases(region, aliases, var_store, new_lambda_set_variables);
arg.instantiate_aliases(
region,
aliases,
var_store,
new_lambda_set_variables,
new_infer_ext_vars,
);
}
actual_type.instantiate_aliases(
@ -1447,12 +1556,14 @@ impl Type {
aliases,
var_store,
new_lambda_set_variables,
new_infer_ext_vars,
);
}
Apply(symbol, args, _) => {
if let Some(alias) = aliases(*symbol) {
// TODO switch to this, but we still need to check for recursion with the
// `else` branch
// `else` branch.
// We would also need to determine polarity correct.
if false {
let mut type_var_to_arg = Vec::new();
@ -1477,10 +1588,20 @@ impl Type {
lambda_set_variables.push(LambdaSet(Type::Variable(lvar)));
}
let mut infer_ext_in_output_types =
Vec::with_capacity(alias.infer_ext_in_output_variables.len());
for _ in 0..alias.infer_ext_in_output_variables.len() {
let var = var_store.fresh();
new_infer_ext_vars.insert(var);
infer_ext_in_output_types.push(Type::Variable(var));
}
let alias = Type::DelayedAlias(AliasCommon {
symbol: *symbol,
type_arguments: type_var_to_arg,
lambda_set_variables,
infer_ext_in_output_types,
});
*self = alias;
@ -1521,6 +1642,7 @@ impl Type {
aliases,
var_store,
new_lambda_set_variables,
new_infer_ext_vars,
);
named_args.push(OptAbleType {
typ: filler.value.clone(),
@ -1542,12 +1664,21 @@ impl Type {
unreachable!("at this point there should be only vars in there");
}
}
let mut infer_ext_in_output_types =
Vec::with_capacity(alias.infer_ext_in_output_variables.len());
for var in alias.infer_ext_in_output_variables.iter() {
let fresh = var_store.fresh();
new_infer_ext_vars.insert(fresh);
substitution.insert(*var, Type::Variable(fresh));
infer_ext_in_output_types.push(Type::Variable(fresh));
}
actual.instantiate_aliases(
region,
aliases,
var_store,
new_lambda_set_variables,
new_infer_ext_vars,
);
actual.substitute(&substitution);
@ -1572,6 +1703,7 @@ impl Type {
symbol: *symbol,
type_arguments: named_args,
lambda_set_variables,
infer_ext_in_output_types,
actual: Box::new(actual),
kind: alias.kind,
};
@ -1586,6 +1718,7 @@ impl Type {
aliases,
var_store,
new_lambda_set_variables,
new_infer_ext_vars,
);
}
}
@ -1638,11 +1771,8 @@ impl Type {
/// ```
pub fn is_narrow(&self) -> bool {
match self.shallow_dealias() {
Type::TagUnion(tags, ext) | Type::RecursiveTagUnion(_, tags, ext) => {
matches!(ext, TypeExtension::Closed)
&& tags.len() == 1
&& tags[0].1.len() == 1
&& tags[0].1[0].is_narrow()
Type::TagUnion(tags, _ext) | Type::RecursiveTagUnion(_, tags, _ext) => {
tags.len() == 1 && tags[0].1.len() == 1 && tags[0].1[0].is_narrow()
}
Type::Record(fields, ext) => match ext {
TypeExtension::Open(ext) => {
@ -1957,6 +2087,7 @@ fn variables_help_detailed(tipe: &Type, accum: &mut VariableDetail) {
DelayedAlias(AliasCommon {
type_arguments,
lambda_set_variables,
infer_ext_in_output_types: _,
..
}) => {
for arg in type_arguments {
@ -1974,6 +2105,7 @@ fn variables_help_detailed(tipe: &Type, accum: &mut VariableDetail) {
Alias {
type_arguments,
actual,
infer_ext_in_output_types: _,
..
} => {
for arg in type_arguments {
@ -2245,6 +2377,10 @@ pub struct Alias {
/// a |c|-> b
pub lambda_set_variables: Vec<LambdaSet>,
/// Extension variables that should be inferred in output positions, and closed in input
/// positions.
pub infer_ext_in_output_variables: Vec<Variable>,
pub recursion_variables: MutSet<Variable>,
pub typ: Type,
@ -3057,6 +3193,7 @@ fn instantiate_lambda_sets_as_unspecialized(
symbol: _,
type_arguments,
lambda_set_variables,
infer_ext_in_output_types: _, // these are irrelevant for ULS instantiation, since they're inferred or closed
}) => {
for lambda_set in lambda_set_variables.iter_mut() {
debug_assert!(matches!(lambda_set.0, Type::Variable(_)));
@ -3068,6 +3205,7 @@ fn instantiate_lambda_sets_as_unspecialized(
symbol: _,
type_arguments,
lambda_set_variables,
infer_ext_in_output_types: _, // these are irrelevant for ULS instantiation, since they're inferred
actual,
kind: _,
} => {