mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-10-31 12:04:43 +00:00 
			
		
		
		
	Merge pull request #18940 from Veykril/push-ulowqkpprslq
fix: Fix semantics not always correctly caching file roots
This commit is contained in:
		
						commit
						1fc15e0673
					
				
					 2 changed files with 36 additions and 40 deletions
				
			
		|  | @ -136,8 +136,6 @@ pub struct Semantics<'db, DB> { | |||
| pub struct SemanticsImpl<'db> { | ||||
|     pub db: &'db dyn HirDatabase, | ||||
|     s2d_cache: RefCell<SourceToDefCache>, | ||||
|     /// Rootnode to HirFileId cache
 | ||||
|     root_to_file_cache: RefCell<FxHashMap<SyntaxNode, HirFileId>>, | ||||
|     /// MacroCall to its expansion's MacroFileId cache
 | ||||
|     macro_call_cache: RefCell<FxHashMap<InFile<ast::MacroCall>, MacroFileId>>, | ||||
| } | ||||
|  | @ -304,12 +302,7 @@ impl<DB: HirDatabase> Semantics<'_, DB> { | |||
| 
 | ||||
| impl<'db> SemanticsImpl<'db> { | ||||
|     fn new(db: &'db dyn HirDatabase) -> Self { | ||||
|         SemanticsImpl { | ||||
|             db, | ||||
|             s2d_cache: Default::default(), | ||||
|             root_to_file_cache: Default::default(), | ||||
|             macro_call_cache: Default::default(), | ||||
|         } | ||||
|         SemanticsImpl { db, s2d_cache: Default::default(), macro_call_cache: Default::default() } | ||||
|     } | ||||
| 
 | ||||
|     pub fn parse(&self, file_id: EditionedFileId) -> ast::SourceFile { | ||||
|  | @ -483,7 +476,7 @@ impl<'db> SemanticsImpl<'db> { | |||
|             Some( | ||||
|                 calls | ||||
|                     .into_iter() | ||||
|                     .map(|call| macro_call_to_macro_id(self, ctx, call?).map(|id| Macro { id })) | ||||
|                     .map(|call| macro_call_to_macro_id(ctx, call?).map(|id| Macro { id })) | ||||
|                     .collect(), | ||||
|             ) | ||||
|         }) | ||||
|  | @ -962,7 +955,7 @@ impl<'db> SemanticsImpl<'db> { | |||
|             let InMacroFile { file_id, value: mapped_tokens } = self.with_ctx(|ctx| { | ||||
|                 Some( | ||||
|                     ctx.cache | ||||
|                         .get_or_insert_expansion(self, macro_file) | ||||
|                         .get_or_insert_expansion(ctx.db, macro_file) | ||||
|                         .map_range_down(span)? | ||||
|                         .map(SmallVec::<[_; 2]>::from_iter), | ||||
|                 ) | ||||
|  | @ -1287,7 +1280,7 @@ impl<'db> SemanticsImpl<'db> { | |||
|                     let macro_file = file_id.macro_file()?; | ||||
| 
 | ||||
|                     self.with_ctx(|ctx| { | ||||
|                         let expansion_info = ctx.cache.get_or_insert_expansion(self, macro_file); | ||||
|                         let expansion_info = ctx.cache.get_or_insert_expansion(ctx.db, macro_file); | ||||
|                         expansion_info.arg().map(|node| node?.parent()).transpose() | ||||
|                     }) | ||||
|                 } | ||||
|  | @ -1318,8 +1311,8 @@ impl<'db> SemanticsImpl<'db> { | |||
|     } | ||||
| 
 | ||||
|     pub fn resolve_label(&self, label: &ast::Lifetime) -> Option<Label> { | ||||
|         let (parent, label_id) = self | ||||
|             .with_ctx(|ctx| ctx.label_ref_to_def(self.wrap_node_infile(label.clone()).as_ref()))?; | ||||
|         let src = self.wrap_node_infile(label.clone()); | ||||
|         let (parent, label_id) = self.with_ctx(|ctx| ctx.label_ref_to_def(src.as_ref()))?; | ||||
|         Some(Label { parent, label_id }) | ||||
|     } | ||||
| 
 | ||||
|  | @ -1519,7 +1512,7 @@ impl<'db> SemanticsImpl<'db> { | |||
|         let macro_call = self.find_file(macro_call.syntax()).with_value(macro_call); | ||||
|         self.with_ctx(|ctx| { | ||||
|             ctx.macro_call_to_macro_call(macro_call) | ||||
|                 .and_then(|call| macro_call_to_macro_id(self, ctx, call)) | ||||
|                 .and_then(|call| macro_call_to_macro_id(ctx, call)) | ||||
|                 .map(Into::into) | ||||
|         }) | ||||
|         .or_else(|| { | ||||
|  | @ -1561,7 +1554,7 @@ impl<'db> SemanticsImpl<'db> { | |||
|         let item_in_file = self.wrap_node_infile(item.clone()); | ||||
|         let id = self.with_ctx(|ctx| { | ||||
|             let macro_call_id = ctx.item_to_macro_call(item_in_file.as_ref())?; | ||||
|             macro_call_to_macro_id(self, ctx, macro_call_id) | ||||
|             macro_call_to_macro_id(ctx, macro_call_id) | ||||
|         })?; | ||||
|         Some(Macro { id }) | ||||
|     } | ||||
|  | @ -1725,10 +1718,11 @@ impl<'db> SemanticsImpl<'db> { | |||
|     } | ||||
| 
 | ||||
|     fn cache(&self, root_node: SyntaxNode, file_id: HirFileId) { | ||||
|         assert!(root_node.parent().is_none()); | ||||
|         let mut cache = self.root_to_file_cache.borrow_mut(); | ||||
|         let prev = cache.insert(root_node, file_id); | ||||
|         assert!(prev.is_none() || prev == Some(file_id)); | ||||
|         SourceToDefCache::cache( | ||||
|             &mut self.s2d_cache.borrow_mut().root_to_file_cache, | ||||
|             root_node, | ||||
|             file_id, | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     pub fn assert_contains_node(&self, node: &SyntaxNode) { | ||||
|  | @ -1736,8 +1730,8 @@ impl<'db> SemanticsImpl<'db> { | |||
|     } | ||||
| 
 | ||||
|     fn lookup(&self, root_node: &SyntaxNode) -> Option<HirFileId> { | ||||
|         let cache = self.root_to_file_cache.borrow(); | ||||
|         cache.get(root_node).copied() | ||||
|         let cache = self.s2d_cache.borrow(); | ||||
|         cache.root_to_file_cache.get(root_node).copied() | ||||
|     } | ||||
| 
 | ||||
|     fn wrap_node_infile<N: AstNode>(&self, node: N) -> InFile<N> { | ||||
|  | @ -1761,8 +1755,9 @@ impl<'db> SemanticsImpl<'db> { | |||
|                  known nodes: {}\n\n",
 | ||||
|                 node, | ||||
|                 root_node, | ||||
|                 self.root_to_file_cache | ||||
|                 self.s2d_cache | ||||
|                     .borrow() | ||||
|                     .root_to_file_cache | ||||
|                     .keys() | ||||
|                     .map(|it| format!("{it:?}")) | ||||
|                     .collect::<Vec<_>>() | ||||
|  | @ -1909,7 +1904,6 @@ impl<'db> SemanticsImpl<'db> { | |||
| } | ||||
| 
 | ||||
| fn macro_call_to_macro_id( | ||||
|     sema: &SemanticsImpl<'_>, | ||||
|     ctx: &mut SourceToDefCtx<'_, '_>, | ||||
|     macro_call_id: MacroCallId, | ||||
| ) -> Option<MacroId> { | ||||
|  | @ -1925,7 +1919,7 @@ fn macro_call_to_macro_id( | |||
|                     it.to_ptr(db).to_node(&db.parse(file_id).syntax_node()) | ||||
|                 } | ||||
|                 HirFileIdRepr::MacroFile(macro_file) => { | ||||
|                     let expansion_info = ctx.cache.get_or_insert_expansion(sema, macro_file); | ||||
|                     let expansion_info = ctx.cache.get_or_insert_expansion(ctx.db, macro_file); | ||||
|                     it.to_ptr(db).to_node(&expansion_info.expanded().value) | ||||
|                 } | ||||
|             }; | ||||
|  | @ -1937,7 +1931,7 @@ fn macro_call_to_macro_id( | |||
|                     it.to_ptr(db).to_node(&db.parse(file_id).syntax_node()) | ||||
|                 } | ||||
|                 HirFileIdRepr::MacroFile(macro_file) => { | ||||
|                     let expansion_info = ctx.cache.get_or_insert_expansion(sema, macro_file); | ||||
|                     let expansion_info = ctx.cache.get_or_insert_expansion(ctx.db, macro_file); | ||||
|                     it.to_ptr(db).to_node(&expansion_info.expanded().value) | ||||
|                 } | ||||
|             }; | ||||
|  |  | |||
|  | @ -110,10 +110,7 @@ use syntax::{ | |||
|     AstNode, AstPtr, SyntaxNode, | ||||
| }; | ||||
| 
 | ||||
| use crate::{ | ||||
|     db::HirDatabase, semantics::child_by_source::ChildBySource, InFile, InlineAsmOperand, | ||||
|     SemanticsImpl, | ||||
| }; | ||||
| use crate::{db::HirDatabase, semantics::child_by_source::ChildBySource, InFile, InlineAsmOperand}; | ||||
| 
 | ||||
| #[derive(Default)] | ||||
| pub(super) struct SourceToDefCache { | ||||
|  | @ -121,9 +118,21 @@ pub(super) struct SourceToDefCache { | |||
|     expansion_info_cache: FxHashMap<MacroFileId, ExpansionInfo>, | ||||
|     pub(super) file_to_def_cache: FxHashMap<FileId, SmallVec<[ModuleId; 1]>>, | ||||
|     pub(super) included_file_cache: FxHashMap<EditionedFileId, Option<MacroFileId>>, | ||||
|     /// Rootnode to HirFileId cache
 | ||||
|     pub(super) root_to_file_cache: FxHashMap<SyntaxNode, HirFileId>, | ||||
| } | ||||
| 
 | ||||
| impl SourceToDefCache { | ||||
|     pub(super) fn cache( | ||||
|         root_to_file_cache: &mut FxHashMap<SyntaxNode, HirFileId>, | ||||
|         root_node: SyntaxNode, | ||||
|         file_id: HirFileId, | ||||
|     ) { | ||||
|         assert!(root_node.parent().is_none()); | ||||
|         let prev = root_to_file_cache.insert(root_node, file_id); | ||||
|         assert!(prev.is_none() || prev == Some(file_id)); | ||||
|     } | ||||
| 
 | ||||
|     pub(super) fn get_or_insert_include_for( | ||||
|         &mut self, | ||||
|         db: &dyn HirDatabase, | ||||
|  | @ -143,14 +152,14 @@ impl SourceToDefCache { | |||
| 
 | ||||
|     pub(super) fn get_or_insert_expansion( | ||||
|         &mut self, | ||||
|         sema: &SemanticsImpl<'_>, | ||||
|         db: &dyn HirDatabase, | ||||
|         macro_file: MacroFileId, | ||||
|     ) -> &ExpansionInfo { | ||||
|         self.expansion_info_cache.entry(macro_file).or_insert_with(|| { | ||||
|             let exp_info = macro_file.expansion_info(sema.db.upcast()); | ||||
|             let exp_info = macro_file.expansion_info(db.upcast()); | ||||
| 
 | ||||
|             let InMacroFile { file_id, value } = exp_info.expanded(); | ||||
|             sema.cache(value, file_id.into()); | ||||
|             Self::cache(&mut self.root_to_file_cache, value, file_id.into()); | ||||
| 
 | ||||
|             exp_info | ||||
|         }) | ||||
|  | @ -520,18 +529,11 @@ impl SourceToDefCtx<'_, '_> { | |||
|         node: InFile<&SyntaxNode>, | ||||
|         mut cb: impl FnMut(&mut Self, InFile<SyntaxNode>) -> Option<T>, | ||||
|     ) -> Option<T> { | ||||
|         use hir_expand::MacroFileIdExt; | ||||
|         let parent = |this: &mut Self, node: InFile<&SyntaxNode>| match node.value.parent() { | ||||
|             Some(parent) => Some(node.with_value(parent)), | ||||
|             None => { | ||||
|                 let macro_file = node.file_id.macro_file()?; | ||||
| 
 | ||||
|                 let expansion_info = this | ||||
|                     .cache | ||||
|                     .expansion_info_cache | ||||
|                     .entry(macro_file) | ||||
|                     .or_insert_with(|| macro_file.expansion_info(this.db.upcast())); | ||||
| 
 | ||||
|                 let expansion_info = this.cache.get_or_insert_expansion(this.db, macro_file); | ||||
|                 expansion_info.arg().map(|node| node?.parent()).transpose() | ||||
|             } | ||||
|         }; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lukas Wirth
						Lukas Wirth