From 42ed53a15b0e37a5da847ae7e5df55bb2f056689 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 26 May 2026 17:33:15 +0200 Subject: [PATCH 01/14] add lifetime to NavigationTarget --- crates/ide/src/annotations.rs | 2 +- crates/ide/src/call_hierarchy.rs | 8 +-- crates/ide/src/child_modules.rs | 5 +- crates/ide/src/goto_declaration.rs | 4 +- crates/ide/src/goto_definition.rs | 29 +++++----- crates/ide/src/goto_implementation.rs | 11 ++-- crates/ide/src/goto_type_definition.rs | 2 +- crates/ide/src/hover.rs | 4 +- crates/ide/src/lib.rs | 26 ++++++--- crates/ide/src/navigation_target.rs | 69 ++++++++++++------------ crates/ide/src/parent_module.rs | 5 +- crates/ide/src/references.rs | 2 +- crates/ide/src/runnables.rs | 2 +- crates/rust-analyzer/src/lsp/to_proto.rs | 12 ++--- 14 files changed, 101 insertions(+), 80 deletions(-) diff --git a/crates/ide/src/annotations.rs b/crates/ide/src/annotations.rs index f716f94d7141..449a03ffd6aa 100644 --- a/crates/ide/src/annotations.rs +++ b/crates/ide/src/annotations.rs @@ -32,7 +32,7 @@ pub struct Annotation { #[derive(Debug, Hash, PartialEq, Eq)] pub enum AnnotationKind { Runnable(Runnable), - HasImpls { pos: FilePosition, data: Option> }, + HasImpls { pos: FilePosition, data: Option>> }, HasReferences { pos: FilePosition, data: Option> }, } diff --git a/crates/ide/src/call_hierarchy.rs b/crates/ide/src/call_hierarchy.rs index 402764f11202..8e2ef74f22cb 100644 --- a/crates/ide/src/call_hierarchy.rs +++ b/crates/ide/src/call_hierarchy.rs @@ -18,7 +18,7 @@ use crate::{ #[derive(Debug, Clone)] pub struct CallItem { - pub target: NavigationTarget, + pub target: NavigationTarget<'static>, pub ranges: Vec, } @@ -33,7 +33,7 @@ pub(crate) fn call_hierarchy( db: &RootDatabase, position: FilePosition, config: &CallHierarchyConfig<'_>, -) -> Option>> { +) -> Option>>> { goto_definition::goto_definition( db, position, @@ -159,11 +159,11 @@ pub(crate) fn outgoing_calls( #[derive(Default)] struct CallLocations { - funcs: FxIndexMap>, + funcs: FxIndexMap, Vec>, } impl CallLocations { - fn add(&mut self, target: NavigationTarget, range: FileRange) { + fn add(&mut self, target: NavigationTarget<'static>, range: FileRange) { self.funcs.entry(target).or_default().push(range); } diff --git a/crates/ide/src/child_modules.rs b/crates/ide/src/child_modules.rs index b781596187b9..cb51f4ae407e 100644 --- a/crates/ide/src/child_modules.rs +++ b/crates/ide/src/child_modules.rs @@ -16,7 +16,10 @@ use crate::NavigationTarget; // | VS Code | **rust-analyzer: Locate child modules** | /// This returns `Vec` because a module may be included from several places. -pub(crate) fn child_modules(db: &RootDatabase, position: FilePosition) -> Vec { +pub(crate) fn child_modules( + db: &RootDatabase, + position: FilePosition, +) -> Vec> { let sema = Semantics::new(db); let source_file = sema.parse_guess_edition(position.file_id); // First go to the parent module which contains the cursor diff --git a/crates/ide/src/goto_declaration.rs b/crates/ide/src/goto_declaration.rs index d2b47a37c7b0..b6ce47b17700 100644 --- a/crates/ide/src/goto_declaration.rs +++ b/crates/ide/src/goto_declaration.rs @@ -22,14 +22,14 @@ pub(crate) fn goto_declaration( db: &RootDatabase, position @ FilePosition { file_id, offset }: FilePosition, config: &GotoDefinitionConfig<'_>, -) -> Option>> { +) -> Option>>> { let sema = Semantics::new(db); let file = sema.parse_guess_edition(file_id).syntax().clone(); let original_token = file .token_at_offset(offset) .find(|it| matches!(it.kind(), IDENT | T![self] | T![super] | T![crate] | T![Self]))?; let range = original_token.text_range(); - let info: Vec = sema + let info: Vec> = sema .descend_into_macros_no_opaque(original_token, false) .iter() .filter_map(|token| { diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index 4890badcbf5b..ab0ee6e78e72 100644 --- a/crates/ide/src/goto_definition.rs +++ b/crates/ide/src/goto_definition.rs @@ -44,7 +44,7 @@ pub(crate) fn goto_definition( db: &RootDatabase, FilePosition { file_id, offset }: FilePosition, config: &GotoDefinitionConfig<'_>, -) -> Option>> { +) -> Option>>> { let sema = &Semantics::new(db); let file = sema.parse_guess_edition(file_id).syntax().clone(); let edition = sema.attach_first_edition(file_id).edition(db); @@ -202,7 +202,7 @@ fn goto_question_mark_conversions( fn find_definition_for_known_blanket_dual_impls( sema: &Semantics<'_, RootDatabase>, original_token: &SyntaxToken, -) -> Option> { +) -> Option>> { let method_call = ast::MethodCallExpr::cast(original_token.parent()?.parent()?)?; let callable = sema.resolve_method_call_as_callable(&method_call)?; let CallableKind::Function(f) = callable.kind() else { return None }; @@ -273,7 +273,7 @@ fn find_definition_for_known_blanket_dual_impls( fn find_definition_for_comparison_operators( sema: &Semantics<'_, RootDatabase>, original_token: &SyntaxToken, -) -> Option> { +) -> Option>> { let bin_expr = ast::BinExpr::cast(original_token.parent()?)?; let f = sema.resolve_bin_expr(&bin_expr)?; @@ -329,7 +329,7 @@ fn try_lookup_include_path( sema: &Semantics<'_, RootDatabase>, token: InFile, file_id: FileId, -) -> Option { +) -> Option> { let file = token.file_id.macro_file()?; // Check that we are in the eager argument expansion of an include macro @@ -359,7 +359,7 @@ fn try_lookup_include_path( fn try_lookup_macro_def_in_macro_use( sema: &Semantics<'_, RootDatabase>, token: SyntaxToken, -) -> Option { +) -> Option> { let extern_crate = token.parent()?.ancestors().find_map(ast::ExternCrate::cast)?; let extern_crate = sema.to_def(&extern_crate)?; let krate = extern_crate.resolved_crate(sema.db)?; @@ -386,7 +386,7 @@ fn try_lookup_macro_def_in_macro_use( fn try_filter_trait_item_definition( sema: &Semantics<'_, RootDatabase>, def: &Definition, -) -> Option> { +) -> Option>> { let db = sema.db; let assoc = def.as_assoc_item(db)?; match assoc { @@ -408,7 +408,7 @@ fn try_filter_trait_item_definition( fn handle_control_flow_keywords( sema: &Semantics<'_, RootDatabase>, token: &SyntaxToken, -) -> Option> { +) -> Option>> { match token.kind() { // For `fn` / `loop` / `while` / `for` / `async` / `match`, return the keyword it self, // so that VSCode will find the references when using `ctrl + click` @@ -456,7 +456,7 @@ pub(crate) fn find_fn_or_blocks( fn nav_for_exit_points( sema: &Semantics<'_, RootDatabase>, token: &SyntaxToken, -) -> Option> { +) -> Option>> { let db = sema.db; let token_kind = token.kind(); @@ -482,7 +482,7 @@ fn nav_for_exit_points( .map(|(frange, _)| frange); if let Some(FileRange { file_id, range }) = focus_frange { - let contains_frange = |nav: &NavigationTarget| { + let contains_frange = |nav: &NavigationTarget<'_>| { nav.file_id == file_id.file_id(db) && nav.full_range.contains_range(range) }; @@ -563,7 +563,7 @@ pub(crate) fn find_branch_root( fn nav_for_branch_exit_points( sema: &Semantics<'_, RootDatabase>, token: &SyntaxToken, -) -> Option> { +) -> Option>> { let db = sema.db; let navs = match token.kind() { @@ -615,7 +615,7 @@ fn nav_for_branch_exit_points( fn nav_for_break_points( sema: &Semantics<'_, RootDatabase>, token: &SyntaxToken, -) -> Option> { +) -> Option>> { let db = sema.db; let navs = find_loops(sema, token)? @@ -639,7 +639,10 @@ fn nav_for_break_points( Some(navs) } -fn def_to_nav(sema: &Semantics<'_, RootDatabase>, def: Definition) -> Vec { +fn def_to_nav( + sema: &Semantics<'_, RootDatabase>, + def: Definition, +) -> Vec> { def.try_to_nav(sema).map(|it| it.collect()).unwrap_or_default() } @@ -647,7 +650,7 @@ fn expr_to_nav( db: &RootDatabase, InFile { file_id, value }: InFile, focus_range: Option, -) -> UpmappingResult { +) -> UpmappingResult> { let kind = SymbolKind::Label; let value_range = value.syntax().text_range(); diff --git a/crates/ide/src/goto_implementation.rs b/crates/ide/src/goto_implementation.rs index 4bf9b82cc877..7877af82d045 100644 --- a/crates/ide/src/goto_implementation.rs +++ b/crates/ide/src/goto_implementation.rs @@ -25,7 +25,7 @@ pub(crate) fn goto_implementation( db: &RootDatabase, config: &GotoImplementationConfig, FilePosition { file_id, offset }: FilePosition, -) -> Option>> { +) -> Option>>> { let sema = Semantics::new(db); let source_file = sema.parse_guess_edition(file_id); let syntax = source_file.syntax().clone(); @@ -100,7 +100,10 @@ pub(crate) fn goto_implementation( Some(RangeInfo { range, info: navs }) } -fn impls_for_ty(sema: &Semantics<'_, RootDatabase>, ty: hir::Type<'_>) -> Vec { +fn impls_for_ty( + sema: &Semantics<'_, RootDatabase>, + ty: hir::Type<'_>, +) -> Vec> { Impl::all_for_type(sema.db, ty) .into_iter() .filter_map(|imp| imp.try_to_nav(sema)) @@ -111,7 +114,7 @@ fn impls_for_ty(sema: &Semantics<'_, RootDatabase>, ty: hir::Type<'_>) -> Vec, trait_: hir::Trait, -) -> Vec { +) -> Vec> { Impl::all_for_trait(sema.db, trait_) .into_iter() .filter_map(|imp| imp.try_to_nav(sema)) @@ -123,7 +126,7 @@ fn impls_for_trait_item( sema: &Semantics<'_, RootDatabase>, trait_: hir::Trait, fun_name: hir::Name, -) -> Vec { +) -> Vec> { Impl::all_for_trait(sema.db, trait_) .into_iter() .filter_map(|imp| { diff --git a/crates/ide/src/goto_type_definition.rs b/crates/ide/src/goto_type_definition.rs index ffd144a827e3..bfb6f18a4f37 100644 --- a/crates/ide/src/goto_type_definition.rs +++ b/crates/ide/src/goto_type_definition.rs @@ -16,7 +16,7 @@ use crate::{FilePosition, NavigationTarget, RangeInfo, TryToNav}; pub(crate) fn goto_type_definition( db: &RootDatabase, FilePosition { file_id, offset }: FilePosition, -) -> Option>> { +) -> Option>>> { let sema = hir::Semantics::new(db); let file: ast::SourceFile = sema.parse_guess_edition(file_id); diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index c3a8e0362fee..9ed4d6597fab 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -112,7 +112,7 @@ impl HoverAction { #[derive(Debug, Clone, Eq, PartialEq, Hash, UpmapFromRaFixture)] pub struct HoverGotoTypeData { pub mod_path: String, - pub nav: NavigationTarget, + pub nav: NavigationTarget<'static>, } /// Contains the results when hovering over an item @@ -544,7 +544,7 @@ fn show_implementations_action( sema: &Semantics<'_, RootDatabase>, def: Definition, ) -> Option { - fn to_action(nav_target: NavigationTarget) -> HoverAction { + fn to_action(nav_target: NavigationTarget<'_>) -> HoverAction { HoverAction::Implementation(FilePosition { file_id: nav_target.file_id, offset: nav_target.focus_or_full_range().start(), diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index e131e7bdd17d..3bc59487ec9e 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -519,7 +519,11 @@ impl Analysis { } /// Fuzzy searches for a symbol. - pub fn symbol_search(&self, query: Query, limit: usize) -> Cancellable> { + pub fn symbol_search( + &self, + query: Query, + limit: usize, + ) -> Cancellable>> { // `world_symbols` currently clones the database to run stuff in parallel, which will make any query panic // if we were to attach it here. Cancelled::catch(|| { @@ -540,7 +544,7 @@ impl Analysis { &self, position: FilePosition, config: &GotoDefinitionConfig<'_>, - ) -> Cancellable>>> { + ) -> Cancellable>>>> { self.with_db(|db| goto_definition::goto_definition(db, position, config)) } @@ -549,7 +553,7 @@ impl Analysis { &self, position: FilePosition, config: &GotoDefinitionConfig<'_>, - ) -> Cancellable>>> { + ) -> Cancellable>>>> { self.with_db(|db| goto_declaration::goto_declaration(db, position, config)) } @@ -558,7 +562,7 @@ impl Analysis { &self, config: &GotoImplementationConfig, position: FilePosition, - ) -> Cancellable>>> { + ) -> Cancellable>>>> { self.with_db(|db| goto_implementation::goto_implementation(db, config, position)) } @@ -566,7 +570,7 @@ impl Analysis { pub fn goto_type_definition( &self, position: FilePosition, - ) -> Cancellable>>> { + ) -> Cancellable>>>> { self.with_db(|db| goto_type_definition::goto_type_definition(db, position)) } @@ -621,7 +625,7 @@ impl Analysis { &self, position: FilePosition, config: &CallHierarchyConfig<'_>, - ) -> Cancellable>>> { + ) -> Cancellable>>>> { self.with_db(|db| call_hierarchy::call_hierarchy(db, position, config)) } @@ -644,12 +648,18 @@ impl Analysis { } /// Returns a `mod name;` declaration which created the current module. - pub fn parent_module(&self, position: FilePosition) -> Cancellable> { + pub fn parent_module( + &self, + position: FilePosition, + ) -> Cancellable>> { self.with_db(|db| parent_module::parent_module(db, position)) } /// Returns vec of `mod name;` declaration which are created by the current module. - pub fn child_modules(&self, position: FilePosition) -> Cancellable> { + pub fn child_modules( + &self, + position: FilePosition, + ) -> Cancellable>> { self.with_db(|db| child_modules::child_modules(db, position)) } diff --git a/crates/ide/src/navigation_target.rs b/crates/ide/src/navigation_target.rs index b8c14dc09f9a..ee842ba3be26 100644 --- a/crates/ide/src/navigation_target.rs +++ b/crates/ide/src/navigation_target.rs @@ -28,7 +28,7 @@ use syntax::{ /// Typically, a `NavigationTarget` corresponds to some element in the source /// code, like a function or a struct, but this is not strictly required. #[derive(Clone, PartialEq, Eq, Hash)] -pub struct NavigationTarget { +pub struct NavigationTarget<'db> { pub file_id: FileId, /// Range which encompasses the whole element. /// @@ -50,14 +50,13 @@ pub struct NavigationTarget { pub kind: Option, pub container_name: Option, pub description: Option, - // FIXME: Use the database lifetime here. - pub docs: Option>, + pub docs: Option>, /// In addition to a `name` field, a `NavigationTarget` may also be aliased /// In such cases we want a `NavigationTarget` to be accessible by its alias pub alias: Option, } -impl fmt::Debug for NavigationTarget { +impl fmt::Debug for NavigationTarget<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut f = f.debug_struct("NavigationTarget"); macro_rules! opt { @@ -75,7 +74,7 @@ impl fmt::Debug for NavigationTarget { } } -impl UpmapFromRaFixture for NavigationTarget { +impl UpmapFromRaFixture for NavigationTarget<'_> { fn upmap_from_ra_fixture( self, analysis: &ide_db::ra_fixture::RaFixtureAnalysis, @@ -114,21 +113,21 @@ impl UpmapFromRaFixture for NavigationTarget { } pub(crate) trait ToNav { - fn to_nav(&self, db: &RootDatabase) -> UpmappingResult; + fn to_nav(&self, db: &RootDatabase) -> UpmappingResult>; } pub trait TryToNav { fn try_to_nav( &self, sema: &Semantics<'_, RootDatabase>, - ) -> Option>; + ) -> Option>>; } impl TryToNav for Either { fn try_to_nav( &self, sema: &Semantics<'_, RootDatabase>, - ) -> Option> { + ) -> Option>> { match self { Either::Left(it) => it.try_to_nav(sema), Either::Right(it) => it.try_to_nav(sema), @@ -136,7 +135,7 @@ impl TryToNav for Either { } } -impl NavigationTarget { +impl<'db> NavigationTarget<'db> { pub fn focus_or_full_range(&self) -> TextRange { self.focus_range.unwrap_or(self.full_range) } @@ -144,7 +143,7 @@ impl NavigationTarget { pub(crate) fn from_module_to_decl( db: &RootDatabase, module: hir::Module, - ) -> UpmappingResult { + ) -> UpmappingResult> { let name = module.name(db).map(|it| it.symbol().clone()).unwrap_or_else(|| sym::underscore); match module.declaration_source(db) { Some(InFile { value, file_id }) => { @@ -192,7 +191,7 @@ impl NavigationTarget { db: &RootDatabase, InFile { file_id, value }: InFile<&dyn ast::HasName>, kind: SymbolKind, - ) -> UpmappingResult { + ) -> UpmappingResult> { let name = value.name().map(|it| Symbol::intern(&it.text())).unwrap_or_else(|| sym::underscore); @@ -208,7 +207,7 @@ impl NavigationTarget { ranges: InFile<(TextRange, Option)>, name: Option, kind: SymbolKind, - ) -> UpmappingResult { + ) -> UpmappingResult> { let InFile { file_id, value: (full_range, focus_range) } = ranges; let name = name.map(|name| name.symbol().clone()).unwrap_or_else(|| sym::underscore); @@ -225,7 +224,7 @@ impl NavigationTarget { focus_range: Option, full_range: TextRange, kind: SymbolKind, - ) -> NavigationTarget { + ) -> NavigationTarget<'static> { NavigationTarget { file_id, name, @@ -244,7 +243,7 @@ impl<'db> TryToNav for FileSymbol<'db> { fn try_to_nav( &self, sema: &Semantics<'_, RootDatabase>, - ) -> Option> { + ) -> Option>> { let db = sema.db; let display_target = self.def.krate(db).to_display_target(db); Some( @@ -306,7 +305,7 @@ impl TryToNav for Definition { fn try_to_nav( &self, sema: &Semantics<'_, RootDatabase>, - ) -> Option> { + ) -> Option>> { match self { Definition::Local(it) => Some(it.to_nav(sema.db)), Definition::Label(it) => it.try_to_nav(sema), @@ -341,7 +340,7 @@ impl TryToNav for hir::ModuleDef { fn try_to_nav( &self, sema: &Semantics<'_, RootDatabase>, - ) -> Option> { + ) -> Option>> { match self { hir::ModuleDef::Module(it) => Some(it.to_nav(sema.db)), hir::ModuleDef::Function(it) => it.try_to_nav(sema), @@ -441,7 +440,7 @@ where fn try_to_nav( &self, sema: &Semantics<'_, RootDatabase>, - ) -> Option> { + ) -> Option>> { let db = sema.db; let src = self.source_with_range(db)?; Some( @@ -470,7 +469,7 @@ where } impl ToNav for hir::Module { - fn to_nav(&self, db: &RootDatabase) -> UpmappingResult { + fn to_nav(&self, db: &RootDatabase) -> UpmappingResult> { let InFile { file_id, value } = self.definition_source(db); let name = self.name(db).map(|it| it.symbol().clone()).unwrap_or_else(|| sym::underscore); @@ -490,7 +489,7 @@ impl ToNav for hir::Module { } impl ToNav for hir::Crate { - fn to_nav(&self, db: &RootDatabase) -> UpmappingResult { + fn to_nav(&self, db: &RootDatabase) -> UpmappingResult> { self.root_module(db).to_nav(db) } } @@ -499,7 +498,7 @@ impl TryToNav for hir::Impl { fn try_to_nav( &self, sema: &Semantics<'_, RootDatabase>, - ) -> Option> { + ) -> Option>> { let db = sema.db; let InFile { file_id, value: (full_range, source) } = self.source_with_range(db)?; @@ -527,7 +526,7 @@ impl TryToNav for hir::ExternCrateDecl { fn try_to_nav( &self, sema: &Semantics<'_, RootDatabase>, - ) -> Option> { + ) -> Option>> { let db = sema.db; let src = self.source(db)?; let InFile { file_id, value } = src; @@ -559,7 +558,7 @@ impl TryToNav for hir::Field { fn try_to_nav( &self, sema: &Semantics<'_, RootDatabase>, - ) -> Option> { + ) -> Option>> { let db = sema.db; let src = self.source(db)?; let krate = self.parent_def(db).module(db).krate(db); @@ -595,7 +594,7 @@ impl TryToNav for hir::Macro { fn try_to_nav( &self, sema: &Semantics<'_, RootDatabase>, - ) -> Option> { + ) -> Option>> { let db = sema.db; let src = self.source(db)?; let name_owner: &dyn ast::HasName = match &src.value { @@ -620,7 +619,7 @@ impl TryToNav for hir::Adt { fn try_to_nav( &self, sema: &Semantics<'_, RootDatabase>, - ) -> Option> { + ) -> Option>> { match self { hir::Adt::Struct(it) => it.try_to_nav(sema), hir::Adt::Union(it) => it.try_to_nav(sema), @@ -633,7 +632,7 @@ impl TryToNav for hir::AssocItem { fn try_to_nav( &self, sema: &Semantics<'_, RootDatabase>, - ) -> Option> { + ) -> Option>> { match self { AssocItem::Function(it) => it.try_to_nav(sema), AssocItem::Const(it) => it.try_to_nav(sema), @@ -646,7 +645,7 @@ impl TryToNav for hir::GenericParam { fn try_to_nav( &self, sema: &Semantics<'_, RootDatabase>, - ) -> Option> { + ) -> Option>> { match self { hir::GenericParam::TypeParam(it) => it.try_to_nav(sema), hir::GenericParam::ConstParam(it) => it.try_to_nav(sema), @@ -656,7 +655,7 @@ impl TryToNav for hir::GenericParam { } impl ToNav for LocalSource { - fn to_nav(&self, db: &RootDatabase) -> UpmappingResult { + fn to_nav(&self, db: &RootDatabase) -> UpmappingResult> { let InFile { file_id, value } = &self.source; let file_id = *file_id; let local = self.local; @@ -692,7 +691,7 @@ impl ToNav for LocalSource { } impl ToNav for hir::Local { - fn to_nav(&self, db: &RootDatabase) -> UpmappingResult { + fn to_nav(&self, db: &RootDatabase) -> UpmappingResult> { self.primary_source(db).to_nav(db) } } @@ -701,7 +700,7 @@ impl TryToNav for hir::Label { fn try_to_nav( &self, sema: &Semantics<'_, RootDatabase>, - ) -> Option> { + ) -> Option>> { let db = sema.db; let InFile { file_id, value } = self.source(db)?; let name = self.name(db).symbol().clone(); @@ -726,7 +725,7 @@ impl TryToNav for hir::TypeParam { fn try_to_nav( &self, sema: &Semantics<'_, RootDatabase>, - ) -> Option> { + ) -> Option>> { let db = sema.db; let InFile { file_id, value } = self.merge().source(db)?; let name = self.name(db).symbol().clone(); @@ -766,7 +765,7 @@ impl TryToNav for hir::TypeOrConstParam { fn try_to_nav( &self, sema: &Semantics<'_, RootDatabase>, - ) -> Option> { + ) -> Option>> { self.split(sema.db).try_to_nav(sema) } } @@ -775,7 +774,7 @@ impl TryToNav for hir::LifetimeParam { fn try_to_nav( &self, sema: &Semantics<'_, RootDatabase>, - ) -> Option> { + ) -> Option>> { let db = sema.db; let InFile { file_id, value } = self.source(db)?; let name = self.name(db).symbol().clone(); @@ -800,7 +799,7 @@ impl TryToNav for hir::ConstParam { fn try_to_nav( &self, sema: &Semantics<'_, RootDatabase>, - ) -> Option> { + ) -> Option>> { let db = sema.db; let InFile { file_id, value } = self.merge().source(db)?; let name = self.name(db).symbol().clone(); @@ -833,7 +832,7 @@ impl TryToNav for hir::InlineAsmOperand { fn try_to_nav( &self, sema: &Semantics<'_, RootDatabase>, - ) -> Option> { + ) -> Option>> { let db = sema.db; let InFile { file_id, value } = &self.source(db)?; let file_id = *file_id; @@ -858,7 +857,7 @@ impl TryToNav for hir::BuiltinType { fn try_to_nav( &self, sema: &Semantics<'_, RootDatabase>, - ) -> Option> { + ) -> Option>> { let db = sema.db; let krate = all_crates(db) .iter() diff --git a/crates/ide/src/parent_module.rs b/crates/ide/src/parent_module.rs index 509ec2ab4051..d76691a76a63 100644 --- a/crates/ide/src/parent_module.rs +++ b/crates/ide/src/parent_module.rs @@ -22,7 +22,10 @@ use crate::NavigationTarget; // ![Parent Module](https://user-images.githubusercontent.com/48062697/113065580-04c21800-91b1-11eb-9a32-00086161c0bd.gif) /// This returns `Vec` because a module may be included from several places. -pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec { +pub(crate) fn parent_module( + db: &RootDatabase, + position: FilePosition, +) -> Vec> { let sema = Semantics::new(db); let source_file = sema.parse_guess_edition(position.file_id); diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index 3eb7867a3ab3..fc4b602460eb 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs @@ -63,7 +63,7 @@ pub struct ReferenceSearchResult { #[derive(Debug, Clone, UpmapFromRaFixture)] pub struct Declaration { /// Navigation information to jump to the declaration - pub nav: NavigationTarget, + pub nav: NavigationTarget<'static>, /// Whether the declared item is mutable (relevant for variables) pub is_mut: bool, } diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs index 60750608a5b4..544204c7f4d8 100644 --- a/crates/ide/src/runnables.rs +++ b/crates/ide/src/runnables.rs @@ -29,7 +29,7 @@ use crate::{FileId, NavigationTarget, ToNav, TryToNav, references}; #[derive(Debug, Clone, Hash, PartialEq, Eq, UpmapFromRaFixture)] pub struct Runnable { pub use_name_in_title: bool, - pub nav: NavigationTarget, + pub nav: NavigationTarget<'static>, pub kind: RunnableKind, pub cfg: Option, pub update_test: UpdateTest, diff --git a/crates/rust-analyzer/src/lsp/to_proto.rs b/crates/rust-analyzer/src/lsp/to_proto.rs index eff54779697c..0649e172fcdd 100644 --- a/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/crates/rust-analyzer/src/lsp/to_proto.rs @@ -1042,7 +1042,7 @@ pub(crate) fn location( /// Prefer using `location_link`, if the client has the cap. pub(crate) fn location_from_nav( snap: &GlobalStateSnapshot, - nav: NavigationTarget, + nav: NavigationTarget<'_>, ) -> Cancellable { let url = url(snap, nav.file_id); let line_index = snap.file_line_index(nav.file_id)?; @@ -1054,7 +1054,7 @@ pub(crate) fn location_from_nav( pub(crate) fn location_link( snap: &GlobalStateSnapshot, src: Option, - target: NavigationTarget, + target: NavigationTarget<'_>, ) -> Cancellable { let origin_selection_range = match src { Some(src) => { @@ -1076,7 +1076,7 @@ pub(crate) fn location_link( fn location_info( snap: &GlobalStateSnapshot, - target: NavigationTarget, + target: NavigationTarget<'_>, ) -> Cancellable<(lsp_types::Url, lsp_types::Range, lsp_types::Range)> { let line_index = snap.file_line_index(target.file_id)?; @@ -1090,7 +1090,7 @@ fn location_info( pub(crate) fn goto_definition_response( snap: &GlobalStateSnapshot, src: Option, - targets: Vec, + targets: Vec>, ) -> Cancellable { if snap.config.location_link() { let links = targets @@ -1491,7 +1491,7 @@ impl From pub(crate) fn call_hierarchy_item( snap: &GlobalStateSnapshot, - target: NavigationTarget, + target: NavigationTarget<'_>, ) -> Cancellable { let name = target.name.to_string(); let detail = target.description.clone(); @@ -1937,7 +1937,7 @@ pub(crate) mod command { pub(crate) fn goto_location( snap: &GlobalStateSnapshot, - nav: &NavigationTarget, + nav: &NavigationTarget<'_>, ) -> Option { let value = if snap.config.location_link() { let link = location_link(snap, None, nav.clone()).ok()?; From 9343c40d6837e915d308effa63d2f3944211b915 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 26 May 2026 17:35:35 +0200 Subject: [PATCH 02/14] add lifetime to HoverGotoTypeData --- crates/ide/src/hover.rs | 6 +++--- crates/rust-analyzer/src/handlers/request.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 9ed4d6597fab..b43f6fa2735d 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -81,7 +81,7 @@ pub enum HoverAction { Runnable(Runnable), Implementation(FilePosition), Reference(FilePosition), - GoToType(Vec), + GoToType(Vec>), } impl HoverAction { @@ -110,9 +110,9 @@ impl HoverAction { } #[derive(Debug, Clone, Eq, PartialEq, Hash, UpmapFromRaFixture)] -pub struct HoverGotoTypeData { +pub struct HoverGotoTypeData<'db> { pub mod_path: String, - pub nav: NavigationTarget<'static>, + pub nav: NavigationTarget<'db>, } /// Contains the results when hovering over an item diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index 5bc0f5f0a72a..4a836c4b508e 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -2290,7 +2290,7 @@ fn runnable_action_links( fn goto_type_action_links( snap: &GlobalStateSnapshot, - nav_targets: &[HoverGotoTypeData], + nav_targets: &[HoverGotoTypeData<'_>], hover_actions: &HoverActionsConfig, client_commands: &ClientCommandsConfig, ) -> Option { From fb1483ad2a246debce29e14adfd4697ab038924e Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 26 May 2026 17:37:51 +0200 Subject: [PATCH 03/14] add lifetime to AnnotationKind --- crates/ide/src/annotations.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/ide/src/annotations.rs b/crates/ide/src/annotations.rs index 449a03ffd6aa..9637ca17fe05 100644 --- a/crates/ide/src/annotations.rs +++ b/crates/ide/src/annotations.rs @@ -26,13 +26,13 @@ mod fn_references; #[derive(Debug, Hash, PartialEq, Eq)] pub struct Annotation { pub range: TextRange, - pub kind: AnnotationKind, + pub kind: AnnotationKind<'static>, } #[derive(Debug, Hash, PartialEq, Eq)] -pub enum AnnotationKind { +pub enum AnnotationKind<'db> { Runnable(Runnable), - HasImpls { pos: FilePosition, data: Option>> }, + HasImpls { pos: FilePosition, data: Option>> }, HasReferences { pos: FilePosition, data: Option> }, } From 611b2a9b546e28b74074419f636dd571ec41fdd2 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 26 May 2026 17:40:36 +0200 Subject: [PATCH 04/14] add lifetime to Annotation --- crates/ide/src/annotations.rs | 14 +++++++------- crates/ide/src/lib.rs | 6 +++--- crates/rust-analyzer/src/lsp/from_proto.rs | 2 +- crates/rust-analyzer/src/lsp/to_proto.rs | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/crates/ide/src/annotations.rs b/crates/ide/src/annotations.rs index 9637ca17fe05..e79ef14d9a91 100644 --- a/crates/ide/src/annotations.rs +++ b/crates/ide/src/annotations.rs @@ -24,9 +24,9 @@ mod fn_references; // // ![Annotations](https://user-images.githubusercontent.com/48062697/113020672-b7c34f00-917a-11eb-8f6e-858735660a0e.png) #[derive(Debug, Hash, PartialEq, Eq)] -pub struct Annotation { +pub struct Annotation<'db> { pub range: TextRange, - pub kind: AnnotationKind<'static>, + pub kind: AnnotationKind<'db>, } #[derive(Debug, Hash, PartialEq, Eq)] @@ -57,7 +57,7 @@ pub(crate) fn annotations( db: &RootDatabase, config: &AnnotationConfig<'_>, file_id: FileId, -) -> Vec { +) -> Vec> { let mut annotations = FxIndexSet::default(); if config.annotate_runnables { @@ -198,11 +198,11 @@ pub(crate) fn annotations( .collect() } -pub(crate) fn resolve_annotation( +pub(crate) fn resolve_annotation<'db>( db: &RootDatabase, config: &AnnotationConfig<'_>, - mut annotation: Annotation, -) -> Annotation { + mut annotation: Annotation<'db>, +) -> Annotation<'db> { match annotation.kind { AnnotationKind::HasImpls { pos, ref mut data } => { let goto_implementation_config = GotoImplementationConfig { @@ -274,7 +274,7 @@ mod tests { ) { let (analysis, file_id) = fixture::file(ra_fixture); - let annotations: Vec = analysis + let annotations: Vec> = analysis .annotations(config, file_id) .unwrap() .into_iter() diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 3bc59487ec9e..f0749b498a50 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -902,15 +902,15 @@ impl Analysis { &self, config: &AnnotationConfig<'_>, file_id: FileId, - ) -> Cancellable> { + ) -> Cancellable>> { self.with_db(|db| annotations::annotations(db, config, file_id)) } pub fn resolve_annotation( &self, config: &AnnotationConfig<'_>, - annotation: Annotation, - ) -> Cancellable { + annotation: Annotation<'static>, + ) -> Cancellable> { self.with_db(|db| annotations::resolve_annotation(db, config, annotation)) } diff --git a/crates/rust-analyzer/src/lsp/from_proto.rs b/crates/rust-analyzer/src/lsp/from_proto.rs index 333826a1790e..6488edc8ae39 100644 --- a/crates/rust-analyzer/src/lsp/from_proto.rs +++ b/crates/rust-analyzer/src/lsp/from_proto.rs @@ -121,7 +121,7 @@ pub(crate) fn annotation( snap: &GlobalStateSnapshot, range: lsp_types::Range, data: lsp_ext::CodeLensResolveData, -) -> anyhow::Result> { +) -> anyhow::Result>> { match data.kind { lsp_ext::CodeLensResolveDataKind::Impls(params) => { if snap.url_file_version(¶ms.text_document_position_params.text_document.uri) diff --git a/crates/rust-analyzer/src/lsp/to_proto.rs b/crates/rust-analyzer/src/lsp/to_proto.rs index 0649e172fcdd..e4a2f933bc4b 100644 --- a/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/crates/rust-analyzer/src/lsp/to_proto.rs @@ -1681,7 +1681,7 @@ pub(crate) fn runnable( pub(crate) fn code_lens( acc: &mut Vec, snap: &GlobalStateSnapshot, - annotation: Annotation, + annotation: Annotation<'_>, ) -> Cancellable<()> { let client_commands_config = snap.config.client_commands(); match annotation.kind { From f776187bca5b6338425f4773ddbd34042e6f9424 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 26 May 2026 17:47:28 +0200 Subject: [PATCH 05/14] add lifetime to Runnable --- crates/ide/src/annotations.rs | 2 +- crates/ide/src/hover.rs | 2 +- crates/ide/src/lib.rs | 4 +- crates/ide/src/runnables.rs | 42 +++++++++++--------- crates/ide/src/test_explorer.rs | 2 +- crates/rust-analyzer/src/handlers/request.rs | 6 +-- crates/rust-analyzer/src/lsp/to_proto.rs | 2 +- 7 files changed, 33 insertions(+), 27 deletions(-) diff --git a/crates/ide/src/annotations.rs b/crates/ide/src/annotations.rs index e79ef14d9a91..a37a295c0214 100644 --- a/crates/ide/src/annotations.rs +++ b/crates/ide/src/annotations.rs @@ -31,7 +31,7 @@ pub struct Annotation<'db> { #[derive(Debug, Hash, PartialEq, Eq)] pub enum AnnotationKind<'db> { - Runnable(Runnable), + Runnable(Runnable<'db>), HasImpls { pos: FilePosition, data: Option>> }, HasReferences { pos: FilePosition, data: Option> }, } diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index b43f6fa2735d..d0de3f765a03 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -78,7 +78,7 @@ pub enum HoverDocFormat { #[derive(Debug, Clone, Hash, PartialEq, Eq, UpmapFromRaFixture)] pub enum HoverAction { - Runnable(Runnable), + Runnable(Runnable<'static>), Implementation(FilePosition), Reference(FilePosition), GoToType(Vec>), diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index f0749b498a50..d6b3868c88ef 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -699,7 +699,7 @@ impl Analysis { } /// Returns the set of possible targets to run for the current file. - pub fn runnables(&self, file_id: FileId) -> Cancellable> { + pub fn runnables(&self, file_id: FileId) -> Cancellable>> { self.with_db(|db| runnables::runnables(db, file_id)) } @@ -708,7 +708,7 @@ impl Analysis { &self, position: FilePosition, search_scope: Option, - ) -> Cancellable> { + ) -> Cancellable>> { let search_scope = AssertUnwindSafe(search_scope); self.with_db(|db| { let _ = &search_scope; diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs index 544204c7f4d8..f2c085bbc34c 100644 --- a/crates/ide/src/runnables.rs +++ b/crates/ide/src/runnables.rs @@ -27,9 +27,9 @@ use syntax::{ use crate::{FileId, NavigationTarget, ToNav, TryToNav, references}; #[derive(Debug, Clone, Hash, PartialEq, Eq, UpmapFromRaFixture)] -pub struct Runnable { +pub struct Runnable<'db> { pub use_name_in_title: bool, - pub nav: NavigationTarget<'static>, + pub nav: NavigationTarget<'db>, pub kind: RunnableKind, pub cfg: Option, pub update_test: UpdateTest, @@ -82,7 +82,7 @@ impl RunnableKind { } } -impl Runnable { +impl Runnable<'_> { pub fn label(&self, target: Option<&str>) -> String { match &self.kind { RunnableKind::Test { test_id, .. } => format!("test {test_id}"), @@ -126,14 +126,14 @@ impl Runnable { // | VS Code | **rust-analyzer: Run** | // // ![Run](https://user-images.githubusercontent.com/48062697/113065583-055aae80-91b1-11eb-958f-d67efcaf6a2f.gif) -pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec { +pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec> { let sema = Semantics::new(db); let mut res = Vec::new(); // Record all runnables that come from macro expansions here instead. // In case an expansion creates multiple runnables we want to name them to avoid emitting a bunch of equally named runnables. - let mut in_macro_expansion = FxIndexMap::>::default(); - let mut add_opt = |runnable: Option, def| { + let mut in_macro_expansion = FxIndexMap::>>::default(); + let mut add_opt = |runnable: Option>, def| { if let Some(runnable) = runnable.filter(|runnable| runnable.nav.file_id == file_id) { if let Some(def) = def { let file_id = match def { @@ -202,9 +202,9 @@ pub(crate) fn related_tests( db: &RootDatabase, position: FilePosition, search_scope: Option, -) -> Vec { +) -> Vec> { let sema = Semantics::new(db); - let mut res: FxIndexSet = FxIndexSet::default(); + let mut res: FxIndexSet> = FxIndexSet::default(); let syntax = sema.parse_guess_edition(position.file_id).syntax().clone(); find_related_tests(&sema, &syntax, position, search_scope, &mut res); @@ -213,8 +213,8 @@ pub(crate) fn related_tests( } fn cmp_runnables( - Runnable { nav, kind, .. }: &Runnable, - Runnable { nav: nav_b, kind: kind_b, .. }: &Runnable, + Runnable { nav, kind, .. }: &Runnable<'_>, + Runnable { nav: nav_b, kind: kind_b, .. }: &Runnable<'_>, ) -> std::cmp::Ordering { // full_range.start < focus_range.start < name, should give us a decent unique ordering nav.full_range @@ -235,7 +235,7 @@ fn find_related_tests( syntax: &SyntaxNode, position: FilePosition, search_scope: Option, - tests: &mut FxIndexSet, + tests: &mut FxIndexSet>, ) { // FIXME: why is this using references::find_defs, this should use ide_db::search let defs = match references::find_defs(sema, syntax, position.offset) { @@ -275,7 +275,7 @@ fn find_related_tests_in_module( syntax: &SyntaxNode, fn_def: &ast::Fn, parent_module: &hir::Module, - tests: &mut FxIndexSet, + tests: &mut FxIndexSet>, ) { let fn_name = match fn_def.name() { Some(it) => it, @@ -292,7 +292,10 @@ fn find_related_tests_in_module( find_related_tests(sema, syntax, fn_pos, Some(mod_scope), tests) } -fn as_test_runnable(sema: &Semantics<'_, RootDatabase>, fn_def: &ast::Fn) -> Option { +fn as_test_runnable( + sema: &Semantics<'_, RootDatabase>, + fn_def: &ast::Fn, +) -> Option> { if test_related_attribute_syn(fn_def).is_some() { let function = sema.to_def(fn_def)?; runnable_fn(sema, function) @@ -317,7 +320,7 @@ fn parent_test_module(sema: &Semantics<'_, RootDatabase>, fn_def: &ast::Fn) -> O pub(crate) fn runnable_fn( sema: &Semantics<'_, RootDatabase>, def: hir::Function, -) -> Option { +) -> Option> { let edition = def.krate(sema.db).edition(sema.db); let under_cfg_test = has_cfg_test(def.module(sema.db).attrs(sema.db).cfgs(sema.db)); let kind = if !under_cfg_test && def.is_main(sema.db) { @@ -360,7 +363,7 @@ pub(crate) fn runnable_fn( pub(crate) fn runnable_mod( sema: &Semantics<'_, RootDatabase>, def: hir::Module, -) -> Option { +) -> Option> { let cfg = def.attrs(sema.db).cfgs(sema.db); if !has_test_function_or_multiple_test_submodules(sema, &def, has_cfg_test(cfg)) { return None; @@ -399,7 +402,7 @@ pub(crate) fn runnable_mod( pub(crate) fn runnable_impl( sema: &Semantics<'_, RootDatabase>, def: &hir::Impl, -) -> Option { +) -> Option> { let display_target = def.module(sema.db).krate(sema.db).to_display_target(sema.db); let edition = display_target.edition; let attrs = def.attrs(sema.db); @@ -450,7 +453,7 @@ fn has_cfg_test(cfg: Option<&CfgExpr>) -> bool { fn runnable_mod_outline_definition( sema: &Semantics<'_, RootDatabase>, def: hir::Module, -) -> Option { +) -> Option> { def.as_source_file_id(sema.db)?; let cfg = def.attrs(sema.db).cfgs(sema.db); @@ -487,7 +490,10 @@ fn runnable_mod_outline_definition( }) } -fn module_def_doctest(sema: &Semantics<'_, RootDatabase>, def: Definition) -> Option { +fn module_def_doctest( + sema: &Semantics<'_, RootDatabase>, + def: Definition, +) -> Option> { let db = sema.db; let attrs = match def { Definition::Module(it) => it.attrs(db), diff --git a/crates/ide/src/test_explorer.rs b/crates/ide/src/test_explorer.rs index 02040ef1388b..dc2daecebbaf 100644 --- a/crates/ide/src/test_explorer.rs +++ b/crates/ide/src/test_explorer.rs @@ -22,7 +22,7 @@ pub struct TestItem { pub parent: Option, pub file: Option, pub text_range: Option, - pub runnable: Option, + pub runnable: Option>, } pub(crate) fn discover_test_roots(db: &RootDatabase) -> Vec { diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index 4a836c4b508e..484ea3fb1b32 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -1090,7 +1090,7 @@ pub(crate) fn handle_runnables( Ok(res) } -fn should_skip_for_offset(runnable: &Runnable, offset: Option) -> bool { +fn should_skip_for_offset(runnable: &Runnable<'_>, offset: Option) -> bool { match offset { None => false, _ if matches!(&runnable.kind, RunnableKind::TestMod { .. }) => false, @@ -2244,7 +2244,7 @@ fn show_ref_command_link( fn runnable_action_links( snap: &GlobalStateSnapshot, - runnable: Runnable, + runnable: Runnable<'_>, hover_actions_config: &HoverActionsConfig, client_commands_config: &ClientCommandsConfig, ) -> Option { @@ -2341,7 +2341,7 @@ fn prepare_hover_actions( .collect() } -fn should_skip_target(runnable: &Runnable, cargo_spec: Option<&TargetSpec>) -> bool { +fn should_skip_target(runnable: &Runnable<'_>, cargo_spec: Option<&TargetSpec>) -> bool { match runnable.kind { RunnableKind::Bin => { // Do not suggest binary run on other target than binary diff --git a/crates/rust-analyzer/src/lsp/to_proto.rs b/crates/rust-analyzer/src/lsp/to_proto.rs index e4a2f933bc4b..ee4884b68f12 100644 --- a/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/crates/rust-analyzer/src/lsp/to_proto.rs @@ -1567,7 +1567,7 @@ pub(crate) fn code_action( pub(crate) fn runnable( snap: &GlobalStateSnapshot, - runnable: Runnable, + runnable: Runnable<'_>, ) -> Cancellable> { let target_spec = TargetSpec::for_file(snap, runnable.nav.file_id)?; let source_root = snap.analysis.source_root_id(runnable.nav.file_id).ok(); From ce2ecaf13fd0ddf336e5046e25e3e368c6976565 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 26 May 2026 17:55:49 +0200 Subject: [PATCH 06/14] add lifetime to TestItem --- crates/ide/src/lib.rs | 11 +++++++---- crates/ide/src/test_explorer.rs | 16 ++++++++-------- crates/rust-analyzer/src/lsp/to_proto.rs | 2 +- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index d6b3868c88ef..a38f56a04b24 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -403,19 +403,22 @@ impl Analysis { self.with_db(|db| view_item_tree::view_item_tree(db, file_id)) } - pub fn discover_test_roots(&self) -> Cancellable> { + pub fn discover_test_roots(&self) -> Cancellable>> { self.with_db(test_explorer::discover_test_roots) } - pub fn discover_tests_in_crate_by_test_id(&self, crate_id: &str) -> Cancellable> { + pub fn discover_tests_in_crate_by_test_id( + &self, + crate_id: &str, + ) -> Cancellable>> { self.with_db(|db| test_explorer::discover_tests_in_crate_by_test_id(db, crate_id)) } - pub fn discover_tests_in_crate(&self, crate_id: Crate) -> Cancellable> { + pub fn discover_tests_in_crate(&self, crate_id: Crate) -> Cancellable>> { self.with_db(|db| test_explorer::discover_tests_in_crate(db, crate_id)) } - pub fn discover_tests_in_file(&self, file_id: FileId) -> Cancellable> { + pub fn discover_tests_in_file(&self, file_id: FileId) -> Cancellable>> { self.with_db(|db| test_explorer::discover_tests_in_file(db, file_id)) } diff --git a/crates/ide/src/test_explorer.rs b/crates/ide/src/test_explorer.rs index dc2daecebbaf..a269f870bc2e 100644 --- a/crates/ide/src/test_explorer.rs +++ b/crates/ide/src/test_explorer.rs @@ -15,17 +15,17 @@ pub enum TestItemKind { } #[derive(Debug)] -pub struct TestItem { +pub struct TestItem<'db> { pub id: String, pub kind: TestItemKind, pub label: String, pub parent: Option, pub file: Option, pub text_range: Option, - pub runnable: Option>, + pub runnable: Option>, } -pub(crate) fn discover_test_roots(db: &RootDatabase) -> Vec { +pub(crate) fn discover_test_roots(db: &RootDatabase) -> Vec> { all_crates(db) .iter() .copied() @@ -59,7 +59,7 @@ fn discover_tests_in_module( module: Module, prefix_id: String, only_in_this_file: bool, -) -> Vec { +) -> Vec> { let sema = Semantics::new(db); let mut r = vec![]; @@ -112,14 +112,14 @@ fn discover_tests_in_module( pub(crate) fn discover_tests_in_crate_by_test_id( db: &RootDatabase, crate_test_id: &str, -) -> Vec { +) -> Vec> { let Some(crate_id) = find_crate_by_id(db, crate_test_id) else { return vec![]; }; discover_tests_in_crate(db, crate_id) } -pub(crate) fn discover_tests_in_file(db: &RootDatabase, file_id: FileId) -> Vec { +pub(crate) fn discover_tests_in_file(db: &RootDatabase, file_id: FileId) -> Vec> { let sema = Semantics::new(db); let Some(module) = sema.file_to_module_def(file_id) else { return vec![] }; @@ -133,7 +133,7 @@ pub(crate) fn discover_tests_in_file(db: &RootDatabase, file_id: FileId) -> Vec< fn find_module_id_and_test_parents( sema: &Semantics<'_, RootDatabase>, module: Module, -) -> Option<(Vec, String)> { +) -> Option<(Vec>, String)> { let Some(parent) = module.parent(sema.db) else { let name = module.krate(sema.db).display_name(sema.db)?.to_string(); return Some(( @@ -171,7 +171,7 @@ fn find_module_id_and_test_parents( pub(crate) fn discover_tests_in_crate( db: &RootDatabase, crate_id: base_db::Crate, -) -> Vec { +) -> Vec> { if !crate_id.data(db).origin.is_local() { return vec![]; } diff --git a/crates/rust-analyzer/src/lsp/to_proto.rs b/crates/rust-analyzer/src/lsp/to_proto.rs index ee4884b68f12..59efafe65c26 100644 --- a/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/crates/rust-analyzer/src/lsp/to_proto.rs @@ -1843,7 +1843,7 @@ pub(crate) fn code_lens( pub(crate) fn test_item( snap: &GlobalStateSnapshot, - test_item: ide::TestItem, + test_item: ide::TestItem<'_>, line_index: Option<&LineIndex>, ) -> Option { Some(lsp_ext::TestItem { From 26cdf0415591a30d0b503a5b858704a9040d1745 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 26 May 2026 18:07:27 +0200 Subject: [PATCH 07/14] add lifetime to Declaration --- crates/ide/src/references.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index fc4b602460eb..1a5de65f83af 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs @@ -49,7 +49,7 @@ pub struct ReferenceSearchResult { /// Information about the declaration site of the searched item. /// For ADTs (structs/enums), this points to the type definition. /// May be None for primitives or items without clear declaration sites. - pub declaration: Option, + pub declaration: Option>, /// All references found, grouped by file. /// For ADTs when searching from a constructor position (e.g. on '{', '(', ';'), /// this only includes constructor/initialization usages. @@ -61,9 +61,9 @@ pub struct ReferenceSearchResult { /// Information about the declaration site of a searched item. #[derive(Debug, Clone, UpmapFromRaFixture)] -pub struct Declaration { +pub struct Declaration<'db> { /// Navigation information to jump to the declaration - pub nav: NavigationTarget<'static>, + pub nav: NavigationTarget<'db>, /// Whether the declared item is mutable (relevant for variables) pub is_mut: bool, } From c74278cd3122f8f512f786bd2ac44b441cbf5fbd Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 26 May 2026 18:09:02 +0200 Subject: [PATCH 08/14] add lifetime to ReferenceSearchResult --- crates/ide/src/lib.rs | 2 +- crates/ide/src/references.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index a38f56a04b24..bdd26c7dae58 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -581,7 +581,7 @@ impl Analysis { &self, position: FilePosition, config: &FindAllRefsConfig<'_>, - ) -> Cancellable>> { + ) -> Cancellable>>> { let config = AssertUnwindSafe(config); self.with_db(|db| references::find_all_refs(&Semantics::new(db), position, &config)) } diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index 1a5de65f83af..dd1a1c26a23c 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs @@ -45,11 +45,11 @@ use crate::{ /// Result of a reference search operation. #[derive(Debug, Clone, UpmapFromRaFixture)] -pub struct ReferenceSearchResult { +pub struct ReferenceSearchResult<'db> { /// Information about the declaration site of the searched item. /// For ADTs (structs/enums), this points to the type definition. /// May be None for primitives or items without clear declaration sites. - pub declaration: Option>, + pub declaration: Option>, /// All references found, grouped by file. /// For ADTs when searching from a constructor position (e.g. on '{', '(', ';'), /// this only includes constructor/initialization usages. @@ -125,7 +125,7 @@ pub(crate) fn find_all_refs( sema: &Semantics<'_, RootDatabase>, position: FilePosition, config: &FindAllRefsConfig<'_>, -) -> Option> { +) -> Option>> { let _p = tracing::info_span!("find_all_refs").entered(); let syntax = sema.parse_guess_edition(position.file_id).syntax().clone(); let exclude_library_refs = !is_library_file(sema.db, position.file_id); @@ -445,7 +445,7 @@ fn is_lit_name_ref(name_ref: &ast::NameRef) -> bool { fn handle_control_flow_keywords( sema: &Semantics<'_, RootDatabase>, FilePosition { file_id, offset }: FilePosition, -) -> Option { +) -> Option> { let file = sema.parse_guess_edition(file_id); let edition = sema.attach_first_edition(file_id).edition(sema.db); let token = pick_best_token(file.syntax().token_at_offset(offset), |kind| match kind { From 2bd14ce71441acf1cf8abc9357e7a14e603b1553 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 26 May 2026 18:14:46 +0200 Subject: [PATCH 09/14] add lifetime to HoverAction --- crates/ide/src/hover.rs | 22 ++++++++++---------- crates/ide/src/hover/render.rs | 2 +- crates/rust-analyzer/src/handlers/request.rs | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index d0de3f765a03..9bbe3556625a 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -77,14 +77,14 @@ pub enum HoverDocFormat { } #[derive(Debug, Clone, Hash, PartialEq, Eq, UpmapFromRaFixture)] -pub enum HoverAction { - Runnable(Runnable<'static>), +pub enum HoverAction<'db> { + Runnable(Runnable<'db>), Implementation(FilePosition), Reference(FilePosition), - GoToType(Vec>), + GoToType(Vec>), } -impl HoverAction { +impl HoverAction<'_> { fn goto_type_from_targets( sema: &Semantics<'_, RootDatabase>, targets: Vec, @@ -119,7 +119,7 @@ pub struct HoverGotoTypeData<'db> { #[derive(Clone, Debug, Default, Hash, PartialEq, Eq, UpmapFromRaFixture)] pub struct HoverResult { pub markup: Markup, - pub actions: Vec, + pub actions: Vec>, } // Feature: Hover @@ -543,8 +543,8 @@ fn notable_traits<'db>( fn show_implementations_action( sema: &Semantics<'_, RootDatabase>, def: Definition, -) -> Option { - fn to_action(nav_target: NavigationTarget<'_>) -> HoverAction { +) -> Option> { + fn to_action(nav_target: NavigationTarget<'_>) -> HoverAction<'static> { HoverAction::Implementation(FilePosition { file_id: nav_target.file_id, offset: nav_target.focus_or_full_range().start(), @@ -565,7 +565,7 @@ fn show_implementations_action( fn show_fn_references_action( sema: &Semantics<'_, RootDatabase>, def: Definition, -) -> Option { +) -> Option> { match def { Definition::Function(it) => { it.try_to_nav(sema).map(UpmappingResult::call_site).map(|nav_target| { @@ -583,7 +583,7 @@ fn runnable_action( sema: &hir::Semantics<'_, RootDatabase>, def: Definition, file_id: FileId, -) -> Option { +) -> Option> { match def { Definition::Module(it) => runnable_mod(sema, it).map(HoverAction::Runnable), Definition::Function(func) => { @@ -606,7 +606,7 @@ fn goto_type_action_for_def( notable_traits: &[(hir::Trait, Vec<(Option>, hir::Name)>)], subst_types: Option)>>, edition: Edition, -) -> Option { +) -> Option> { let db = sema.db; let mut targets: Vec = Vec::new(); let mut push_new_def = |item: hir::ModuleDef| { @@ -681,7 +681,7 @@ fn walk_and_push_ty( }); } -fn dedupe_or_merge_hover_actions(actions: Vec) -> Vec { +fn dedupe_or_merge_hover_actions(actions: Vec>) -> Vec> { let mut deduped_actions = Vec::with_capacity(actions.len()); let mut go_to_type_targets = FxIndexSet::default(); diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index da4f185d7564..b45e0904127c 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -1240,7 +1240,7 @@ fn render_memory_layout<'db>( struct KeywordHint { description: String, keyword_mod: String, - actions: Vec, + actions: Vec>, } impl KeywordHint { diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index 484ea3fb1b32..876dd226a861 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -2312,7 +2312,7 @@ fn goto_type_action_links( fn prepare_hover_actions( snap: &GlobalStateSnapshot, - actions: &[HoverAction], + actions: &[HoverAction<'_>], ) -> Vec { let hover_actions = snap.config.hover_actions(); let client_commands = snap.config.client_commands(); From b7d6ddfc44c0e2113eab89b01ceed67cb721fb2a Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 26 May 2026 18:19:42 +0200 Subject: [PATCH 10/14] add lifetime to HoverResult --- crates/ide/src/hover.rs | 16 ++++++++-------- crates/ide/src/hover/render.rs | 20 ++++++++++---------- crates/ide/src/lib.rs | 2 +- crates/ide/src/static_index.rs | 3 ++- 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 9bbe3556625a..01ac18998f00 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -117,9 +117,9 @@ pub struct HoverGotoTypeData<'db> { /// Contains the results when hovering over an item #[derive(Clone, Debug, Default, Hash, PartialEq, Eq, UpmapFromRaFixture)] -pub struct HoverResult { +pub struct HoverResult<'db> { pub markup: Markup, - pub actions: Vec>, + pub actions: Vec>, } // Feature: Hover @@ -132,7 +132,7 @@ pub(crate) fn hover( db: &RootDatabase, frange @ FileRange { file_id, range }: FileRange, config: &HoverConfig<'_>, -) -> Option> { +) -> Option>> { let sema = &hir::Semantics::new(db); let file = sema.parse_guess_edition(file_id).syntax().clone(); let edition = sema.attach_first_edition(file_id).edition(db); @@ -164,7 +164,7 @@ fn hover_offset( config: &HoverConfig<'_>, edition: Edition, display_target: DisplayTarget, -) -> Option> { +) -> Option>> { let original_token = pick_best_token(file.token_at_offset(offset), |kind| match kind { IDENT | INT_NUMBER @@ -385,12 +385,12 @@ fn hover_offset( res.into_iter() .unique() - .reduce(|mut acc: HoverResult, HoverResult { markup, actions }| { + .reduce(|mut acc: HoverResult<'_>, HoverResult { markup, actions }| { acc.actions.extend(actions); acc.markup = Markup::from(format!("{}\n\n---\n{markup}", acc.markup)); acc }) - .map(|mut res: HoverResult| { + .map(|mut res: HoverResult<'_>| { res.actions = dedupe_or_merge_hover_actions(res.actions); RangeInfo::new(original_token.text_range(), res) }) @@ -403,7 +403,7 @@ fn hover_ranged( config: &HoverConfig<'_>, edition: Edition, display_target: DisplayTarget, -) -> Option> { +) -> Option>> { // FIXME: make this work in attributes let expr_or_pat = file .covering_element(range) @@ -458,7 +458,7 @@ pub(crate) fn hover_for_definition( config: &HoverConfig<'_>, edition: Edition, display_target: DisplayTarget, -) -> HoverResult { +) -> HoverResult<'static> { let famous_defs = match &def { Definition::BuiltinType(_) => sema.scope(scope_node).map(|it| FamousDefs(sema, it.krate())), _ => None, diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index b45e0904127c..c62bbdd403cf 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -39,7 +39,7 @@ pub(super) fn type_info_of( expr_or_pat: &Either, edition: Edition, display_target: DisplayTarget, -) -> Option { +) -> Option> { let ty_info = match expr_or_pat { Either::Left(expr) => sema.type_of_expr(expr)?, Either::Right(pat) => sema.type_of_pat(pat)?, @@ -53,7 +53,7 @@ pub(super) fn closure_expr( c: ast::ClosureExpr, edition: Edition, display_target: DisplayTarget, -) -> Option { +) -> Option> { let TypeInfo { original, .. } = sema.type_of_expr(&c.into())?; closure_ty(sema, config, &TypeInfo { original, adjusted: None }, edition, display_target) } @@ -64,7 +64,7 @@ pub(super) fn try_expr( try_expr: &ast::TryExpr, edition: Edition, display_target: DisplayTarget, -) -> Option { +) -> Option> { let inner_ty = sema.type_of_expr(&try_expr.expr()?)?.original; let mut ancestors = try_expr.syntax().ancestors(); let mut body_ty = loop { @@ -159,7 +159,7 @@ pub(super) fn deref_expr( deref_expr: &ast::PrefixExpr, edition: Edition, display_target: DisplayTarget, -) -> Option { +) -> Option> { let inner_ty = sema.type_of_expr(&deref_expr.expr()?)?.original; let TypeInfo { original, adjusted } = sema.type_of_expr(&ast::Expr::from(deref_expr.clone()))?; @@ -223,7 +223,7 @@ pub(super) fn underscore( token: &SyntaxToken, edition: Edition, display_target: DisplayTarget, -) -> Option { +) -> Option> { if token.kind() != T![_] { return None; } @@ -244,7 +244,7 @@ pub(super) fn keyword( token: &SyntaxToken, edition: Edition, display_target: DisplayTarget, -) -> Option { +) -> Option> { if !token.kind().is_keyword(edition) || !config.documentation || !config.keywords { return None; } @@ -271,7 +271,7 @@ pub(super) fn struct_rest_pat( pattern: &ast::RecordPat, edition: Edition, display_target: DisplayTarget, -) -> HoverResult { +) -> HoverResult<'static> { let matched_fields = sema.record_pattern_matched_fields(pattern); // if there are no matched fields, the end result is a hover that shows ".." @@ -306,7 +306,7 @@ pub(super) fn struct_rest_pat( res } -pub(super) fn try_for_lint(attr: &ast::Attr, token: &SyntaxToken) -> Option { +pub(super) fn try_for_lint(attr: &ast::Attr, token: &SyntaxToken) -> Option> { let (path, tt) = attr.as_simple_call()?; if !tt.syntax().text_range().contains(token.text_range().start()) { return None; @@ -948,7 +948,7 @@ fn type_info( ty: TypeInfo<'_>, edition: Edition, display_target: DisplayTarget, -) -> Option { +) -> Option> { if let Some(res) = closure_ty(sema, config, &ty, edition, display_target) { return Some(res); }; @@ -1007,7 +1007,7 @@ fn closure_ty( TypeInfo { original, adjusted }: &TypeInfo<'_>, edition: Edition, display_target: DisplayTarget, -) -> Option { +) -> Option> { let c = original.as_closure()?; let captures = c.captured_items(sema.db); let mut captures_rendered = captures diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index bdd26c7dae58..66adb8c62331 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -591,7 +591,7 @@ impl Analysis { &self, config: &HoverConfig<'_>, range: FileRange, - ) -> Cancellable>> { + ) -> Cancellable>>> { self.with_db(|db| hover::hover(db, range, config)) } diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs index 4b2c9ceef9ff..7ad2f0d1083e 100644 --- a/crates/ide/src/static_index.rs +++ b/crates/ide/src/static_index.rs @@ -44,7 +44,8 @@ pub struct ReferenceData { pub struct TokenStaticData { // FIXME: Make this have the lifetime of the database. pub documentation: Option>, - pub hover: Option, + // FIXME: Make this have the lifetime of the database. + pub hover: Option>, /// The position of the token itself. /// /// For example, in `fn foo() {}` this is the position of `foo`. From d9f4dfe12a7456b6931ad3942f75ade9a899ffbf Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 26 May 2026 18:34:21 +0200 Subject: [PATCH 11/14] add lifetime to TokenStaticData.hover --- crates/ide/src/static_index.rs | 15 +++++++-------- crates/rust-analyzer/src/cli/lsif.rs | 2 +- crates/rust-analyzer/src/cli/scip.rs | 4 ++-- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs index 7ad2f0d1083e..b90a3d6b95f2 100644 --- a/crates/ide/src/static_index.rs +++ b/crates/ide/src/static_index.rs @@ -41,11 +41,10 @@ pub struct ReferenceData { } #[derive(Debug)] -pub struct TokenStaticData { +pub struct TokenStaticData<'db> { // FIXME: Make this have the lifetime of the database. pub documentation: Option>, - // FIXME: Make this have the lifetime of the database. - pub hover: Option>, + pub hover: Option>, /// The position of the token itself. /// /// For example, in `fn foo() {}` this is the position of `foo`. @@ -72,24 +71,24 @@ impl TokenId { } #[derive(Default, Debug)] -pub struct TokenStore(Vec); +pub struct TokenStore(Vec>); impl TokenStore { - pub fn insert(&mut self, data: TokenStaticData) -> TokenId { + pub fn insert(&mut self, data: TokenStaticData<'static>) -> TokenId { let id = TokenId(self.0.len()); self.0.push(data); id } - pub fn get_mut(&mut self, id: TokenId) -> Option<&mut TokenStaticData> { + pub fn get_mut(&mut self, id: TokenId) -> Option<&mut TokenStaticData<'static>> { self.0.get_mut(id.0) } - pub fn get(&self, id: TokenId) -> Option<&TokenStaticData> { + pub fn get(&self, id: TokenId) -> Option<&TokenStaticData<'static>> { self.0.get(id.0) } - pub fn iter(self) -> impl Iterator { + pub fn iter(self) -> impl Iterator)> { self.0.into_iter().enumerate().map(|(id, data)| (TokenId(id), data)) } } diff --git a/crates/rust-analyzer/src/cli/lsif.rs b/crates/rust-analyzer/src/cli/lsif.rs index 4f6de6850abb..468d428ad722 100644 --- a/crates/rust-analyzer/src/cli/lsif.rs +++ b/crates/rust-analyzer/src/cli/lsif.rs @@ -151,7 +151,7 @@ impl LsifManager<'_, '_> { doc_id } - fn add_token(&mut self, id: TokenId, token: TokenStaticData) { + fn add_token(&mut self, id: TokenId, token: TokenStaticData<'_>) { let result_set_id = self.get_token_id(id); if let Some(hover) = token.hover { let hover_id = self.add_vertex(lsif::Vertex::HoverResult { diff --git a/crates/rust-analyzer/src/cli/scip.rs b/crates/rust-analyzer/src/cli/scip.rs index bca38ed82fdd..ad2af51b44cc 100644 --- a/crates/rust-analyzer/src/cli/scip.rs +++ b/crates/rust-analyzer/src/cli/scip.rs @@ -311,7 +311,7 @@ Duplicate symbols encountered: fn compute_symbol_info( symbol: String, enclosing_symbol: Option, - token: &TokenStaticData, + token: &TokenStaticData<'_>, ) -> SymbolInformation { let documentation = match &token.documentation { Some(doc) => vec![doc.as_str().to_owned()], @@ -437,7 +437,7 @@ impl SymbolGenerator { self.local_count = 0; } - fn token_symbols(&mut self, id: TokenId, token: &TokenStaticData) -> Option { + fn token_symbols(&mut self, id: TokenId, token: &TokenStaticData<'_>) -> Option { let mut local_count = self.local_count; let token_symbols = self .token_to_symbols From e319a740c2472a7dc26149b2dfb8392b57685eb6 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 26 May 2026 18:36:25 +0200 Subject: [PATCH 12/14] add lifetime to TokenStore --- crates/ide/src/static_index.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs index b90a3d6b95f2..e9e271362dfb 100644 --- a/crates/ide/src/static_index.rs +++ b/crates/ide/src/static_index.rs @@ -28,7 +28,7 @@ use crate::{ #[derive(Debug)] pub struct StaticIndex<'a> { pub files: Vec, - pub tokens: TokenStore, + pub tokens: TokenStore<'a>, analysis: &'a Analysis, db: &'a RootDatabase, def_map: FxHashMap, @@ -71,24 +71,24 @@ impl TokenId { } #[derive(Default, Debug)] -pub struct TokenStore(Vec>); +pub struct TokenStore<'db>(Vec>); -impl TokenStore { - pub fn insert(&mut self, data: TokenStaticData<'static>) -> TokenId { +impl<'db> TokenStore<'db> { + pub fn insert(&mut self, data: TokenStaticData<'db>) -> TokenId { let id = TokenId(self.0.len()); self.0.push(data); id } - pub fn get_mut(&mut self, id: TokenId) -> Option<&mut TokenStaticData<'static>> { + pub fn get_mut(&mut self, id: TokenId) -> Option<&mut TokenStaticData<'db>> { self.0.get_mut(id.0) } - pub fn get(&self, id: TokenId) -> Option<&TokenStaticData<'static>> { + pub fn get(&self, id: TokenId) -> Option<&TokenStaticData<'db>> { self.0.get(id.0) } - pub fn iter(self) -> impl Iterator)> { + pub fn iter(self) -> impl Iterator)> { self.0.into_iter().enumerate().map(|(id, data)| (TokenId(id), data)) } } @@ -149,7 +149,7 @@ pub enum VendoredLibrariesConfig<'a> { Excluded, } -impl StaticIndex<'_> { +impl<'db> StaticIndex<'db> { fn add_file(&mut self, file_id: FileId) { let current_crate = crates_for(self.db, file_id).pop().map(Into::into); let folds = self.analysis.folding_ranges(file_id, true).unwrap(); From 6f90e05429948ed8996f8121adad5a336bc517d0 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 26 May 2026 18:09:38 +0200 Subject: [PATCH 13/14] don't `to_owned` in `NavigationTarget::from_module_to_decl` Note: this will not compile due to the queries in `ide` --- crates/ide/src/annotations.rs | 6 +++--- crates/ide/src/child_modules.rs | 6 +++--- crates/ide/src/goto_declaration.rs | 6 +++--- crates/ide/src/hover.rs | 24 ++++++++++++------------ crates/ide/src/navigation_target.rs | 6 +++--- crates/ide/src/parent_module.rs | 6 +++--- crates/ide/src/references.rs | 6 +++--- crates/ide/src/runnables.rs | 18 +++++++++--------- 8 files changed, 39 insertions(+), 39 deletions(-) diff --git a/crates/ide/src/annotations.rs b/crates/ide/src/annotations.rs index a37a295c0214..46d286ca4d5c 100644 --- a/crates/ide/src/annotations.rs +++ b/crates/ide/src/annotations.rs @@ -53,11 +53,11 @@ pub enum AnnotationLocation { AboveWholeItem, } -pub(crate) fn annotations( - db: &RootDatabase, +pub(crate) fn annotations<'db>( + db: &'db RootDatabase, config: &AnnotationConfig<'_>, file_id: FileId, -) -> Vec> { +) -> Vec> { let mut annotations = FxIndexSet::default(); if config.annotate_runnables { diff --git a/crates/ide/src/child_modules.rs b/crates/ide/src/child_modules.rs index cb51f4ae407e..c67eeabddaea 100644 --- a/crates/ide/src/child_modules.rs +++ b/crates/ide/src/child_modules.rs @@ -16,10 +16,10 @@ use crate::NavigationTarget; // | VS Code | **rust-analyzer: Locate child modules** | /// This returns `Vec` because a module may be included from several places. -pub(crate) fn child_modules( - db: &RootDatabase, +pub(crate) fn child_modules<'db>( + db: &'db RootDatabase, position: FilePosition, -) -> Vec> { +) -> Vec> { let sema = Semantics::new(db); let source_file = sema.parse_guess_edition(position.file_id); // First go to the parent module which contains the cursor diff --git a/crates/ide/src/goto_declaration.rs b/crates/ide/src/goto_declaration.rs index b6ce47b17700..88eef28bb80b 100644 --- a/crates/ide/src/goto_declaration.rs +++ b/crates/ide/src/goto_declaration.rs @@ -18,11 +18,11 @@ use crate::{ // - outline modules will navigate to the `mod name;` item declaration // - trait assoc items will navigate to the assoc item of the trait declaration as opposed to the trait impl // - fields in patterns will navigate to the field declaration of the struct, union or variant -pub(crate) fn goto_declaration( - db: &RootDatabase, +pub(crate) fn goto_declaration<'db>( + db: &'db RootDatabase, position @ FilePosition { file_id, offset }: FilePosition, config: &GotoDefinitionConfig<'_>, -) -> Option>>> { +) -> Option>>> { let sema = Semantics::new(db); let file = sema.parse_guess_edition(file_id).syntax().clone(); let original_token = file diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 01ac18998f00..a74e6db19d11 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -128,11 +128,11 @@ pub struct HoverResult<'db> { // Focusing is usually hovering with a mouse, but can also be triggered with a shortcut. // // ![Hover](https://user-images.githubusercontent.com/48062697/113020658-b5f98b80-917a-11eb-9f88-3dbc27320c95.gif) -pub(crate) fn hover( - db: &RootDatabase, +pub(crate) fn hover<'db>( + db: &'db RootDatabase, frange @ FileRange { file_id, range }: FileRange, config: &HoverConfig<'_>, -) -> Option>> { +) -> Option>> { let sema = &hir::Semantics::new(db); let file = sema.parse_guess_edition(file_id).syntax().clone(); let edition = sema.attach_first_edition(file_id).edition(db); @@ -157,14 +157,14 @@ pub(crate) fn hover( } #[allow(clippy::field_reassign_with_default)] -fn hover_offset( - sema: &Semantics<'_, RootDatabase>, +fn hover_offset<'db>( + sema: &Semantics<'db, RootDatabase>, FilePosition { file_id, offset }: FilePosition, file: SyntaxNode, config: &HoverConfig<'_>, edition: Edition, display_target: DisplayTarget, -) -> Option>> { +) -> Option>> { let original_token = pick_best_token(file.token_at_offset(offset), |kind| match kind { IDENT | INT_NUMBER @@ -447,8 +447,8 @@ fn hover_ranged( } // FIXME: Why is this pub(crate)? -pub(crate) fn hover_for_definition( - sema: &Semantics<'_, RootDatabase>, +pub(crate) fn hover_for_definition<'db>( + sema: &Semantics<'db, RootDatabase>, file_id: FileId, def: Definition, subst: Option>, @@ -458,7 +458,7 @@ pub(crate) fn hover_for_definition( config: &HoverConfig<'_>, edition: Edition, display_target: DisplayTarget, -) -> HoverResult<'static> { +) -> HoverResult<'db> { let famous_defs = match &def { Definition::BuiltinType(_) => sema.scope(scope_node).map(|it| FamousDefs(sema, it.krate())), _ => None, @@ -579,11 +579,11 @@ fn show_fn_references_action( } } -fn runnable_action( - sema: &hir::Semantics<'_, RootDatabase>, +fn runnable_action<'db>( + sema: &hir::Semantics<'db, RootDatabase>, def: Definition, file_id: FileId, -) -> Option> { +) -> Option> { match def { Definition::Module(it) => runnable_mod(sema, it).map(HoverAction::Runnable), Definition::Function(func) => { diff --git a/crates/ide/src/navigation_target.rs b/crates/ide/src/navigation_target.rs index ee842ba3be26..7f4508f5c830 100644 --- a/crates/ide/src/navigation_target.rs +++ b/crates/ide/src/navigation_target.rs @@ -141,9 +141,9 @@ impl<'db> NavigationTarget<'db> { } pub(crate) fn from_module_to_decl( - db: &RootDatabase, + db: &'db RootDatabase, module: hir::Module, - ) -> UpmappingResult> { + ) -> UpmappingResult> { let name = module.name(db).map(|it| it.symbol().clone()).unwrap_or_else(|| sym::underscore); match module.declaration_source(db) { Some(InFile { value, file_id }) => { @@ -156,7 +156,7 @@ impl<'db> NavigationTarget<'db> { full_range, SymbolKind::Module, ); - res.docs = module.docs(db).map(Documentation::into_owned); + res.docs = module.docs(db); res.description = Some( module.display(db, module.krate(db).to_display_target(db)).to_string(), ); diff --git a/crates/ide/src/parent_module.rs b/crates/ide/src/parent_module.rs index d76691a76a63..7e7ee08b56dc 100644 --- a/crates/ide/src/parent_module.rs +++ b/crates/ide/src/parent_module.rs @@ -22,10 +22,10 @@ use crate::NavigationTarget; // ![Parent Module](https://user-images.githubusercontent.com/48062697/113065580-04c21800-91b1-11eb-9a32-00086161c0bd.gif) /// This returns `Vec` because a module may be included from several places. -pub(crate) fn parent_module( - db: &RootDatabase, +pub(crate) fn parent_module<'db>( + db: &'db RootDatabase, position: FilePosition, -) -> Vec> { +) -> Vec> { let sema = Semantics::new(db); let source_file = sema.parse_guess_edition(position.file_id); diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index dd1a1c26a23c..625c78e5ee3d 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs @@ -121,11 +121,11 @@ pub struct FindAllRefsConfig<'a> { /// - `;` after unit struct: Shows unit literal initializations /// - Type name in definition: Shows all initialization usages /// In these cases, other kinds of references (like type references) are filtered out. -pub(crate) fn find_all_refs( - sema: &Semantics<'_, RootDatabase>, +pub(crate) fn find_all_refs<'db>( + sema: &Semantics<'db, RootDatabase>, position: FilePosition, config: &FindAllRefsConfig<'_>, -) -> Option>> { +) -> Option>> { let _p = tracing::info_span!("find_all_refs").entered(); let syntax = sema.parse_guess_edition(position.file_id).syntax().clone(); let exclude_library_refs = !is_library_file(sema.db, position.file_id); diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs index f2c085bbc34c..c63308be2106 100644 --- a/crates/ide/src/runnables.rs +++ b/crates/ide/src/runnables.rs @@ -126,14 +126,14 @@ impl Runnable<'_> { // | VS Code | **rust-analyzer: Run** | // // ![Run](https://user-images.githubusercontent.com/48062697/113065583-055aae80-91b1-11eb-958f-d67efcaf6a2f.gif) -pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec> { +pub(crate) fn runnables<'db>(db: &'db RootDatabase, file_id: FileId) -> Vec> { let sema = Semantics::new(db); let mut res = Vec::new(); // Record all runnables that come from macro expansions here instead. // In case an expansion creates multiple runnables we want to name them to avoid emitting a bunch of equally named runnables. - let mut in_macro_expansion = FxIndexMap::>>::default(); - let mut add_opt = |runnable: Option>, def| { + let mut in_macro_expansion = FxIndexMap::>>::default(); + let mut add_opt = |runnable: Option>, def| { if let Some(runnable) = runnable.filter(|runnable| runnable.nav.file_id == file_id) { if let Some(def) = def { let file_id = match def { @@ -360,10 +360,10 @@ pub(crate) fn runnable_fn( Some(Runnable { use_name_in_title: false, nav, kind, cfg, update_test }) } -pub(crate) fn runnable_mod( - sema: &Semantics<'_, RootDatabase>, +pub(crate) fn runnable_mod<'db>( + sema: &Semantics<'db, RootDatabase>, def: hir::Module, -) -> Option> { +) -> Option> { let cfg = def.attrs(sema.db).cfgs(sema.db); if !has_test_function_or_multiple_test_submodules(sema, &def, has_cfg_test(cfg)) { return None; @@ -490,10 +490,10 @@ fn runnable_mod_outline_definition( }) } -fn module_def_doctest( - sema: &Semantics<'_, RootDatabase>, +fn module_def_doctest<'db>( + sema: &Semantics<'db, RootDatabase>, def: Definition, -) -> Option> { +) -> Option> { let db = sema.db; let attrs = match def { Definition::Module(it) => it.attrs(db), From 0f8f7626328c0ae0e878efa31ffe2addaee2601a Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Wed, 27 May 2026 16:40:05 +0200 Subject: [PATCH 14/14] fix the fallout by sometimes turning `NavigationTarget<'db>` into `NavigationTarget<'static>` --- crates/ide/src/annotations.rs | 6 ++--- crates/ide/src/child_modules.rs | 8 ++++--- crates/ide/src/goto_declaration.rs | 13 ++++++---- crates/ide/src/hover.rs | 24 +++++++++---------- crates/ide/src/navigation_target.rs | 4 ++++ crates/ide/src/parent_module.rs | 8 ++++--- crates/ide/src/references.rs | 13 +++++----- crates/ide/src/runnables.rs | 37 +++++++++++++++++++---------- 8 files changed, 68 insertions(+), 45 deletions(-) diff --git a/crates/ide/src/annotations.rs b/crates/ide/src/annotations.rs index 46d286ca4d5c..a37a295c0214 100644 --- a/crates/ide/src/annotations.rs +++ b/crates/ide/src/annotations.rs @@ -53,11 +53,11 @@ pub enum AnnotationLocation { AboveWholeItem, } -pub(crate) fn annotations<'db>( - db: &'db RootDatabase, +pub(crate) fn annotations( + db: &RootDatabase, config: &AnnotationConfig<'_>, file_id: FileId, -) -> Vec> { +) -> Vec> { let mut annotations = FxIndexSet::default(); if config.annotate_runnables { diff --git a/crates/ide/src/child_modules.rs b/crates/ide/src/child_modules.rs index c67eeabddaea..8fbd1b35110d 100644 --- a/crates/ide/src/child_modules.rs +++ b/crates/ide/src/child_modules.rs @@ -16,10 +16,10 @@ use crate::NavigationTarget; // | VS Code | **rust-analyzer: Locate child modules** | /// This returns `Vec` because a module may be included from several places. -pub(crate) fn child_modules<'db>( - db: &'db RootDatabase, +pub(crate) fn child_modules( + db: &RootDatabase, position: FilePosition, -) -> Vec> { +) -> Vec> { let sema = Semantics::new(db); let source_file = sema.parse_guess_edition(position.file_id); // First go to the parent module which contains the cursor @@ -32,6 +32,7 @@ pub(crate) fn child_modules<'db>( .into_iter() .flat_map(|module| module.children(db)) .map(|module| NavigationTarget::from_module_to_decl(db, module).call_site()) + .map(NavigationTarget::into_owned) .collect() } None => { @@ -39,6 +40,7 @@ pub(crate) fn child_modules<'db>( sema.file_to_module_defs(position.file_id) .flat_map(|module| module.children(db)) .map(|module| NavigationTarget::from_module_to_decl(db, module).call_site()) + .map(NavigationTarget::into_owned) .collect() } } diff --git a/crates/ide/src/goto_declaration.rs b/crates/ide/src/goto_declaration.rs index 88eef28bb80b..b0d4d6b12f23 100644 --- a/crates/ide/src/goto_declaration.rs +++ b/crates/ide/src/goto_declaration.rs @@ -18,18 +18,18 @@ use crate::{ // - outline modules will navigate to the `mod name;` item declaration // - trait assoc items will navigate to the assoc item of the trait declaration as opposed to the trait impl // - fields in patterns will navigate to the field declaration of the struct, union or variant -pub(crate) fn goto_declaration<'db>( - db: &'db RootDatabase, +pub(crate) fn goto_declaration( + db: &RootDatabase, position @ FilePosition { file_id, offset }: FilePosition, config: &GotoDefinitionConfig<'_>, -) -> Option>>> { +) -> Option>>> { let sema = Semantics::new(db); let file = sema.parse_guess_edition(file_id).syntax().clone(); let original_token = file .token_at_offset(offset) .find(|it| matches!(it.kind(), IDENT | T![self] | T![super] | T![crate] | T![Self]))?; let range = original_token.text_range(); - let info: Vec> = sema + let info: Vec> = sema .descend_into_macros_no_opaque(original_token, false) .iter() .filter_map(|token| { @@ -53,7 +53,10 @@ pub(crate) fn goto_declaration<'db>( }; let assoc = match def? { Definition::Module(module) => { - return Some(NavigationTarget::from_module_to_decl(db, module)); + return Some( + NavigationTarget::from_module_to_decl(db, module) + .map(NavigationTarget::into_owned), + ); } Definition::Const(c) => c.as_assoc_item(db), Definition::TypeAlias(ta) => ta.as_assoc_item(db), diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index a74e6db19d11..01ac18998f00 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -128,11 +128,11 @@ pub struct HoverResult<'db> { // Focusing is usually hovering with a mouse, but can also be triggered with a shortcut. // // ![Hover](https://user-images.githubusercontent.com/48062697/113020658-b5f98b80-917a-11eb-9f88-3dbc27320c95.gif) -pub(crate) fn hover<'db>( - db: &'db RootDatabase, +pub(crate) fn hover( + db: &RootDatabase, frange @ FileRange { file_id, range }: FileRange, config: &HoverConfig<'_>, -) -> Option>> { +) -> Option>> { let sema = &hir::Semantics::new(db); let file = sema.parse_guess_edition(file_id).syntax().clone(); let edition = sema.attach_first_edition(file_id).edition(db); @@ -157,14 +157,14 @@ pub(crate) fn hover<'db>( } #[allow(clippy::field_reassign_with_default)] -fn hover_offset<'db>( - sema: &Semantics<'db, RootDatabase>, +fn hover_offset( + sema: &Semantics<'_, RootDatabase>, FilePosition { file_id, offset }: FilePosition, file: SyntaxNode, config: &HoverConfig<'_>, edition: Edition, display_target: DisplayTarget, -) -> Option>> { +) -> Option>> { let original_token = pick_best_token(file.token_at_offset(offset), |kind| match kind { IDENT | INT_NUMBER @@ -447,8 +447,8 @@ fn hover_ranged( } // FIXME: Why is this pub(crate)? -pub(crate) fn hover_for_definition<'db>( - sema: &Semantics<'db, RootDatabase>, +pub(crate) fn hover_for_definition( + sema: &Semantics<'_, RootDatabase>, file_id: FileId, def: Definition, subst: Option>, @@ -458,7 +458,7 @@ pub(crate) fn hover_for_definition<'db>( config: &HoverConfig<'_>, edition: Edition, display_target: DisplayTarget, -) -> HoverResult<'db> { +) -> HoverResult<'static> { let famous_defs = match &def { Definition::BuiltinType(_) => sema.scope(scope_node).map(|it| FamousDefs(sema, it.krate())), _ => None, @@ -579,11 +579,11 @@ fn show_fn_references_action( } } -fn runnable_action<'db>( - sema: &hir::Semantics<'db, RootDatabase>, +fn runnable_action( + sema: &hir::Semantics<'_, RootDatabase>, def: Definition, file_id: FileId, -) -> Option> { +) -> Option> { match def { Definition::Module(it) => runnable_mod(sema, it).map(HoverAction::Runnable), Definition::Function(func) => { diff --git a/crates/ide/src/navigation_target.rs b/crates/ide/src/navigation_target.rs index 7f4508f5c830..23610e78c572 100644 --- a/crates/ide/src/navigation_target.rs +++ b/crates/ide/src/navigation_target.rs @@ -237,6 +237,10 @@ impl<'db> NavigationTarget<'db> { alias: None, } } + + pub(crate) fn into_owned(self) -> NavigationTarget<'static> { + NavigationTarget { docs: self.docs.map(Documentation::into_owned), ..self } + } } impl<'db> TryToNav for FileSymbol<'db> { diff --git a/crates/ide/src/parent_module.rs b/crates/ide/src/parent_module.rs index 7e7ee08b56dc..97f8bbd8eb1e 100644 --- a/crates/ide/src/parent_module.rs +++ b/crates/ide/src/parent_module.rs @@ -22,10 +22,10 @@ use crate::NavigationTarget; // ![Parent Module](https://user-images.githubusercontent.com/48062697/113065580-04c21800-91b1-11eb-9a32-00086161c0bd.gif) /// This returns `Vec` because a module may be included from several places. -pub(crate) fn parent_module<'db>( - db: &'db RootDatabase, +pub(crate) fn parent_module( + db: &RootDatabase, position: FilePosition, -) -> Vec> { +) -> Vec> { let sema = Semantics::new(db); let source_file = sema.parse_guess_edition(position.file_id); @@ -46,10 +46,12 @@ pub(crate) fn parent_module<'db>( .to_def(&module) .into_iter() .flat_map(|module| NavigationTarget::from_module_to_decl(db, module)) + .map(NavigationTarget::into_owned) .collect(), None => sema .file_to_module_defs(position.file_id) .flat_map(|module| NavigationTarget::from_module_to_decl(db, module)) + .map(NavigationTarget::into_owned) .collect(), } } diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index 625c78e5ee3d..2881c0bcf85d 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs @@ -121,11 +121,11 @@ pub struct FindAllRefsConfig<'a> { /// - `;` after unit struct: Shows unit literal initializations /// - Type name in definition: Shows all initialization usages /// In these cases, other kinds of references (like type references) are filtered out. -pub(crate) fn find_all_refs<'db>( - sema: &Semantics<'db, RootDatabase>, +pub(crate) fn find_all_refs( + sema: &Semantics<'_, RootDatabase>, position: FilePosition, config: &FindAllRefsConfig<'_>, -) -> Option>> { +) -> Option>> { let _p = tracing::info_span!("find_all_refs").entered(); let syntax = sema.parse_guess_edition(position.file_id).syntax().clone(); let exclude_library_refs = !is_library_file(sema.db, position.file_id); @@ -162,9 +162,10 @@ pub(crate) fn find_all_refs<'db>( }) .collect(); let declaration = match def { - Definition::Module(module) => { - Some(NavigationTarget::from_module_to_decl(sema.db, module)) - } + Definition::Module(module) => Some( + NavigationTarget::from_module_to_decl(sema.db, module) + .map(NavigationTarget::into_owned), + ), def => def.try_to_nav(sema), } .map(|nav| { diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs index c63308be2106..87dd9e6d8643 100644 --- a/crates/ide/src/runnables.rs +++ b/crates/ide/src/runnables.rs @@ -113,6 +113,10 @@ impl Runnable<'_> { s.push_str(suffix); s } + + pub(crate) fn into_owned(self) -> Runnable<'static> { + Runnable { nav: self.nav.into_owned(), ..self } + } } // Feature: Run @@ -126,14 +130,14 @@ impl Runnable<'_> { // | VS Code | **rust-analyzer: Run** | // // ![Run](https://user-images.githubusercontent.com/48062697/113065583-055aae80-91b1-11eb-958f-d67efcaf6a2f.gif) -pub(crate) fn runnables<'db>(db: &'db RootDatabase, file_id: FileId) -> Vec> { +pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec> { let sema = Semantics::new(db); let mut res = Vec::new(); // Record all runnables that come from macro expansions here instead. // In case an expansion creates multiple runnables we want to name them to avoid emitting a bunch of equally named runnables. - let mut in_macro_expansion = FxIndexMap::>>::default(); - let mut add_opt = |runnable: Option>, def| { + let mut in_macro_expansion = FxIndexMap::>>::default(); + let mut add_opt = |runnable: Option>, def| { if let Some(runnable) = runnable.filter(|runnable| runnable.nav.file_id == file_id) { if let Some(def) = def { let file_id = match def { @@ -158,7 +162,10 @@ pub(crate) fn runnables<'db>(db: &'db RootDatabase, file_id: FileId) -> Vec runnable_impl(&sema, &impl_), _ => None, }; - add_opt(runnable.or_else(|| module_def_doctest(&sema, def)), Some(def)); + add_opt( + runnable.or_else(|| module_def_doctest(&sema, def).map(Runnable::into_owned)), + Some(def), + ); if let Definition::SelfType(impl_) = def { impl_.items(db).into_iter().for_each(|assoc| { let runnable = match assoc { @@ -168,7 +175,7 @@ pub(crate) fn runnables<'db>(db: &'db RootDatabase, file_id: FileId) -> Vec module_def_doctest(&sema, it.into()), hir::AssocItem::TypeAlias(it) => module_def_doctest(&sema, it.into()), }; - add_opt(runnable, Some(assoc.into())) + add_opt(runnable.map(Runnable::into_owned), Some(assoc.into())); }); } }); @@ -360,10 +367,10 @@ pub(crate) fn runnable_fn( Some(Runnable { use_name_in_title: false, nav, kind, cfg, update_test }) } -pub(crate) fn runnable_mod<'db>( - sema: &Semantics<'db, RootDatabase>, +pub(crate) fn runnable_mod( + sema: &Semantics<'_, RootDatabase>, def: hir::Module, -) -> Option> { +) -> Option> { let cfg = def.attrs(sema.db).cfgs(sema.db); if !has_test_function_or_multiple_test_submodules(sema, &def, has_cfg_test(cfg)) { return None; @@ -380,7 +387,7 @@ pub(crate) fn runnable_mod<'db>( .join("::"); let cfg = cfg.cloned(); - let nav = NavigationTarget::from_module_to_decl(sema.db, def).call_site(); + let nav = NavigationTarget::from_module_to_decl(sema.db, def).call_site().into_owned(); let module_source = sema.module_definition_node(def); let module_syntax = module_source.file_syntax(sema.db); @@ -490,10 +497,10 @@ fn runnable_mod_outline_definition( }) } -fn module_def_doctest<'db>( - sema: &Semantics<'db, RootDatabase>, +fn module_def_doctest( + sema: &Semantics<'_, RootDatabase>, def: Definition, -) -> Option> { +) -> Option> { let db = sema.db; let attrs = match def { Definition::Module(it) => it.attrs(db), @@ -545,7 +552,11 @@ fn module_def_doctest<'db>( .map_or_else(|| TestId::Name(def_name.display_no_db(edition).to_smolstr()), TestId::Path); let mut nav = match def { - Definition::Module(def) => NavigationTarget::from_module_to_decl(db, def), + Definition::Module(def) => { + // FIXME: this `into_owned` is unfortunate, since we overwrite `nav.docs` to `None` below, + // which will effectively make `nav: NavigationTarget<'static>` anyway + NavigationTarget::from_module_to_decl(db, def).map(NavigationTarget::into_owned) + } def => def.try_to_nav(sema)?, } .call_site();