aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def')
-rw-r--r--crates/hir_def/src/data.rs6
-rw-r--r--crates/hir_def/src/item_tree.rs2
-rw-r--r--crates/hir_def/src/item_tree/lower.rs10
-rw-r--r--crates/hir_def/src/item_tree/pretty.rs6
-rw-r--r--crates/hir_def/src/item_tree/tests.rs4
-rw-r--r--crates/hir_def/src/nameres/collector.rs57
-rw-r--r--crates/hir_def/src/nameres/diagnostics.rs9
-rw-r--r--crates/hir_def/src/nameres/proc_macro.rs10
-rw-r--r--crates/hir_def/src/nameres/tests/incremental.rs74
-rw-r--r--crates/hir_def/src/test_db.rs7
10 files changed, 150 insertions, 35 deletions
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs
index 8bcac60ef..d2bb381be 100644
--- a/crates/hir_def/src/data.rs
+++ b/crates/hir_def/src/data.rs
@@ -22,6 +22,7 @@ pub struct FunctionData {
22 pub name: Name, 22 pub name: Name,
23 pub params: Vec<Interned<TypeRef>>, 23 pub params: Vec<Interned<TypeRef>>,
24 pub ret_type: Interned<TypeRef>, 24 pub ret_type: Interned<TypeRef>,
25 pub async_ret_type: Option<Interned<TypeRef>>,
25 pub attrs: Attrs, 26 pub attrs: Attrs,
26 pub visibility: RawVisibility, 27 pub visibility: RawVisibility,
27 pub abi: Option<Interned<str>>, 28 pub abi: Option<Interned<str>>,
@@ -63,6 +64,7 @@ impl FunctionData {
63 }) 64 })
64 .collect(), 65 .collect(),
65 ret_type: func.ret_type.clone(), 66 ret_type: func.ret_type.clone(),
67 async_ret_type: func.async_ret_type.clone(),
66 attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), 68 attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()),
67 visibility: item_tree[func.visibility].clone(), 69 visibility: item_tree[func.visibility].clone(),
68 abi: func.abi.clone(), 70 abi: func.abi.clone(),
@@ -141,7 +143,6 @@ pub struct TraitData {
141 pub is_auto: bool, 143 pub is_auto: bool,
142 pub is_unsafe: bool, 144 pub is_unsafe: bool,
143 pub visibility: RawVisibility, 145 pub visibility: RawVisibility,
144 pub bounds: Box<[Interned<TypeBound>]>,
145} 146}
146 147
147impl TraitData { 148impl TraitData {
@@ -155,7 +156,6 @@ impl TraitData {
155 let module_id = tr_loc.container; 156 let module_id = tr_loc.container;
156 let container = AssocContainerId::TraitId(tr); 157 let container = AssocContainerId::TraitId(tr);
157 let visibility = item_tree[tr_def.visibility].clone(); 158 let visibility = item_tree[tr_def.visibility].clone();
158 let bounds = tr_def.bounds.clone();
159 let mut expander = Expander::new(db, tr_loc.id.file_id(), module_id); 159 let mut expander = Expander::new(db, tr_loc.id.file_id(), module_id);
160 160
161 let items = collect_items( 161 let items = collect_items(
@@ -168,7 +168,7 @@ impl TraitData {
168 100, 168 100,
169 ); 169 );
170 170
171 Arc::new(TraitData { name, items, is_auto, is_unsafe, visibility, bounds }) 171 Arc::new(TraitData { name, items, is_auto, is_unsafe, visibility })
172 } 172 }
173 173
174 pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ { 174 pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ {
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index f84c4cf2b..227337a8d 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -580,6 +580,7 @@ pub struct Function {
580 pub abi: Option<Interned<str>>, 580 pub abi: Option<Interned<str>>,
581 pub params: IdRange<Param>, 581 pub params: IdRange<Param>,
582 pub ret_type: Interned<TypeRef>, 582 pub ret_type: Interned<TypeRef>,
583 pub async_ret_type: Option<Interned<TypeRef>>,
583 pub ast_id: FileAstId<ast::Fn>, 584 pub ast_id: FileAstId<ast::Fn>,
584 pub(crate) flags: FnFlags, 585 pub(crate) flags: FnFlags,
585} 586}
@@ -661,7 +662,6 @@ pub struct Trait {
661 pub generic_params: Interned<GenericParams>, 662 pub generic_params: Interned<GenericParams>,
662 pub is_auto: bool, 663 pub is_auto: bool,
663 pub is_unsafe: bool, 664 pub is_unsafe: bool,
664 pub bounds: Box<[Interned<TypeBound>]>,
665 pub items: Box<[AssocItem]>, 665 pub items: Box<[AssocItem]>,
666 pub ast_id: FileAstId<ast::Trait>, 666 pub ast_id: FileAstId<ast::Trait>,
667} 667}
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index 40f3428b7..6208facd5 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -356,12 +356,13 @@ impl<'a> Ctx<'a> {
356 _ => TypeRef::unit(), 356 _ => TypeRef::unit(),
357 }; 357 };
358 358
359 let ret_type = if func.async_token().is_some() { 359 let (ret_type, async_ret_type) = if func.async_token().is_some() {
360 let async_ret_type = ret_type.clone();
360 let future_impl = desugar_future_path(ret_type); 361 let future_impl = desugar_future_path(ret_type);
361 let ty_bound = Interned::new(TypeBound::Path(future_impl)); 362 let ty_bound = Interned::new(TypeBound::Path(future_impl));
362 TypeRef::ImplTrait(vec![ty_bound]) 363 (TypeRef::ImplTrait(vec![ty_bound]), Some(async_ret_type))
363 } else { 364 } else {
364 ret_type 365 (ret_type, None)
365 }; 366 };
366 367
367 let abi = func.abi().map(lower_abi); 368 let abi = func.abi().map(lower_abi);
@@ -395,6 +396,7 @@ impl<'a> Ctx<'a> {
395 abi, 396 abi,
396 params, 397 params,
397 ret_type: Interned::new(ret_type), 398 ret_type: Interned::new(ret_type),
399 async_ret_type: async_ret_type.map(Interned::new),
398 ast_id, 400 ast_id,
399 flags, 401 flags,
400 }; 402 };
@@ -474,7 +476,6 @@ impl<'a> Ctx<'a> {
474 self.lower_generic_params_and_inner_items(GenericsOwner::Trait(trait_def), trait_def); 476 self.lower_generic_params_and_inner_items(GenericsOwner::Trait(trait_def), trait_def);
475 let is_auto = trait_def.auto_token().is_some(); 477 let is_auto = trait_def.auto_token().is_some();
476 let is_unsafe = trait_def.unsafe_token().is_some(); 478 let is_unsafe = trait_def.unsafe_token().is_some();
477 let bounds = self.lower_type_bounds(trait_def);
478 let items = trait_def.assoc_item_list().map(|list| { 479 let items = trait_def.assoc_item_list().map(|list| {
479 let db = self.db; 480 let db = self.db;
480 self.with_inherited_visibility(visibility, |this| { 481 self.with_inherited_visibility(visibility, |this| {
@@ -497,7 +498,6 @@ impl<'a> Ctx<'a> {
497 generic_params, 498 generic_params,
498 is_auto, 499 is_auto,
499 is_unsafe, 500 is_unsafe,
500 bounds: bounds.into(),
501 items: items.unwrap_or_default(), 501 items: items.unwrap_or_default(),
502 ast_id, 502 ast_id,
503 }; 503 };
diff --git a/crates/hir_def/src/item_tree/pretty.rs b/crates/hir_def/src/item_tree/pretty.rs
index 53631ab19..cc9944a22 100644
--- a/crates/hir_def/src/item_tree/pretty.rs
+++ b/crates/hir_def/src/item_tree/pretty.rs
@@ -235,6 +235,7 @@ impl<'a> Printer<'a> {
235 abi, 235 abi,
236 params, 236 params,
237 ret_type, 237 ret_type,
238 async_ret_type: _,
238 ast_id: _, 239 ast_id: _,
239 flags, 240 flags,
240 } = &self.tree[it]; 241 } = &self.tree[it];
@@ -345,7 +346,6 @@ impl<'a> Printer<'a> {
345 visibility, 346 visibility,
346 is_auto, 347 is_auto,
347 is_unsafe, 348 is_unsafe,
348 bounds,
349 items, 349 items,
350 generic_params, 350 generic_params,
351 ast_id: _, 351 ast_id: _,
@@ -359,10 +359,6 @@ impl<'a> Printer<'a> {
359 } 359 }
360 w!(self, "trait {}", name); 360 w!(self, "trait {}", name);
361 self.print_generic_params(generic_params); 361 self.print_generic_params(generic_params);
362 if !bounds.is_empty() {
363 w!(self, ": ");
364 self.print_type_bounds(bounds);
365 }
366 self.print_where_clause_and_opening_brace(generic_params); 362 self.print_where_clause_and_opening_brace(generic_params);
367 self.indented(|this| { 363 self.indented(|this| {
368 for item in &**items { 364 for item in &**items {
diff --git a/crates/hir_def/src/item_tree/tests.rs b/crates/hir_def/src/item_tree/tests.rs
index 20773aa69..b362add5c 100644
--- a/crates/hir_def/src/item_tree/tests.rs
+++ b/crates/hir_def/src/item_tree/tests.rs
@@ -180,7 +180,7 @@ trait Tr: SuperTrait + 'lifetime {
180 _: (), 180 _: (),
181 ) -> (); 181 ) -> ();
182 182
183 pub(self) trait Tr<Self>: SuperTrait + 'lifetime 183 pub(self) trait Tr<Self>
184 where 184 where
185 Self: SuperTrait, 185 Self: SuperTrait,
186 Self: 'lifetime 186 Self: 'lifetime
@@ -350,7 +350,7 @@ trait Tr<'a, T: 'a>: Super {}
350 pub(self) union Union<'a, T, const U: u8> { 350 pub(self) union Union<'a, T, const U: u8> {
351 } 351 }
352 352
353 pub(self) trait Tr<'a, Self, T>: Super 353 pub(self) trait Tr<'a, Self, T>
354 where 354 where
355 Self: Super, 355 Self: Super,
356 T: 'a 356 T: 'a
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 716dcf1f7..7f9fdb379 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -477,16 +477,21 @@ impl DefCollector<'_> {
477 /// going out of sync with what the build system sees (since we resolve using VFS state, but 477 /// going out of sync with what the build system sees (since we resolve using VFS state, but
478 /// Cargo builds only on-disk files). We could and probably should add diagnostics for that. 478 /// Cargo builds only on-disk files). We could and probably should add diagnostics for that.
479 fn export_proc_macro(&mut self, def: ProcMacroDef, ast_id: AstId<ast::Fn>) { 479 fn export_proc_macro(&mut self, def: ProcMacroDef, ast_id: AstId<ast::Fn>) {
480 let kind = def.kind.to_basedb_kind();
480 self.exports_proc_macros = true; 481 self.exports_proc_macros = true;
481 let macro_def = match self.proc_macros.iter().find(|(n, _)| n == &def.name) { 482 let macro_def = match self.proc_macros.iter().find(|(n, _)| n == &def.name) {
482 Some((_, expander)) => MacroDefId { 483 Some((_, expander)) => MacroDefId {
483 krate: self.def_map.krate, 484 krate: self.def_map.krate,
484 kind: MacroDefKind::ProcMacro(*expander, ast_id), 485 kind: MacroDefKind::ProcMacro(*expander, kind, ast_id),
485 local_inner: false, 486 local_inner: false,
486 }, 487 },
487 None => MacroDefId { 488 None => MacroDefId {
488 krate: self.def_map.krate, 489 krate: self.def_map.krate,
489 kind: MacroDefKind::ProcMacro(ProcMacroExpander::dummy(self.def_map.krate), ast_id), 490 kind: MacroDefKind::ProcMacro(
491 ProcMacroExpander::dummy(self.def_map.krate),
492 kind,
493 ast_id,
494 ),
490 local_inner: false, 495 local_inner: false,
491 }, 496 },
492 }; 497 };
@@ -1674,14 +1679,22 @@ impl ModCollector<'_, '_> {
1674 None => &mac.name, 1679 None => &mac.name,
1675 }; 1680 };
1676 let krate = self.def_collector.def_map.krate; 1681 let krate = self.def_collector.def_map.krate;
1677 if let Some(macro_id) = find_builtin_macro(name, krate, ast_id) { 1682 match find_builtin_macro(name, krate, ast_id) {
1678 self.def_collector.define_macro_rules( 1683 Some(macro_id) => {
1679 self.module_id, 1684 self.def_collector.define_macro_rules(
1680 mac.name.clone(), 1685 self.module_id,
1681 macro_id, 1686 mac.name.clone(),
1682 is_export, 1687 macro_id,
1683 ); 1688 is_export,
1684 return; 1689 );
1690 return;
1691 }
1692 None => {
1693 self.def_collector
1694 .def_map
1695 .diagnostics
1696 .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id));
1697 }
1685 } 1698 }
1686 } 1699 }
1687 1700
@@ -1710,15 +1723,23 @@ impl ModCollector<'_, '_> {
1710 let macro_id = find_builtin_macro(&mac.name, krate, ast_id) 1723 let macro_id = find_builtin_macro(&mac.name, krate, ast_id)
1711 .or_else(|| find_builtin_derive(&mac.name, krate, ast_id)); 1724 .or_else(|| find_builtin_derive(&mac.name, krate, ast_id));
1712 1725
1713 if let Some(macro_id) = macro_id { 1726 match macro_id {
1714 self.def_collector.define_macro_def( 1727 Some(macro_id) => {
1715 self.module_id, 1728 self.def_collector.define_macro_def(
1716 mac.name.clone(), 1729 self.module_id,
1717 macro_id, 1730 mac.name.clone(),
1718 &self.item_tree[mac.visibility], 1731 macro_id,
1719 ); 1732 &self.item_tree[mac.visibility],
1733 );
1734 return;
1735 }
1736 None => {
1737 self.def_collector
1738 .def_map
1739 .diagnostics
1740 .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id));
1741 }
1720 } 1742 }
1721 return;
1722 } 1743 }
1723 1744
1724 // Case 2: normal `macro` 1745 // Case 2: normal `macro`
diff --git a/crates/hir_def/src/nameres/diagnostics.rs b/crates/hir_def/src/nameres/diagnostics.rs
index 57c36c3c6..95061f601 100644
--- a/crates/hir_def/src/nameres/diagnostics.rs
+++ b/crates/hir_def/src/nameres/diagnostics.rs
@@ -27,6 +27,8 @@ pub enum DefDiagnosticKind {
27 UnresolvedMacroCall { ast: AstId<ast::MacroCall>, path: ModPath }, 27 UnresolvedMacroCall { ast: AstId<ast::MacroCall>, path: ModPath },
28 28
29 MacroError { ast: MacroCallKind, message: String }, 29 MacroError { ast: MacroCallKind, message: String },
30
31 UnimplementedBuiltinMacro { ast: AstId<ast::Macro> },
30} 32}
31 33
32#[derive(Debug, PartialEq, Eq)] 34#[derive(Debug, PartialEq, Eq)]
@@ -93,4 +95,11 @@ impl DefDiagnostic {
93 ) -> Self { 95 ) -> Self {
94 Self { in_module: container, kind: DefDiagnosticKind::UnresolvedMacroCall { ast, path } } 96 Self { in_module: container, kind: DefDiagnosticKind::UnresolvedMacroCall { ast, path } }
95 } 97 }
98
99 pub(super) fn unimplemented_builtin_macro(
100 container: LocalModuleId,
101 ast: AstId<ast::Macro>,
102 ) -> Self {
103 Self { in_module: container, kind: DefDiagnosticKind::UnimplementedBuiltinMacro { ast } }
104 }
96} 105}
diff --git a/crates/hir_def/src/nameres/proc_macro.rs b/crates/hir_def/src/nameres/proc_macro.rs
index 156598f19..3f095d623 100644
--- a/crates/hir_def/src/nameres/proc_macro.rs
+++ b/crates/hir_def/src/nameres/proc_macro.rs
@@ -18,6 +18,16 @@ pub(super) enum ProcMacroKind {
18 Attr, 18 Attr,
19} 19}
20 20
21impl ProcMacroKind {
22 pub(super) fn to_basedb_kind(&self) -> base_db::ProcMacroKind {
23 match self {
24 ProcMacroKind::CustomDerive { .. } => base_db::ProcMacroKind::CustomDerive,
25 ProcMacroKind::FnLike => base_db::ProcMacroKind::FuncLike,
26 ProcMacroKind::Attr => base_db::ProcMacroKind::Attr,
27 }
28 }
29}
30
21impl Attrs { 31impl Attrs {
22 #[rustfmt::skip] 32 #[rustfmt::skip]
23 pub(super) fn parse_proc_macro_decl(&self, func_name: &Name) -> Option<ProcMacroDef> { 33 pub(super) fn parse_proc_macro_decl(&self, func_name: &Name) -> Option<ProcMacroDef> {
diff --git a/crates/hir_def/src/nameres/tests/incremental.rs b/crates/hir_def/src/nameres/tests/incremental.rs
index d884a6eb4..7bf152e26 100644
--- a/crates/hir_def/src/nameres/tests/incremental.rs
+++ b/crates/hir_def/src/nameres/tests/incremental.rs
@@ -1,6 +1,8 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use base_db::SourceDatabaseExt; 3use base_db::{salsa::SweepStrategy, SourceDatabaseExt};
4
5use crate::{AdtId, ModuleDefId};
4 6
5use super::*; 7use super::*;
6 8
@@ -163,3 +165,73 @@ m!(Z);
163 assert_eq!(n_reparsed_macros, 0); 165 assert_eq!(n_reparsed_macros, 0);
164 } 166 }
165} 167}
168
169#[test]
170fn item_tree_prevents_reparsing() {
171 // The `ItemTree` is used by both name resolution and the various queries in `adt.rs` and
172 // `data.rs`. After computing the `ItemTree` and deleting the parse tree, we should be able to
173 // run those other queries without triggering a reparse.
174
175 let (db, pos) = TestDB::with_position(
176 r#"
177pub struct S;
178pub union U {}
179pub enum E {
180 Variant,
181}
182pub fn f(_: S) { $0 }
183pub trait Tr {}
184impl Tr for () {}
185pub const C: u8 = 0;
186pub static ST: u8 = 0;
187pub type Ty = ();
188"#,
189 );
190 let krate = db.test_crate();
191 {
192 let events = db.log_executed(|| {
193 db.file_item_tree(pos.file_id.into());
194 });
195 let n_calculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count();
196 assert_eq!(n_calculated_item_trees, 1);
197 let n_parsed_files = events.iter().filter(|it| it.contains("parse(")).count();
198 assert_eq!(n_parsed_files, 1);
199 }
200
201 // Delete the parse tree.
202 let sweep = SweepStrategy::default().discard_values().sweep_all_revisions();
203 base_db::ParseQuery.in_db(&db).sweep(sweep);
204
205 {
206 let events = db.log_executed(|| {
207 let crate_def_map = db.crate_def_map(krate);
208 let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
209 assert_eq!(module_data.scope.resolutions().count(), 8);
210 assert_eq!(module_data.scope.impls().count(), 1);
211
212 for imp in module_data.scope.impls() {
213 db.impl_data(imp);
214 }
215
216 for (_, res) in module_data.scope.resolutions() {
217 match res.values.or(res.types).unwrap().0 {
218 ModuleDefId::FunctionId(f) => drop(db.function_data(f)),
219 ModuleDefId::AdtId(adt) => match adt {
220 AdtId::StructId(it) => drop(db.struct_data(it)),
221 AdtId::UnionId(it) => drop(db.union_data(it)),
222 AdtId::EnumId(it) => drop(db.enum_data(it)),
223 },
224 ModuleDefId::ConstId(it) => drop(db.const_data(it)),
225 ModuleDefId::StaticId(it) => drop(db.static_data(it)),
226 ModuleDefId::TraitId(it) => drop(db.trait_data(it)),
227 ModuleDefId::TypeAliasId(it) => drop(db.type_alias_data(it)),
228 ModuleDefId::EnumVariantId(_)
229 | ModuleDefId::ModuleId(_)
230 | ModuleDefId::BuiltinType(_) => unreachable!(),
231 }
232 }
233 });
234 let n_reparsed_files = events.iter().filter(|it| it.contains("parse(")).count();
235 assert_eq!(n_reparsed_files, 0);
236 }
237}
diff --git a/crates/hir_def/src/test_db.rs b/crates/hir_def/src/test_db.rs
index a9c1e13e2..e840fe5e8 100644
--- a/crates/hir_def/src/test_db.rs
+++ b/crates/hir_def/src/test_db.rs
@@ -298,6 +298,13 @@ impl TestDB {
298 DefDiagnosticKind::MacroError { ast, message } => { 298 DefDiagnosticKind::MacroError { ast, message } => {
299 (ast.to_node(self.upcast()), message.as_str()) 299 (ast.to_node(self.upcast()), message.as_str())
300 } 300 }
301 DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => {
302 let node = ast.to_node(self.upcast());
303 (
304 InFile::new(ast.file_id, node.syntax().clone()),
305 "UnimplementedBuiltinMacro",
306 )
307 }
301 }; 308 };
302 309
303 let frange = node.as_ref().original_file_range(self); 310 let frange = node.as_ref().original_file_range(self);