add test for transitive alias import

This commit is contained in:
Folkert 2020-11-11 01:19:54 +01:00
parent 984cf744e3
commit cf80e2852f
9 changed files with 135 additions and 27 deletions

1
Cargo.lock generated
View file

@ -2524,6 +2524,7 @@ dependencies = [
"roc_solve",
"roc_types",
"roc_unify",
"tempfile",
]
[[package]]

View file

@ -227,20 +227,8 @@ fn can_annotation_help(
// instantiate variables
actual.substitute(&substitutions);
// Type::Alias(symbol, vars, Box::new(actual))
if vars.is_empty() {
let actual_var = var_store.fresh();
introduced_variables.insert_host_exposed_alias(symbol, actual_var);
Type::HostExposedAlias {
name: symbol,
arguments: vars,
actual: Box::new(actual),
actual_var,
}
} else {
Type::Alias(symbol, vars, Box::new(actual))
}
}
None => {
let mut args = Vec::new();
@ -373,7 +361,7 @@ fn can_annotation_help(
// Type::Alias(symbol, vars, Box::new(alias.typ.clone()))
if vars.is_empty() {
if vars.is_empty() && env.home == symbol.module_id() {
let actual_var = var_store.fresh();
introduced_variables.insert_host_exposed_alias(symbol, actual_var);
Type::HostExposedAlias {

View file

@ -25,6 +25,7 @@ crossbeam = "0.7"
num_cpus = "1"
[dev-dependencies]
tempfile = "3.1.0"
pretty_assertions = "0.5.1"
maplit = "1.0.1"
indoc = "0.3.3"

View file

@ -1,4 +1,6 @@
#[macro_use]
extern crate indoc;
#[macro_use]
extern crate pretty_assertions;
#[macro_use]
extern crate maplit;
@ -28,6 +30,87 @@ mod test_load {
// HELPERS
fn multiple_modules(files: Vec<(&str, &str)>) -> LoadedModule {
multiple_modules_help(files).unwrap()
}
fn multiple_modules_help(mut files: Vec<(&str, &str)>) -> Result<LoadedModule, std::io::Error> {
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
use tempfile::tempdir;
let arena = Bump::new();
let arena = &arena;
let stdlib = roc_builtins::std::standard_stdlib();
let mut file_handles: Vec<_> = Vec::new();
let exposed_types = MutMap::default();
let loaded = {
// create a temporary directory
let dir = tempdir()?;
let app_module = files.pop().unwrap();
let interfaces = files;
debug_assert!(
app_module.1.starts_with("app"),
"The final module should be the application module"
);
for (name, source) in interfaces {
let mut filename = PathBuf::from(name);
filename.set_extension("roc");
let file_path = dir.path().join(filename.clone());
let mut file = File::create(file_path)?;
writeln!(file, "{}", source)?;
file_handles.push(file);
}
let result = {
let (name, source) = app_module;
let filename = PathBuf::from(name);
let file_path = dir.path().join(filename.clone());
let full_file_path = PathBuf::from(file_path.clone());
let mut file = File::create(file_path)?;
writeln!(file, "{}", source)?;
file_handles.push(file);
roc_load::file::load_and_typecheck(
arena,
full_file_path,
stdlib,
dir.path(),
exposed_types,
)
};
dir.close()?;
result
};
let mut loaded_module = loaded.expect("failed to load module");
let home = loaded_module.module_id;
assert_eq!(
loaded_module.can_problems.remove(&home).unwrap_or_default(),
Vec::new()
);
assert_eq!(
loaded_module
.type_problems
.remove(&home)
.unwrap_or_default(),
Vec::new()
);
Ok(loaded_module)
}
fn load_fixture(
dir_name: &str,
module_name: &str,
@ -146,6 +229,46 @@ mod test_load {
// TESTS
#[test]
fn import_transitive_alias() {
// this had a bug where NodeColor was HostExposed, and it's `actual_var` conflicted
// with variables in the importee
let modules = vec![
(
"RBTree",
indoc!(
r#"
interface RBTree exposes [ Dict, empty ] imports []
# The color of a node. Leaves are considered Black.
NodeColor : [ Red, Black ]
Dict k v : [ Node NodeColor k v (Dict k v) (Dict k v), Empty ]
# Create an empty dictionary.
empty : Dict k v
empty =
Empty
"#
),
),
(
"Main",
indoc!(
r#"
app Test provides [ main ] imports [ RBTree ]
empty : RBTree.Dict Int Int
empty = RBTree.empty
main = empty
"#
),
),
];
multiple_modules(modules);
}
#[test]
fn interface_with_deps() {
let subs_by_module = MutMap::default();

View file

@ -972,7 +972,7 @@ fn add_category<'b>(
this_is,
alloc.text(" an uniqueness attribute of type:"),
]),
Storage => alloc.concat(vec![this_is, alloc.text(" a value of type:")]),
Storage(_file, _line) => alloc.concat(vec![this_is, alloc.text(" a value of type:")]),
DefaultValue(_) => alloc.concat(vec![this_is, alloc.text(" a default field of type:")]),
}

View file

@ -154,9 +154,6 @@ pub fn run(
constraint,
);
//dbg!(&subs, &state.env.vars_by_symbol);
//panic!();
(Solved(subs), state.env)
}

View file

@ -1007,7 +1007,7 @@ pub enum Category {
StrInterpolation,
// storing variables in the ast
Storage,
Storage(&'static str, u32),
// control flow
If,

View file

@ -1,12 +1,12 @@
app Main provides [ main ] imports [ Effect, ConsList ]
app Main provides [ main ] imports [ Effect, RBTree ]
empty : ConsList.ConsList Int
empty = ConsList.empty
foo : RBTree.Dict Int Int
foo = Empty # RBTree.empty
main : Effect.Effect {} as Fx
main =
# if ConsList.isEmpty empty then
if ConsList.len empty == 0 then
# if RBTree.isEmpty empty then
if RBTree.size foo == 0 then
Effect.putLine "Yay"
|> Effect.after (\{} -> Effect.getLine)
|> Effect.after (\line -> Effect.putLine line)

View file

@ -1,6 +1,4 @@
interface RBTree exposes [ Dict, empty, singleton, size, isEmpty, insert, remove, balance ] imports []
# TODO remove `balance` from the exposed list
# todo change `foobar` to `balance`
interface RBTree exposes [ Dict, empty, size, singleton ] imports []
# The color of a node. Leaves are considered Black.
NodeColor : [ Red, Black ]