mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 16:21:11 +00:00
add test for transitive alias import
This commit is contained in:
parent
984cf744e3
commit
cf80e2852f
9 changed files with 135 additions and 27 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2524,6 +2524,7 @@ dependencies = [
|
|||
"roc_solve",
|
||||
"roc_types",
|
||||
"roc_unify",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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:")]),
|
||||
}
|
||||
|
|
|
@ -154,9 +154,6 @@ pub fn run(
|
|||
constraint,
|
||||
);
|
||||
|
||||
//dbg!(&subs, &state.env.vars_by_symbol);
|
||||
//panic!();
|
||||
|
||||
(Solved(subs), state.env)
|
||||
}
|
||||
|
||||
|
|
|
@ -1007,7 +1007,7 @@ pub enum Category {
|
|||
StrInterpolation,
|
||||
|
||||
// storing variables in the ast
|
||||
Storage,
|
||||
Storage(&'static str, u32),
|
||||
|
||||
// control flow
|
||||
If,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 ]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue