Merge pull request #5179 from roc-lang/i5143-tuple-abilities

Implement ability obligation checking and derivation for tuples
This commit is contained in:
Ayaz 2023-03-25 15:51:39 -05:00 committed by GitHub
commit 61dd5cc8c7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 4225 additions and 2296 deletions

View file

@ -2,7 +2,7 @@ use roc_module::{ident::Lowercase, symbol::Symbol};
use roc_types::subs::{Content, FlatType, Subs, Variable};
use crate::{
util::{check_derivable_ext_var, debug_name_record},
util::{check_derivable_ext_var, debug_name_record, debug_name_tuple},
DeriveError,
};
@ -18,6 +18,7 @@ pub enum FlatDecodableKey {
// Unfortunate that we must allocate here, c'est la vie
Record(Vec<Lowercase>),
Tuple(u32),
}
impl FlatDecodableKey {
@ -25,6 +26,7 @@ impl FlatDecodableKey {
match self {
FlatDecodableKey::List() => "list".to_string(),
FlatDecodableKey::Record(fields) => debug_name_record(fields),
FlatDecodableKey::Tuple(arity) => debug_name_tuple(*arity),
}
}
}
@ -61,8 +63,14 @@ impl FlatDecodable {
Ok(Key(FlatDecodableKey::Record(field_names)))
}
FlatType::Tuple(_elems, _ext) => {
todo!()
FlatType::Tuple(elems, ext) => {
let (elems_iter, ext) = elems.sorted_iterator_and_ext(subs, ext);
check_derivable_ext_var(subs, ext, |ext| {
matches!(ext, Content::Structure(FlatType::EmptyTuple))
})?;
Ok(Key(FlatDecodableKey::Tuple(elems_iter.count() as _)))
}
FlatType::TagUnion(_tags, _ext) | FlatType::RecursiveTagUnion(_, _tags, _ext) => {
Err(Underivable) // yet

View file

@ -5,7 +5,7 @@ use roc_module::{
use roc_types::subs::{Content, FlatType, GetSubsSlice, Subs, Variable};
use crate::{
util::{check_derivable_ext_var, debug_name_record, debug_name_tag},
util::{check_derivable_ext_var, debug_name_record, debug_name_tag, debug_name_tuple},
DeriveError,
};
@ -22,6 +22,7 @@ pub enum FlatEncodableKey {
Dict(/* takes two variables */),
// Unfortunate that we must allocate here, c'est la vie
Record(Vec<Lowercase>),
Tuple(u32),
TagUnion(Vec<(TagName, u16)>),
}
@ -32,6 +33,7 @@ impl FlatEncodableKey {
FlatEncodableKey::Set() => "set".to_string(),
FlatEncodableKey::Dict() => "dict".to_string(),
FlatEncodableKey::Record(fields) => debug_name_record(fields),
FlatEncodableKey::Tuple(arity) => debug_name_tuple(*arity),
FlatEncodableKey::TagUnion(tags) => debug_name_tag(tags),
}
}
@ -66,8 +68,14 @@ impl FlatEncodable {
Ok(Key(FlatEncodableKey::Record(field_names)))
}
FlatType::Tuple(_elems, _ext) => {
todo!()
FlatType::Tuple(elems, ext) => {
let (elems_iter, ext) = elems.sorted_iterator_and_ext(subs, ext);
check_derivable_ext_var(subs, ext, |ext| {
matches!(ext, Content::Structure(FlatType::EmptyTuple))
})?;
Ok(Key(FlatEncodableKey::Tuple(elems_iter.count() as _)))
}
FlatType::TagUnion(tags, ext) | FlatType::RecursiveTagUnion(_, tags, ext) => {
// The recursion var doesn't matter, because the derived implementation will only

View file

@ -5,7 +5,7 @@ use roc_module::{
use roc_types::subs::{Content, FlatType, GetSubsSlice, Subs, Variable};
use crate::{
util::{check_derivable_ext_var, debug_name_record, debug_name_tag},
util::{check_derivable_ext_var, debug_name_record, debug_name_tag, debug_name_tuple},
DeriveError,
};
@ -21,6 +21,7 @@ pub enum FlatHash {
pub enum FlatHashKey {
// Unfortunate that we must allocate here, c'est la vie
Record(Vec<Lowercase>),
Tuple(u32),
TagUnion(Vec<(TagName, u16)>),
}
@ -28,6 +29,7 @@ impl FlatHashKey {
pub(crate) fn debug_name(&self) -> String {
match self {
FlatHashKey::Record(fields) => debug_name_record(fields),
FlatHashKey::Tuple(arity) => debug_name_tuple(*arity),
FlatHashKey::TagUnion(tags) => debug_name_tag(tags),
}
}
@ -65,8 +67,14 @@ impl FlatHash {
Ok(Key(FlatHashKey::Record(field_names)))
}
FlatType::Tuple(_elems, _ext) => {
todo!();
FlatType::Tuple(elems, ext) => {
let (elems_iter, ext) = elems.sorted_iterator_and_ext(subs, ext);
check_derivable_ext_var(subs, ext, |ext| {
matches!(ext, Content::Structure(FlatType::EmptyTuple))
})?;
Ok(Key(FlatHashKey::Tuple(elems_iter.count() as _)))
}
FlatType::TagUnion(tags, ext) | FlatType::RecursiveTagUnion(_, tags, ext) => {
// The recursion var doesn't matter, because the derived implementation will only

View file

@ -43,6 +43,10 @@ pub(crate) fn debug_name_record(fields: &[Lowercase]) -> String {
str
}
pub(crate) fn debug_name_tuple(arity: u32) -> String {
format!("(arity:{arity})")
}
pub(crate) fn debug_name_tag(tags: &[(TagName, u16)]) -> String {
let mut str = String::from('[');
tags.iter().enumerate().for_each(|(i, (tag, arity))| {