pub mod checks;
mod expressions;
mod interface;
mod unify;
mod validation;
use rustc_hash::FxHashMap as HashMap;
use super::Checker;
use syntax::ast::Expression;
use syntax::program::{File, FileImport};
impl Checker<'_, '_> {
pub fn infer_module(&mut self, module_id: &str) {
self.cursor.module_id = module_id.to_string();
let files: Vec<File> = {
let module = self
.store
.get_module_mut(module_id)
.expect("module must exist for inference");
std::mem::take(&mut module.files).into_values().collect()
};
for file in files {
let imports = file.imports();
self.reset_scopes();
self.cursor.file_id = Some(file.id);
self.put_prelude_in_scope();
self.put_unprefixed_module_in_scope(module_id);
self.put_imported_modules_in_scope(&imports);
self.check_definition_module_collisions(&file.items, &imports);
let inferred_items: Vec<_> = file
.items
.into_iter()
.map(|item| {
let type_var = self.new_type_var();
self.infer_expression(item, &type_var)
})
.collect();
self.run_post_inference_checks();
self.check_reference_sibling_aliasing(&inferred_items);
let typed_file = File {
id: file.id,
module_id: file.module_id,
name: file.name,
source: file.source,
items: inferred_items,
};
self.store.store_file(module_id, typed_file);
}
self.cursor.file_id = None;
}
fn check_definition_module_collisions(&mut self, items: &[Expression], imports: &[FileImport]) {
let alias_to_path: HashMap<String, String> = imports
.iter()
.filter_map(|imp| {
imp.effective_alias()
.map(|alias| (alias, imp.name.to_string()))
})
.collect();
for item in items {
let (definition_name, name_span) = match item {
Expression::Function {
name, name_span, ..
} => (name.as_str(), *name_span),
Expression::Struct {
name, name_span, ..
} => (name.as_str(), *name_span),
Expression::Enum {
name, name_span, ..
} => (name.as_str(), *name_span),
Expression::ValueEnum {
name, name_span, ..
} => (name.as_str(), *name_span),
Expression::TypeAlias {
name, name_span, ..
} => (name.as_str(), *name_span),
Expression::Const {
identifier,
identifier_span,
..
} => (identifier.as_str(), *identifier_span),
Expression::Interface {
name, name_span, ..
} => (name.as_str(), *name_span),
_ => continue,
};
if let Some(import_path) = alias_to_path.get(definition_name) {
self.sink
.push(diagnostics::infer::definition_shadows_import(
definition_name,
import_path,
name_span,
));
}
}
}
}