Skip to content

Commit 1bb59a7

Browse files
committed
Three-state enum for module origin
1 parent ace661b commit 1bb59a7

File tree

2 files changed

+78
-20
lines changed

2 files changed

+78
-20
lines changed

crates/ra_hir_def/src/nameres.rs

Lines changed: 75 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -100,19 +100,83 @@ impl std::ops::Index<LocalModuleId> for CrateDefMap {
100100
}
101101
}
102102

103+
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
104+
pub enum ModuleOrigin {
105+
/// It should not be `None` after collecting definitions.
106+
Root(Option<FileId>),
107+
/// Note that non-inline modules, by definition, live inside non-macro file.
108+
File(AstId<ast::Module>, FileId),
109+
Inline(AstId<ast::Module>),
110+
Block(AstId<ast::Block>),
111+
}
112+
113+
impl Default for ModuleOrigin {
114+
fn default() -> Self {
115+
ModuleOrigin::Root(None)
116+
}
117+
}
118+
119+
impl ModuleOrigin {
120+
pub fn root(file_id: FileId) -> Self {
121+
ModuleOrigin::Root(Some(file_id))
122+
}
123+
124+
pub fn not_sure_file(file: Option<FileId>, module: AstId<ast::Module>) -> Self {
125+
match file {
126+
None => ModuleOrigin::Inline(module),
127+
Some(file) => ModuleOrigin::File(module, file),
128+
}
129+
}
130+
131+
pub fn not_sure_mod(file: FileId, module: Option<AstId<ast::Module>>) -> Self {
132+
match module {
133+
None => ModuleOrigin::root(file),
134+
Some(module) => ModuleOrigin::File(module, file),
135+
}
136+
}
137+
138+
pub fn declaration(&self) -> Option<AstId<ast::Module>> {
139+
match self {
140+
ModuleOrigin::File(m, _) | ModuleOrigin::Inline(m) => Some(*m),
141+
ModuleOrigin::Root(_) | ModuleOrigin::Block(_) => None,
142+
}
143+
}
144+
145+
pub fn file_id(&self) -> Option<FileId> {
146+
match self {
147+
ModuleOrigin::File(_, file_id) | ModuleOrigin::Root(Some(file_id)) => Some(*file_id),
148+
_ => None,
149+
}
150+
}
151+
152+
/// Returns a node which defines this module.
153+
/// That is, a file or a `mod foo {}` with items.
154+
pub fn definition_source(
155+
&self,
156+
db: &impl DefDatabase,
157+
) -> InFile<Either<ast::SourceFile, ast::Module>> {
158+
match self {
159+
ModuleOrigin::File(_, file_id) | ModuleOrigin::Root(Some(file_id)) => {
160+
let file_id = *file_id;
161+
let sf = db.parse(file_id).tree();
162+
return InFile::new(file_id.into(), Either::Left(sf));
163+
}
164+
ModuleOrigin::Root(None) => unreachable!(),
165+
ModuleOrigin::Inline(m) => InFile::new(m.file_id, Either::Right(m.to_node(db))),
166+
// FIXME: right now it's never constructed, so it's fine to omit
167+
ModuleOrigin::Block(b) => unimplemented!(),
168+
}
169+
}
170+
}
171+
103172
#[derive(Default, Debug, PartialEq, Eq)]
104173
pub struct ModuleData {
105174
pub parent: Option<LocalModuleId>,
106175
pub children: FxHashMap<Name, LocalModuleId>,
107176
pub scope: ModuleScope,
108177

109-
// FIXME: these can't be both null, we need a three-state enum here.
110-
/// None for root
111-
pub declaration: Option<AstId<ast::Module>>,
112-
/// None for inline modules.
113-
///
114-
/// Note that non-inline modules, by definition, live inside non-macro file.
115-
pub definition: Option<FileId>,
178+
/// Where does this module come from?
179+
pub origin: ModuleOrigin,
116180

117181
pub impls: Vec<ImplId>,
118182
}
@@ -262,7 +326,7 @@ impl CrateDefMap {
262326
pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_ {
263327
self.modules
264328
.iter()
265-
.filter(move |(_id, data)| data.definition == Some(file_id))
329+
.filter(move |(_id, data)| data.origin.file_id() == Some(file_id))
266330
.map(|(id, _data)| id)
267331
}
268332

@@ -285,18 +349,13 @@ impl ModuleData {
285349
&self,
286350
db: &impl DefDatabase,
287351
) -> InFile<Either<ast::SourceFile, ast::Module>> {
288-
if let Some(file_id) = self.definition {
289-
let sf = db.parse(file_id).tree();
290-
return InFile::new(file_id.into(), Either::Left(sf));
291-
}
292-
let decl = self.declaration.unwrap();
293-
InFile::new(decl.file_id, Either::Right(decl.to_node(db)))
352+
self.origin.definition_source(db)
294353
}
295354

296355
/// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`.
297-
/// `None` for the crate root.
356+
/// `None` for the crate root or block.
298357
pub fn declaration_source(&self, db: &impl DefDatabase) -> Option<InFile<ast::Module>> {
299-
let decl = self.declaration?;
358+
let decl = self.origin.declaration()?;
300359
let value = decl.to_node(db);
301360
Some(InFile { file_id: decl.file_id, value })
302361
}

crates/ra_hir_def/src/nameres/collector.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use crate::{
1919
db::DefDatabase,
2020
nameres::{
2121
diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
22-
raw, BuiltinShadowMode, CrateDefMap, ModuleData, Resolution, ResolveMode,
22+
raw, BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, Resolution, ResolveMode,
2323
},
2424
path::{Path, PathKind},
2525
per_ns::PerNs,
@@ -131,7 +131,7 @@ where
131131
let file_id = crate_graph.crate_root(self.def_map.krate);
132132
let raw_items = self.db.raw_items(file_id.into());
133133
let module_id = self.def_map.root;
134-
self.def_map.modules[module_id].definition = Some(file_id);
134+
self.def_map.modules[module_id].origin = ModuleOrigin::root(file_id);
135135
ModCollector {
136136
def_collector: &mut *self,
137137
module_id,
@@ -669,8 +669,7 @@ where
669669
let modules = &mut self.def_collector.def_map.modules;
670670
let res = modules.alloc(ModuleData::default());
671671
modules[res].parent = Some(self.module_id);
672-
modules[res].declaration = Some(declaration);
673-
modules[res].definition = definition;
672+
modules[res].origin = ModuleOrigin::not_sure_file(definition, declaration);
674673
modules[res].scope.legacy_macros = modules[self.module_id].scope.legacy_macros.clone();
675674
modules[self.module_id].children.insert(name.clone(), res);
676675
let resolution = Resolution {

0 commit comments

Comments
 (0)