Skip to main content

lisette_semantics/checker/infer/
mod.rs

1pub 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}