lisette_semantics/checker/infer/
mod.rs1pub mod checks;
2mod expressions;
3mod interface;
4mod unify;
5mod validation;
6
7use rustc_hash::FxHashMap as HashMap;
8
9use super::Checker;
10use syntax::ast::Expression;
11use syntax::program::{File, FileImport};
12
13impl Checker<'_, '_> {
14 pub fn infer_module(&mut self, module_id: &str) {
15 self.cursor.module_id = module_id.to_string();
16
17 let files: Vec<File> = {
18 let module = self
19 .store
20 .get_module_mut(module_id)
21 .expect("module must exist for inference");
22 std::mem::take(&mut module.files).into_values().collect()
23 };
24
25 for file in files {
26 let imports = file.imports();
27
28 self.reset_scopes();
29 self.cursor.file_id = Some(file.id);
30 self.put_prelude_in_scope();
31 self.put_unprefixed_module_in_scope(module_id);
32 self.put_imported_modules_in_scope(&imports);
33 self.check_definition_module_collisions(&file.items, &imports);
34
35 let inferred_items: Vec<_> = file
36 .items
37 .into_iter()
38 .map(|item| {
39 let type_var = self.new_type_var();
40 self.infer_expression(item, &type_var)
41 })
42 .collect();
43
44 self.run_post_inference_checks();
45 self.check_reference_sibling_aliasing(&inferred_items);
46
47 let typed_file = File {
48 id: file.id,
49 module_id: file.module_id,
50 name: file.name,
51 source: file.source,
52 items: inferred_items,
53 };
54
55 self.store.store_file(module_id, typed_file);
56 }
57
58 self.cursor.file_id = None;
59 }
60
61 fn check_definition_module_collisions(&mut self, items: &[Expression], imports: &[FileImport]) {
62 let alias_to_path: HashMap<String, String> = imports
63 .iter()
64 .filter_map(|imp| {
65 imp.effective_alias()
66 .map(|alias| (alias, imp.name.to_string()))
67 })
68 .collect();
69
70 for item in items {
71 let (definition_name, name_span) = match item {
72 Expression::Function {
73 name, name_span, ..
74 } => (name.as_str(), *name_span),
75 Expression::Struct {
76 name, name_span, ..
77 } => (name.as_str(), *name_span),
78 Expression::Enum {
79 name, name_span, ..
80 } => (name.as_str(), *name_span),
81 Expression::ValueEnum {
82 name, name_span, ..
83 } => (name.as_str(), *name_span),
84 Expression::TypeAlias {
85 name, name_span, ..
86 } => (name.as_str(), *name_span),
87 Expression::Const {
88 identifier,
89 identifier_span,
90 ..
91 } => (identifier.as_str(), *identifier_span),
92 Expression::Interface {
93 name, name_span, ..
94 } => (name.as_str(), *name_span),
95 _ => continue,
96 };
97
98 if let Some(import_path) = alias_to_path.get(definition_name) {
99 self.sink
100 .push(diagnostics::infer::definition_shadows_import(
101 definition_name,
102 import_path,
103 name_span,
104 ));
105 }
106 }
107 }
108}