mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 00:01:16 +00:00
Add some copy tests
This commit is contained in:
parent
480b84bec1
commit
79e11547be
1 changed files with 211 additions and 2 deletions
|
@ -15,8 +15,8 @@ pub fn deep_copy_type_vars<'a>(
|
||||||
let cloned_var = help(arena, subs, &mut copied, var);
|
let cloned_var = help(arena, subs, &mut copied, var);
|
||||||
|
|
||||||
debug_assert!(match cloned_var {
|
debug_assert!(match cloned_var {
|
||||||
Some(_) => copied.is_empty(),
|
Some(_) => !copied.is_empty(),
|
||||||
None => !copied.is_empty(),
|
None => copied.is_empty(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// we have tracked all visited variables, and can now traverse them
|
// we have tracked all visited variables, and can now traverse them
|
||||||
|
@ -292,3 +292,212 @@ pub fn deep_copy_type_vars<'a>(
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::deep_copy_type_vars;
|
||||||
|
use bumpalo::Bump;
|
||||||
|
use roc_module::ident::TagName;
|
||||||
|
use roc_module::symbol::Symbol;
|
||||||
|
use roc_types::{
|
||||||
|
subs::{
|
||||||
|
Content, Content::*, Descriptor, FlatType::*, Mark, OptVariable, Rank, RecordFields,
|
||||||
|
Subs, SubsIndex, UnionTags, Variable,
|
||||||
|
},
|
||||||
|
types::RecordField,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
fn new_var(subs: &mut Subs, content: Content) -> Variable {
|
||||||
|
subs.fresh(Descriptor {
|
||||||
|
content,
|
||||||
|
rank: Rank::toplevel(),
|
||||||
|
mark: Mark::NONE,
|
||||||
|
copy: OptVariable::NONE,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn copy_flex_var() {
|
||||||
|
let mut subs = Subs::new();
|
||||||
|
let arena = Bump::new();
|
||||||
|
|
||||||
|
let field_name = SubsIndex::push_new(&mut subs.field_names, "a".into());
|
||||||
|
let var = new_var(&mut subs, FlexVar(Some(field_name)));
|
||||||
|
|
||||||
|
let mut copies = deep_copy_type_vars(&arena, &mut subs, var);
|
||||||
|
|
||||||
|
assert_eq!(copies.len(), 1);
|
||||||
|
let (original, new) = copies.pop().unwrap();
|
||||||
|
assert_ne!(original, new);
|
||||||
|
|
||||||
|
assert_eq!(original, var);
|
||||||
|
match subs.get_content_without_compacting(new) {
|
||||||
|
FlexVar(Some(name)) => {
|
||||||
|
assert_eq!(subs[*name].as_str(), "a");
|
||||||
|
}
|
||||||
|
it => assert!(false, "{:?}", it),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn copy_rigid_var() {
|
||||||
|
let mut subs = Subs::new();
|
||||||
|
let arena = Bump::new();
|
||||||
|
|
||||||
|
let field_name = SubsIndex::push_new(&mut subs.field_names, "a".into());
|
||||||
|
let var = new_var(&mut subs, RigidVar(field_name));
|
||||||
|
|
||||||
|
let mut copies = deep_copy_type_vars(&arena, &mut subs, var);
|
||||||
|
|
||||||
|
assert_eq!(copies.len(), 1);
|
||||||
|
let (original, new) = copies.pop().unwrap();
|
||||||
|
assert_ne!(original, new);
|
||||||
|
|
||||||
|
assert_eq!(original, var);
|
||||||
|
match subs.get_content_without_compacting(new) {
|
||||||
|
RigidVar(name) => {
|
||||||
|
assert_eq!(subs[*name].as_str(), "a");
|
||||||
|
}
|
||||||
|
it => assert!(false, "{:?}", it),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn copy_flex_able_var() {
|
||||||
|
let mut subs = Subs::new();
|
||||||
|
let arena = Bump::new();
|
||||||
|
|
||||||
|
let field_name = SubsIndex::push_new(&mut subs.field_names, "a".into());
|
||||||
|
let var = new_var(&mut subs, FlexAbleVar(Some(field_name), Symbol::UNDERSCORE));
|
||||||
|
|
||||||
|
let mut copies = deep_copy_type_vars(&arena, &mut subs, var);
|
||||||
|
|
||||||
|
assert_eq!(copies.len(), 1);
|
||||||
|
let (original, new) = copies.pop().unwrap();
|
||||||
|
assert_ne!(original, new);
|
||||||
|
|
||||||
|
assert_eq!(original, var);
|
||||||
|
match subs.get_content_without_compacting(new) {
|
||||||
|
FlexAbleVar(Some(name), Symbol::UNDERSCORE) => {
|
||||||
|
assert_eq!(subs[*name].as_str(), "a");
|
||||||
|
}
|
||||||
|
it => assert!(false, "{:?}", it),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn copy_rigid_able_var() {
|
||||||
|
let mut subs = Subs::new();
|
||||||
|
let arena = Bump::new();
|
||||||
|
|
||||||
|
let field_name = SubsIndex::push_new(&mut subs.field_names, "a".into());
|
||||||
|
let var = new_var(&mut subs, RigidAbleVar(field_name, Symbol::UNDERSCORE));
|
||||||
|
|
||||||
|
let mut copies = deep_copy_type_vars(&arena, &mut subs, var);
|
||||||
|
|
||||||
|
assert_eq!(copies.len(), 1);
|
||||||
|
let (original, new) = copies.pop().unwrap();
|
||||||
|
assert_ne!(original, new);
|
||||||
|
|
||||||
|
assert_eq!(original, var);
|
||||||
|
match subs.get_content_without_compacting(new) {
|
||||||
|
RigidAbleVar(name, Symbol::UNDERSCORE) => {
|
||||||
|
assert_eq!(subs[*name].as_str(), "a");
|
||||||
|
}
|
||||||
|
it => assert!(false, "{:?}", it),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn types_without_type_vars_should_not_be_copied() {
|
||||||
|
let mut subs = Subs::new();
|
||||||
|
let arena = Bump::new();
|
||||||
|
|
||||||
|
let cases = &[
|
||||||
|
RecursionVar {
|
||||||
|
structure: new_var(&mut subs, Structure(EmptyTagUnion)),
|
||||||
|
opt_name: None,
|
||||||
|
},
|
||||||
|
Structure(Record(
|
||||||
|
RecordFields::insert_into_subs(
|
||||||
|
&mut subs,
|
||||||
|
[("a".into(), RecordField::Required(Variable::BOOL))],
|
||||||
|
),
|
||||||
|
Variable::EMPTY_RECORD,
|
||||||
|
)),
|
||||||
|
Structure(TagUnion(
|
||||||
|
UnionTags::insert_into_subs(
|
||||||
|
&mut subs,
|
||||||
|
[(TagName::Tag("A".into()), [Variable::BOOL])],
|
||||||
|
),
|
||||||
|
Variable::EMPTY_TAG_UNION,
|
||||||
|
)),
|
||||||
|
Structure(RecursiveTagUnion(
|
||||||
|
Variable::EMPTY_TAG_UNION,
|
||||||
|
UnionTags::insert_into_subs(
|
||||||
|
&mut subs,
|
||||||
|
[(TagName::Tag("A".into()), [Variable::BOOL])],
|
||||||
|
),
|
||||||
|
Variable::EMPTY_TAG_UNION,
|
||||||
|
)),
|
||||||
|
Error,
|
||||||
|
];
|
||||||
|
|
||||||
|
for &content in cases {
|
||||||
|
let var = new_var(&mut subs, content);
|
||||||
|
|
||||||
|
let copies = deep_copy_type_vars(&arena, &mut subs, var);
|
||||||
|
|
||||||
|
assert!(copies.is_empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn copy_type_with_copied_reference() {
|
||||||
|
let mut subs = Subs::new();
|
||||||
|
let arena = Bump::new();
|
||||||
|
|
||||||
|
let flex_var = new_var(&mut subs, FlexVar(None));
|
||||||
|
|
||||||
|
let content = Structure(TagUnion(
|
||||||
|
UnionTags::insert_into_subs(&mut subs, [(TagName::Tag("A".into()), [flex_var])]),
|
||||||
|
Variable::EMPTY_TAG_UNION,
|
||||||
|
));
|
||||||
|
|
||||||
|
let tag_var = new_var(&mut subs, content);
|
||||||
|
|
||||||
|
let mut copies = deep_copy_type_vars(&arena, &mut subs, tag_var);
|
||||||
|
|
||||||
|
assert_eq!(copies.len(), 2);
|
||||||
|
let (original_flex, new_flex) = copies[0];
|
||||||
|
assert_ne!(original_flex, new_flex);
|
||||||
|
assert_eq!(original_flex, flex_var);
|
||||||
|
|
||||||
|
let (original_tag, new_tag) = copies[1];
|
||||||
|
assert_ne!(original_tag, new_tag);
|
||||||
|
assert_eq!(original_tag, tag_var);
|
||||||
|
|
||||||
|
match subs.get_content_without_compacting(new_tag) {
|
||||||
|
Structure(TagUnion(union_tags, Variable::EMPTY_TAG_UNION)) => {
|
||||||
|
let (tag_name, vars) = union_tags.iter_all().next().unwrap();
|
||||||
|
match &subs[tag_name] {
|
||||||
|
TagName::Tag(upper) => assert_eq!(upper.as_str(), "A"),
|
||||||
|
_ => assert!(false, "{:?}", tag_name),
|
||||||
|
}
|
||||||
|
|
||||||
|
let vars = subs[vars];
|
||||||
|
assert_eq!(vars.len(), 1);
|
||||||
|
|
||||||
|
let var = subs[vars.into_iter().next().unwrap()];
|
||||||
|
assert_eq!(var, new_flex);
|
||||||
|
}
|
||||||
|
it => assert!(false, "{:?}", it),
|
||||||
|
}
|
||||||
|
|
||||||
|
assert!(matches!(
|
||||||
|
subs.get_content_without_compacting(new_flex),
|
||||||
|
FlexVar(None)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue