From 831e3535e67af55e18daf401724dc2a51c7c37fa Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 21 Jan 2025 11:15:36 +0100 Subject: [PATCH 1/4] Fix Param::as_local treating closures wrong --- crates/hir/src/lib.rs | 41 +++++++++++------- crates/ide/src/inlay_hints.rs | 2 +- crates/ide/src/inlay_hints/generic_param.rs | 30 +++++++------ crates/ide/src/inlay_hints/param_name.rs | 47 ++++++++++----------- 4 files changed, 67 insertions(+), 53 deletions(-) diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 4938478bb121..0cbc75726bf3 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -45,7 +45,7 @@ use hir_def::{ body::BodyDiagnostic, data::{adt::VariantData, TraitFlags}, generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance}, - hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, Pat}, + hir::{BindingAnnotation, BindingId, Expr, ExprId, ExprOrPatId, LabelId, Pat}, item_tree::{AttrOwner, FieldParent, ItemTreeFieldId, ItemTreeNode}, lang_item::LangItemTarget, layout::{self, ReprOptions, TargetDataLayout}, @@ -2470,20 +2470,31 @@ impl Param { } pub fn as_local(&self, db: &dyn HirDatabase) -> Option { - let parent = match self.func { - Callee::Def(CallableDefId::FunctionId(it)) => DefWithBodyId::FunctionId(it), - Callee::Closure(closure, _) => db.lookup_intern_closure(closure.into()).0, - _ => return None, - }; - let body = db.body(parent); - if let Some(self_param) = body.self_param.filter(|_| self.idx == 0) { - Some(Local { parent, binding_id: self_param }) - } else if let Pat::Bind { id, .. } = - &body[body.params[self.idx - body.self_param.is_some() as usize]] - { - Some(Local { parent, binding_id: *id }) - } else { - None + match self.func { + Callee::Def(CallableDefId::FunctionId(it)) => { + let parent = DefWithBodyId::FunctionId(it); + let body = db.body(parent); + if let Some(self_param) = body.self_param.filter(|_| self.idx == 0) { + Some(Local { parent, binding_id: self_param }) + } else if let Pat::Bind { id, .. } = + &body[body.params[self.idx - body.self_param.is_some() as usize]] + { + Some(Local { parent, binding_id: *id }) + } else { + None + } + } + Callee::Closure(closure, _) => { + let c = db.lookup_intern_closure(closure.into()); + let body = db.body(c.0); + if let Expr::Closure { args, .. } = &body[c.1] { + if let Pat::Bind { id, .. } = &body[args[self.idx]] { + return Some(Local { parent: c.0, binding_id: *id }); + } + } + None + } + _ => None, } } diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index 6d83a747d766..94dd90c4aac0 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs @@ -209,7 +209,7 @@ fn hints( ) { closing_brace::hints(hints, sema, config, file_id, node.clone()); if let Some(any_has_generic_args) = ast::AnyHasGenericArgs::cast(node.clone()) { - generic_param::hints(hints, sema, config, any_has_generic_args); + generic_param::hints(hints, famous_defs, config, any_has_generic_args); } match_ast! { diff --git a/crates/ide/src/inlay_hints/generic_param.rs b/crates/ide/src/inlay_hints/generic_param.rs index 037b328d971f..13055757ba6a 100644 --- a/crates/ide/src/inlay_hints/generic_param.rs +++ b/crates/ide/src/inlay_hints/generic_param.rs @@ -1,17 +1,19 @@ //! Implementation of inlay hints for generic parameters. -use ide_db::{active_parameter::generic_def_for_node, RootDatabase}; +use ide_db::{active_parameter::generic_def_for_node, famous_defs::FamousDefs}; use syntax::{ ast::{self, AnyHasGenericArgs, HasGenericArgs, HasName}, AstNode, }; -use crate::{inlay_hints::GenericParameterHints, InlayHint, InlayHintsConfig, InlayKind}; +use crate::{ + inlay_hints::GenericParameterHints, InlayHint, InlayHintLabel, InlayHintsConfig, InlayKind, +}; -use super::param_name::{is_argument_similar_to_param_name, render_label}; +use super::param_name::is_argument_similar_to_param_name; pub(crate) fn hints( acc: &mut Vec, - sema: &hir::Semantics<'_, RootDatabase>, + FamousDefs(sema, krate): &FamousDefs<'_, '_>, config: &InlayHintsConfig, node: AnyHasGenericArgs, ) -> Option<()> { @@ -45,12 +47,11 @@ pub(crate) fn hints( return None; } - let name = param.name(sema.db); - let param_name = name.as_str(); + let param_name = param.name(sema.db); let should_hide = { let argument = get_string_representation(&arg)?; - is_argument_similar_to_param_name(&argument, param_name) + is_argument_similar_to_param_name(&argument, param_name.as_str()) }; if should_hide { @@ -64,7 +65,7 @@ pub(crate) fn hints( if !type_hints || !matches!(arg, ast::GenericArg::TypeArg(_)) { return None; } - sema.source(it.merge())?.value.syntax().clone() + sema.source(it.merge()).map(|it| it.value.syntax().clone()) } hir::GenericParam::ConstParam(it) => { if !const_hints || !matches!(arg, ast::GenericArg::ConstArg(_)) { @@ -72,17 +73,22 @@ pub(crate) fn hints( } let syntax = sema.source(it.merge())?.value.syntax().clone(); let const_param = ast::ConstParam::cast(syntax)?; - const_param.name()?.syntax().clone() + const_param.name().map(|it| it.syntax().clone()) } hir::GenericParam::LifetimeParam(it) => { if !lifetime_hints || !matches!(arg, ast::GenericArg::LifetimeArg(_)) { return None; } - sema.source(it)?.value.syntax().clone() + sema.source(it).map(|it| it.value.syntax().clone()) } }; - let linked_location = sema.original_range_opt(&source_syntax); - let label = render_label(param_name, config, linked_location); + let linked_location = source_syntax.and_then(|it| sema.original_range_opt(&it)); + let colon = if config.render_colons { ":" } else { "" }; + let label = InlayHintLabel::simple( + format!("{}{colon}", param_name.display(sema.db, krate.edition(sema.db))), + None, + linked_location.map(Into::into), + ); Some(InlayHint { range, diff --git a/crates/ide/src/inlay_hints/param_name.rs b/crates/ide/src/inlay_hints/param_name.rs index a6f7e0c184ac..ac137d97d8ae 100644 --- a/crates/ide/src/inlay_hints/param_name.rs +++ b/crates/ide/src/inlay_hints/param_name.rs @@ -3,7 +3,6 @@ //! fn max(x: i32, y: i32) -> i32 { x + y } //! _ = max(/*x*/4, /*y*/4); //! ``` -use std::fmt::Display; use either::Either; use hir::{Callable, Semantics}; @@ -20,7 +19,7 @@ use crate::{InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, Inla pub(super) fn hints( acc: &mut Vec, - FamousDefs(sema, _): &FamousDefs<'_, '_>, + FamousDefs(sema, krate): &FamousDefs<'_, '_>, config: &InlayHintsConfig, _file_id: EditionedFileId, expr: ast::Expr, @@ -37,23 +36,31 @@ pub(super) fn hints( .filter_map(|(p, arg)| { // Only annotate hints for expressions that exist in the original file let range = sema.original_range_opt(arg.syntax())?; - let source = sema.source(p)?; - let (param_name, name_syntax) = match source.value.as_ref() { - Either::Left(pat) => (pat.name()?, pat.name()), - Either::Right(param) => match param.pat()? { - ast::Pat::IdentPat(it) => (it.name()?, it.name()), - _ => return None, - }, - }; - Some((name_syntax, param_name, arg, range)) + let param_name = p.name(sema.db)?; + Some((p, param_name, arg, range)) }) .filter(|(_, param_name, arg, _)| { - !should_hide_param_name_hint(sema, &callable, ¶m_name.text(), arg) + !should_hide_param_name_hint(sema, &callable, param_name.as_str(), arg) }) .map(|(param, param_name, _, hir::FileRange { range, .. })| { - let linked_location = param.and_then(|name| sema.original_range_opt(name.syntax())); - - let label = render_label(¶m_name, config, linked_location); + let linked_location = (|| { + let source = sema.source(param)?; + let name_syntax = match source.value.as_ref() { + Either::Left(pat) => pat.name(), + Either::Right(param) => match param.pat()? { + ast::Pat::IdentPat(it) => it.name(), + _ => None, + }, + }?; + sema.original_range_opt(name_syntax.syntax()) + })(); + + let colon = if config.render_colons { ":" } else { "" }; + let label = InlayHintLabel::simple( + format!("{}{colon}", param_name.display(sema.db, krate.edition(sema.db))), + None, + linked_location.map(Into::into), + ); InlayHint { range, kind: InlayKind::Parameter, @@ -70,16 +77,6 @@ pub(super) fn hints( Some(()) } -pub(super) fn render_label( - param_name: impl Display, - config: &InlayHintsConfig, - linked_location: Option, -) -> InlayHintLabel { - let colon = if config.render_colons { ":" } else { "" }; - - InlayHintLabel::simple(format!("{param_name}{colon}"), None, linked_location.map(Into::into)) -} - fn get_callable( sema: &Semantics<'_, RootDatabase>, expr: &ast::Expr, From 1977aa99b0a0a5533a5bbbc2089a9426ec9a3db6 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 21 Jan 2025 12:07:50 +0100 Subject: [PATCH 2/4] Make `InlayHint::linked_location` computation lazy --- crates/ide/src/inlay_hints.rs | 22 +- crates/ide/src/inlay_hints/bounds.rs | 32 +- crates/ide/src/inlay_hints/chaining.rs | 301 ++++++++++-------- crates/ide/src/inlay_hints/closing_brace.rs | 6 +- .../ide/src/inlay_hints/closure_captures.rs | 17 +- crates/ide/src/inlay_hints/generic_param.rs | 53 +-- crates/ide/src/inlay_hints/implicit_drop.rs | 29 +- crates/ide/src/inlay_hints/param_name.rs | 24 +- crates/rust-analyzer/src/lsp/to_proto.rs | 5 +- 9 files changed, 285 insertions(+), 204 deletions(-) diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index 94dd90c4aac0..405cbf607840 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs @@ -300,6 +300,7 @@ pub struct InlayHintsConfig { pub closing_brace_hints_min_lines: Option, pub fields_to_resolve: InlayFieldsToResolve, } + impl InlayHintsConfig { fn lazy_text_edit(&self, finish: impl FnOnce() -> TextEdit) -> Lazy { if self.fields_to_resolve.resolve_text_edits { @@ -329,6 +330,19 @@ impl InlayHintsConfig { Lazy::Computed(tooltip) } } + + /// This always reports a resolvable location, so only use this when it is very likely for a + /// location link to actually resolve but where computing `finish` would be costly. + fn lazy_location_opt( + &self, + finish: impl FnOnce() -> Option, + ) -> Option> { + if self.fields_to_resolve.resolve_label_location { + Some(Lazy::Lazy) + } else { + finish().map(Lazy::Computed) + } + } } #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -509,7 +523,7 @@ impl InlayHintLabel { pub fn simple( s: impl Into, tooltip: Option>, - linked_location: Option, + linked_location: Option>, ) -> InlayHintLabel { InlayHintLabel { parts: smallvec![InlayHintLabelPart { text: s.into(), linked_location, tooltip }], @@ -593,7 +607,7 @@ pub struct InlayHintLabelPart { /// refers to (not necessarily the location itself). /// When setting this, no tooltip must be set on the containing hint, or VS Code will display /// them both. - pub linked_location: Option, + pub linked_location: Option>, /// The tooltip to show when hovering over the inlay hint, this may invoke other actions like /// hover requests to show. pub tooltip: Option>, @@ -602,7 +616,7 @@ pub struct InlayHintLabelPart { impl std::hash::Hash for InlayHintLabelPart { fn hash(&self, state: &mut H) { self.text.hash(state); - self.linked_location.hash(state); + self.linked_location.is_some().hash(state); self.tooltip.is_some().hash(state); } } @@ -663,7 +677,7 @@ impl InlayHintLabelBuilder<'_> { if !text.is_empty() { self.result.parts.push(InlayHintLabelPart { text, - linked_location: self.location.take(), + linked_location: self.location.take().map(Lazy::Computed), tooltip: None, }); } diff --git a/crates/ide/src/inlay_hints/bounds.rs b/crates/ide/src/inlay_hints/bounds.rs index 429ddd31cbd0..e9b728bcaa75 100644 --- a/crates/ide/src/inlay_hints/bounds.rs +++ b/crates/ide/src/inlay_hints/bounds.rs @@ -22,11 +22,7 @@ pub(super) fn hints( return None; } - let linked_location = - famous_defs.core_marker_Sized().and_then(|it| it.try_to_nav(sema.db)).map(|it| { - let n = it.call_site(); - FileRange { file_id: n.file_id, range: n.focus_or_full_range() } - }); + let sized_trait = famous_defs.core_marker_Sized(); for param in params.type_or_const_params() { match param { @@ -48,7 +44,17 @@ pub(super) fn hints( } hint.parts.push(InlayHintLabelPart { text: "Sized".to_owned(), - linked_location, + linked_location: sized_trait.and_then(|it| { + config.lazy_location_opt(|| { + it.try_to_nav(sema.db).map(|it| { + let n = it.call_site(); + FileRange { + file_id: n.file_id, + range: n.focus_or_full_range(), + } + }) + }) + }), tooltip: None, }); if has_bounds { @@ -134,12 +140,14 @@ fn foo() {} InlayHintLabelPart { text: "Sized", linked_location: Some( - FileRangeWrapper { - file_id: FileId( - 1, - ), - range: 135..140, - }, + Computed( + FileRangeWrapper { + file_id: FileId( + 1, + ), + range: 135..140, + }, + ), ), tooltip: "", }, diff --git a/crates/ide/src/inlay_hints/chaining.rs b/crates/ide/src/inlay_hints/chaining.rs index 7fa7ab1a94d6..477fb5156be6 100644 --- a/crates/ide/src/inlay_hints/chaining.rs +++ b/crates/ide/src/inlay_hints/chaining.rs @@ -81,7 +81,10 @@ mod tests { use crate::{ fixture, - inlay_hints::tests::{check_expect, check_with_config, DISABLED_CONFIG, TEST_CONFIG}, + inlay_hints::{ + tests::{check_expect, check_with_config, DISABLED_CONFIG, TEST_CONFIG}, + Lazy, + }, InlayHintsConfig, }; @@ -99,7 +102,7 @@ mod tests { let (analysis, file_id) = fixture::file(ra_fixture); let mut inlay_hints = analysis.inlay_hints(&config, file_id, None).unwrap(); inlay_hints.iter_mut().flat_map(|hint| &mut hint.label.parts).for_each(|hint| { - if let Some(loc) = &mut hint.linked_location { + if let Some(Lazy::Computed(loc)) = &mut hint.linked_location { loc.range = TextRange::empty(TextSize::from(0)); } }); @@ -134,12 +137,14 @@ fn main() { InlayHintLabelPart { text: "B", linked_location: Some( - FileRangeWrapper { - file_id: FileId( - 0, - ), - range: 63..64, - }, + Computed( + FileRangeWrapper { + file_id: FileId( + 0, + ), + range: 63..64, + }, + ), ), tooltip: "", }, @@ -151,12 +156,14 @@ fn main() { InlayHintLabelPart { text: "A", linked_location: Some( - FileRangeWrapper { - file_id: FileId( - 0, - ), - range: 7..8, - }, + Computed( + FileRangeWrapper { + file_id: FileId( + 0, + ), + range: 7..8, + }, + ), ), tooltip: "", }, @@ -213,12 +220,14 @@ fn main() { InlayHintLabelPart { text: "C", linked_location: Some( - FileRangeWrapper { - file_id: FileId( - 0, - ), - range: 51..52, - }, + Computed( + FileRangeWrapper { + file_id: FileId( + 0, + ), + range: 51..52, + }, + ), ), tooltip: "", }, @@ -230,12 +239,14 @@ fn main() { InlayHintLabelPart { text: "B", linked_location: Some( - FileRangeWrapper { - file_id: FileId( - 0, - ), - range: 29..30, - }, + Computed( + FileRangeWrapper { + file_id: FileId( + 0, + ), + range: 29..30, + }, + ), ), tooltip: "", }, @@ -276,12 +287,14 @@ fn main() { InlayHintLabelPart { text: "C", linked_location: Some( - FileRangeWrapper { - file_id: FileId( - 0, - ), - range: 51..52, - }, + Computed( + FileRangeWrapper { + file_id: FileId( + 0, + ), + range: 51..52, + }, + ), ), tooltip: "", }, @@ -293,12 +306,14 @@ fn main() { InlayHintLabelPart { text: "B", linked_location: Some( - FileRangeWrapper { - file_id: FileId( - 0, - ), - range: 29..30, - }, + Computed( + FileRangeWrapper { + file_id: FileId( + 0, + ), + range: 29..30, + }, + ), ), tooltip: "", }, @@ -340,12 +355,14 @@ fn main() { InlayHintLabelPart { text: "B", linked_location: Some( - FileRangeWrapper { - file_id: FileId( - 0, - ), - range: 23..24, - }, + Computed( + FileRangeWrapper { + file_id: FileId( + 0, + ), + range: 23..24, + }, + ), ), tooltip: "", }, @@ -353,12 +370,14 @@ fn main() { InlayHintLabelPart { text: "X", linked_location: Some( - FileRangeWrapper { - file_id: FileId( - 0, - ), - range: 55..56, - }, + Computed( + FileRangeWrapper { + file_id: FileId( + 0, + ), + range: 55..56, + }, + ), ), tooltip: "", }, @@ -371,12 +390,14 @@ fn main() { InlayHintLabelPart { text: "A", linked_location: Some( - FileRangeWrapper { - file_id: FileId( - 0, - ), - range: 7..8, - }, + Computed( + FileRangeWrapper { + file_id: FileId( + 0, + ), + range: 7..8, + }, + ), ), tooltip: "", }, @@ -384,12 +405,14 @@ fn main() { InlayHintLabelPart { text: "X", linked_location: Some( - FileRangeWrapper { - file_id: FileId( - 0, - ), - range: 55..56, - }, + Computed( + FileRangeWrapper { + file_id: FileId( + 0, + ), + range: 55..56, + }, + ), ), tooltip: "", }, @@ -435,12 +458,14 @@ fn main() { InlayHintLabelPart { text: "Iterator", linked_location: Some( - FileRangeWrapper { - file_id: FileId( - 1, - ), - range: 0..0, - }, + Computed( + FileRangeWrapper { + file_id: FileId( + 1, + ), + range: 0..0, + }, + ), ), tooltip: "", }, @@ -448,12 +473,14 @@ fn main() { InlayHintLabelPart { text: "Item", linked_location: Some( - FileRangeWrapper { - file_id: FileId( - 1, - ), - range: 0..0, - }, + Computed( + FileRangeWrapper { + file_id: FileId( + 1, + ), + range: 0..0, + }, + ), ), tooltip: "", }, @@ -467,12 +494,14 @@ fn main() { InlayHintLabelPart { text: "Iterator", linked_location: Some( - FileRangeWrapper { - file_id: FileId( - 1, - ), - range: 0..0, - }, + Computed( + FileRangeWrapper { + file_id: FileId( + 1, + ), + range: 0..0, + }, + ), ), tooltip: "", }, @@ -480,12 +509,14 @@ fn main() { InlayHintLabelPart { text: "Item", linked_location: Some( - FileRangeWrapper { - file_id: FileId( - 1, - ), - range: 0..0, - }, + Computed( + FileRangeWrapper { + file_id: FileId( + 1, + ), + range: 0..0, + }, + ), ), tooltip: "", }, @@ -499,12 +530,14 @@ fn main() { InlayHintLabelPart { text: "Iterator", linked_location: Some( - FileRangeWrapper { - file_id: FileId( - 1, - ), - range: 0..0, - }, + Computed( + FileRangeWrapper { + file_id: FileId( + 1, + ), + range: 0..0, + }, + ), ), tooltip: "", }, @@ -512,12 +545,14 @@ fn main() { InlayHintLabelPart { text: "Item", linked_location: Some( - FileRangeWrapper { - file_id: FileId( - 1, - ), - range: 0..0, - }, + Computed( + FileRangeWrapper { + file_id: FileId( + 1, + ), + range: 0..0, + }, + ), ), tooltip: "", }, @@ -531,12 +566,14 @@ fn main() { InlayHintLabelPart { text: "MyIter", linked_location: Some( - FileRangeWrapper { - file_id: FileId( - 0, - ), - range: 0..0, - }, + Computed( + FileRangeWrapper { + file_id: FileId( + 0, + ), + range: 0..0, + }, + ), ), tooltip: "", }, @@ -577,12 +614,14 @@ fn main() { InlayHintLabelPart { text: "Struct", linked_location: Some( - FileRangeWrapper { - file_id: FileId( - 0, - ), - range: 7..13, - }, + Computed( + FileRangeWrapper { + file_id: FileId( + 0, + ), + range: 7..13, + }, + ), ), tooltip: "", }, @@ -594,12 +633,14 @@ fn main() { InlayHintLabelPart { text: "Struct", linked_location: Some( - FileRangeWrapper { - file_id: FileId( - 0, - ), - range: 7..13, - }, + Computed( + FileRangeWrapper { + file_id: FileId( + 0, + ), + range: 7..13, + }, + ), ), tooltip: "", }, @@ -611,12 +652,14 @@ fn main() { InlayHintLabelPart { text: "Struct", linked_location: Some( - FileRangeWrapper { - file_id: FileId( - 0, - ), - range: 7..13, - }, + Computed( + FileRangeWrapper { + file_id: FileId( + 0, + ), + range: 7..13, + }, + ), ), tooltip: "", }, @@ -628,12 +671,14 @@ fn main() { InlayHintLabelPart { text: "self", linked_location: Some( - FileRangeWrapper { - file_id: FileId( - 0, - ), - range: 42..46, - }, + Computed( + FileRangeWrapper { + file_id: FileId( + 0, + ), + range: 42..46, + }, + ), ), tooltip: "", }, diff --git a/crates/ide/src/inlay_hints/closing_brace.rs b/crates/ide/src/inlay_hints/closing_brace.rs index 90b8be64a46d..64f1f83d3f5c 100644 --- a/crates/ide/src/inlay_hints/closing_brace.rs +++ b/crates/ide/src/inlay_hints/closing_brace.rs @@ -11,7 +11,9 @@ use syntax::{ match_ast, SyntaxKind, SyntaxNode, T, }; -use crate::{InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, InlayKind}; +use crate::{ + inlay_hints::Lazy, InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, InlayKind, +}; pub(super) fn hints( acc: &mut Vec, @@ -141,7 +143,7 @@ pub(super) fn hints( acc.push(InlayHint { range: closing_token.text_range(), kind: InlayKind::ClosingBrace, - label: InlayHintLabel::simple(label, None, linked_location), + label: InlayHintLabel::simple(label, None, linked_location.map(Lazy::Computed)), text_edit: None, position: InlayHintPosition::After, pad_left: true, diff --git a/crates/ide/src/inlay_hints/closure_captures.rs b/crates/ide/src/inlay_hints/closure_captures.rs index 906f2acf0c44..3e91618d08e6 100644 --- a/crates/ide/src/inlay_hints/closure_captures.rs +++ b/crates/ide/src/inlay_hints/closure_captures.rs @@ -53,10 +53,6 @@ pub(super) fn hints( let last = captures.len() - 1; for (idx, capture) in captures.into_iter().enumerate() { let local = capture.local(); - let source = local.primary_source(sema.db); - - // force cache the source file, otherwise sema lookup will potentially panic - _ = sema.parse_or_expand(source.file()); let label = format!( "{}{}", @@ -73,8 +69,17 @@ pub(super) fn hints( } hint.label.append_part(InlayHintLabelPart { text: label, - linked_location: source.name().and_then(|name| { - name.syntax().original_file_range_opt(sema.db).map(TupleExt::head).map(Into::into) + linked_location: config.lazy_location_opt(|| { + let source = local.primary_source(sema.db); + + // force cache the source file, otherwise sema lookup will potentially panic + _ = sema.parse_or_expand(source.file()); + source.name().and_then(|name| { + name.syntax() + .original_file_range_opt(sema.db) + .map(TupleExt::head) + .map(Into::into) + }) }), tooltip: None, }); diff --git a/crates/ide/src/inlay_hints/generic_param.rs b/crates/ide/src/inlay_hints/generic_param.rs index 13055757ba6a..762a4c265518 100644 --- a/crates/ide/src/inlay_hints/generic_param.rs +++ b/crates/ide/src/inlay_hints/generic_param.rs @@ -47,6 +47,18 @@ pub(crate) fn hints( return None; } + let allowed = match (param, &arg) { + (hir::GenericParam::TypeParam(_), ast::GenericArg::TypeArg(_)) => type_hints, + (hir::GenericParam::ConstParam(_), ast::GenericArg::ConstArg(_)) => const_hints, + (hir::GenericParam::LifetimeParam(_), ast::GenericArg::LifetimeArg(_)) => { + lifetime_hints + } + _ => false, + }; + if !allowed { + return None; + } + let param_name = param.name(sema.db); let should_hide = { @@ -60,34 +72,27 @@ pub(crate) fn hints( let range = sema.original_range_opt(arg.syntax())?.range; - let source_syntax = match param { - hir::GenericParam::TypeParam(it) => { - if !type_hints || !matches!(arg, ast::GenericArg::TypeArg(_)) { - return None; - } - sema.source(it.merge()).map(|it| it.value.syntax().clone()) - } - hir::GenericParam::ConstParam(it) => { - if !const_hints || !matches!(arg, ast::GenericArg::ConstArg(_)) { - return None; - } - let syntax = sema.source(it.merge())?.value.syntax().clone(); - let const_param = ast::ConstParam::cast(syntax)?; - const_param.name().map(|it| it.syntax().clone()) - } - hir::GenericParam::LifetimeParam(it) => { - if !lifetime_hints || !matches!(arg, ast::GenericArg::LifetimeArg(_)) { - return None; - } - sema.source(it).map(|it| it.value.syntax().clone()) - } - }; - let linked_location = source_syntax.and_then(|it| sema.original_range_opt(&it)); let colon = if config.render_colons { ":" } else { "" }; let label = InlayHintLabel::simple( format!("{}{colon}", param_name.display(sema.db, krate.edition(sema.db))), None, - linked_location.map(Into::into), + config.lazy_location_opt(|| { + let source_syntax = match param { + hir::GenericParam::TypeParam(it) => { + sema.source(it.merge()).map(|it| it.value.syntax().clone()) + } + hir::GenericParam::ConstParam(it) => { + let syntax = sema.source(it.merge())?.value.syntax().clone(); + let const_param = ast::ConstParam::cast(syntax)?; + const_param.name().map(|it| it.syntax().clone()) + } + hir::GenericParam::LifetimeParam(it) => { + sema.source(it).map(|it| it.value.syntax().clone()) + } + }; + let linked_location = source_syntax.and_then(|it| sema.original_range_opt(&it)); + linked_location.map(Into::into) + }), ); Some(InlayHint { diff --git a/crates/ide/src/inlay_hints/implicit_drop.rs b/crates/ide/src/inlay_hints/implicit_drop.rs index 1358d3722f89..27c7c3d49818 100644 --- a/crates/ide/src/inlay_hints/implicit_drop.rs +++ b/crates/ide/src/inlay_hints/implicit_drop.rs @@ -49,7 +49,7 @@ pub(super) fn hints( if mir.locals[place.local].ty.adt_id(ChalkTyInterner).is_none() { continue; // Arguably only ADTs have significant drop impls } - let Some(binding) = local_to_binding.get(place.local) else { + let Some(&binding_idx) = local_to_binding.get(place.local) else { continue; // Ignore temporary values }; let range = match terminator.span { @@ -91,25 +91,26 @@ pub(super) fn hints( }, MirSpan::Unknown => continue, }; - let binding_source = source_map - .patterns_for_binding(*binding) - .first() - .and_then(|d| source_map.pat_syntax(*d).ok()) - .and_then(|d| { - Some(FileRange { - file_id: d.file_id.file_id()?.into(), - range: d.value.text_range(), - }) - }); - let binding = &hir.bindings[*binding]; + let binding = &hir.bindings[binding_idx]; let name = binding.name.display_no_db(file_id.edition()).to_smolstr(); if name.starts_with(" pat.name(), - Either::Right(param) => match param.pat()? { - ast::Pat::IdentPat(it) => it.name(), - _ => None, - }, - }?; - sema.original_range_opt(name_syntax.syntax()) - })(); - let colon = if config.render_colons { ":" } else { "" }; let label = InlayHintLabel::simple( format!("{}{colon}", param_name.display(sema.db, krate.edition(sema.db))), None, - linked_location.map(Into::into), + config.lazy_location_opt(|| { + let source = sema.source(param)?; + let name_syntax = match source.value.as_ref() { + Either::Left(pat) => pat.name(), + Either::Right(param) => match param.pat()? { + ast::Pat::IdentPat(it) => it.name(), + _ => None, + }, + }?; + sema.original_range_opt(name_syntax.syntax()).map(Into::into) + }), ); InlayHint { range, diff --git a/crates/rust-analyzer/src/lsp/to_proto.rs b/crates/rust-analyzer/src/lsp/to_proto.rs index a5516e7f9d4f..4947576f1977 100644 --- a/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/crates/rust-analyzer/src/lsp/to_proto.rs @@ -684,7 +684,10 @@ fn inlay_hint_label( *something_to_resolve |= part.linked_location.is_some(); None } else { - part.linked_location.map(|range| location(snap, range)).transpose()? + part.linked_location + .and_then(|it| it.computed()) + .map(|range| location(snap, range)) + .transpose()? }; Ok(lsp_types::InlayHintLabelPart { value: part.text, From f5b86e056b01b43c64207c9cb03c6c4feabe01b2 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 21 Jan 2025 12:32:11 +0100 Subject: [PATCH 3/4] Keep already computed inlay hint properties instead of late resolving them --- crates/ide/src/inlay_hints.rs | 48 +++---- crates/ide/src/inlay_hints/chaining.rs | 4 +- crates/ide/src/inlay_hints/closing_brace.rs | 4 +- crates/ide/src/lib.rs | 2 +- crates/rust-analyzer/src/lsp/to_proto.rs | 133 ++++++++++---------- 5 files changed, 99 insertions(+), 92 deletions(-) diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index 405cbf607840..088a11bcb4cc 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs @@ -302,21 +302,21 @@ pub struct InlayHintsConfig { } impl InlayHintsConfig { - fn lazy_text_edit(&self, finish: impl FnOnce() -> TextEdit) -> Lazy { + fn lazy_text_edit(&self, finish: impl FnOnce() -> TextEdit) -> LazyProperty { if self.fields_to_resolve.resolve_text_edits { - Lazy::Lazy + LazyProperty::Lazy } else { let edit = finish(); never!(edit.is_empty(), "inlay hint produced an empty text edit"); - Lazy::Computed(edit) + LazyProperty::Computed(edit) } } - fn lazy_tooltip(&self, finish: impl FnOnce() -> InlayTooltip) -> Lazy { + fn lazy_tooltip(&self, finish: impl FnOnce() -> InlayTooltip) -> LazyProperty { if self.fields_to_resolve.resolve_hint_tooltip && self.fields_to_resolve.resolve_label_tooltip { - Lazy::Lazy + LazyProperty::Lazy } else { let tooltip = finish(); never!( @@ -327,7 +327,7 @@ impl InlayHintsConfig { .is_empty(), "inlay hint produced an empty tooltip" ); - Lazy::Computed(tooltip) + LazyProperty::Computed(tooltip) } } @@ -336,11 +336,11 @@ impl InlayHintsConfig { fn lazy_location_opt( &self, finish: impl FnOnce() -> Option, - ) -> Option> { + ) -> Option> { if self.fields_to_resolve.resolve_label_location { - Some(Lazy::Lazy) + Some(LazyProperty::Lazy) } else { - finish().map(Lazy::Computed) + finish().map(LazyProperty::Computed) } } } @@ -455,7 +455,7 @@ pub struct InlayHint { /// The actual label to show in the inlay hint. pub label: InlayHintLabel, /// Text edit to apply when "accepting" this inlay hint. - pub text_edit: Option>, + pub text_edit: Option>, /// Range to recompute inlay hints when trying to resolve for this hint. If this is none, the /// hint does not support resolving. pub resolve_parent: Option, @@ -463,15 +463,15 @@ pub struct InlayHint { /// A type signaling that a value is either computed, or is available for computation. #[derive(Clone, Debug)] -pub enum Lazy { +pub enum LazyProperty { Computed(T), Lazy, } -impl Lazy { +impl LazyProperty { pub fn computed(self) -> Option { match self { - Lazy::Computed(it) => Some(it), + LazyProperty::Computed(it) => Some(it), _ => None, } } @@ -522,8 +522,8 @@ pub struct InlayHintLabel { impl InlayHintLabel { pub fn simple( s: impl Into, - tooltip: Option>, - linked_location: Option>, + tooltip: Option>, + linked_location: Option>, ) -> InlayHintLabel { InlayHintLabel { parts: smallvec![InlayHintLabelPart { text: s.into(), linked_location, tooltip }], @@ -607,10 +607,10 @@ pub struct InlayHintLabelPart { /// refers to (not necessarily the location itself). /// When setting this, no tooltip must be set on the containing hint, or VS Code will display /// them both. - pub linked_location: Option>, + pub linked_location: Option>, /// The tooltip to show when hovering over the inlay hint, this may invoke other actions like /// hover requests to show. - pub tooltip: Option>, + pub tooltip: Option>, } impl std::hash::Hash for InlayHintLabelPart { @@ -624,7 +624,9 @@ impl std::hash::Hash for InlayHintLabelPart { impl fmt::Debug for InlayHintLabelPart { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Self { text, linked_location: None, tooltip: None | Some(Lazy::Lazy) } => text.fmt(f), + Self { text, linked_location: None, tooltip: None | Some(LazyProperty::Lazy) } => { + text.fmt(f) + } Self { text, linked_location, tooltip } => f .debug_struct("InlayHintLabelPart") .field("text", text) @@ -632,8 +634,10 @@ impl fmt::Debug for InlayHintLabelPart { .field( "tooltip", &tooltip.as_ref().map_or("", |it| match it { - Lazy::Computed(InlayTooltip::String(it) | InlayTooltip::Markdown(it)) => it, - Lazy::Lazy => "", + LazyProperty::Computed( + InlayTooltip::String(it) | InlayTooltip::Markdown(it), + ) => it, + LazyProperty::Lazy => "", }), ) .finish(), @@ -677,7 +681,7 @@ impl InlayHintLabelBuilder<'_> { if !text.is_empty() { self.result.parts.push(InlayHintLabelPart { text, - linked_location: self.location.take().map(Lazy::Computed), + linked_location: self.location.take().map(LazyProperty::Computed), tooltip: None, }); } @@ -797,7 +801,7 @@ fn ty_to_text_edit( ty: &hir::Type, offset_to_insert: TextSize, prefix: impl Into, -) -> Option> { +) -> Option> { // FIXME: Limit the length and bail out on excess somehow? let rendered = sema .scope(node_for_hint) diff --git a/crates/ide/src/inlay_hints/chaining.rs b/crates/ide/src/inlay_hints/chaining.rs index 477fb5156be6..8471547727fe 100644 --- a/crates/ide/src/inlay_hints/chaining.rs +++ b/crates/ide/src/inlay_hints/chaining.rs @@ -83,7 +83,7 @@ mod tests { fixture, inlay_hints::{ tests::{check_expect, check_with_config, DISABLED_CONFIG, TEST_CONFIG}, - Lazy, + LazyProperty, }, InlayHintsConfig, }; @@ -102,7 +102,7 @@ mod tests { let (analysis, file_id) = fixture::file(ra_fixture); let mut inlay_hints = analysis.inlay_hints(&config, file_id, None).unwrap(); inlay_hints.iter_mut().flat_map(|hint| &mut hint.label.parts).for_each(|hint| { - if let Some(Lazy::Computed(loc)) = &mut hint.linked_location { + if let Some(LazyProperty::Computed(loc)) = &mut hint.linked_location { loc.range = TextRange::empty(TextSize::from(0)); } }); diff --git a/crates/ide/src/inlay_hints/closing_brace.rs b/crates/ide/src/inlay_hints/closing_brace.rs index 64f1f83d3f5c..bd36e2c3be6f 100644 --- a/crates/ide/src/inlay_hints/closing_brace.rs +++ b/crates/ide/src/inlay_hints/closing_brace.rs @@ -12,7 +12,7 @@ use syntax::{ }; use crate::{ - inlay_hints::Lazy, InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, InlayKind, + inlay_hints::LazyProperty, InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, InlayKind, }; pub(super) fn hints( @@ -143,7 +143,7 @@ pub(super) fn hints( acc.push(InlayHint { range: closing_token.text_range(), kind: InlayKind::ClosingBrace, - label: InlayHintLabel::simple(label, None, linked_location.map(Lazy::Computed)), + label: InlayHintLabel::simple(label, None, linked_location.map(LazyProperty::Computed)), text_edit: None, position: InlayHintPosition::After, pad_left: true, diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 346e2862b0fd..6ec95ccb62a5 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -91,7 +91,7 @@ pub use crate::{ inlay_hints::{ AdjustmentHints, AdjustmentHintsMode, ClosureReturnTypeHints, DiscriminantHints, GenericParameterHints, InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart, - InlayHintPosition, InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints, + InlayHintPosition, InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints, LazyProperty }, join_lines::JoinLinesConfig, markup::Markup, diff --git a/crates/rust-analyzer/src/lsp/to_proto.rs b/crates/rust-analyzer/src/lsp/to_proto.rs index 4947576f1977..2a7d95d560d2 100644 --- a/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/crates/rust-analyzer/src/lsp/to_proto.rs @@ -11,8 +11,8 @@ use ide::{ Annotation, AnnotationKind, Assist, AssistKind, Cancellable, CompletionFieldsToResolve, CompletionItem, CompletionItemKind, CompletionRelevance, Documentation, FileId, FileRange, FileSystemEdit, Fold, FoldKind, Highlight, HlMod, HlOperator, HlPunct, HlRange, HlTag, Indel, - InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart, InlayKind, Markup, - NavigationTarget, ReferenceCategory, RenameError, Runnable, Severity, SignatureHelp, + InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart, InlayKind, LazyProperty, + Markup, NavigationTarget, ReferenceCategory, RenameError, Runnable, Severity, SignatureHelp, SnippetEdit, SourceChange, StructureNodeKind, SymbolKind, TextEdit, TextRange, TextSize, }; use ide_db::{assists, rust_doc::format_docs, FxHasher}; @@ -549,12 +549,11 @@ pub(crate) fn inlay_hint( ) -> Cancellable { let hint_needs_resolve = |hint: &InlayHint| -> Option { hint.resolve_parent.filter(|_| { - hint.text_edit.is_some() - || hint - .label - .parts - .iter() - .any(|part| part.linked_location.is_some() || part.tooltip.is_some()) + hint.text_edit.as_ref().is_some_and(LazyProperty::is_lazy) + || hint.label.parts.iter().any(|part| { + part.linked_location.as_ref().is_some_and(LazyProperty::is_lazy) + || part.tooltip.as_ref().is_some_and(LazyProperty::is_lazy) + }) }) }; @@ -569,22 +568,21 @@ pub(crate) fn inlay_hint( }); let mut something_to_resolve = false; - let text_edits = if snap - .config - .visual_studio_code_version() - .is_none_or(|version| VersionReq::parse(">=1.86.0").unwrap().matches(version)) - && resolve_range_and_hash.is_some() - && fields_to_resolve.resolve_text_edits - { - something_to_resolve |= inlay_hint.text_edit.is_some(); - None - } else { - inlay_hint - .text_edit - .take() - .and_then(|it| it.computed()) - .map(|it| text_edit_vec(line_index, it)) - }; + let text_edits = inlay_hint + .text_edit + .take() + .and_then(|it| match it { + LazyProperty::Computed(it) => Some(it), + LazyProperty::Lazy => { + something_to_resolve |= + snap.config.visual_studio_code_version().is_none_or(|version| { + VersionReq::parse(">=1.86.0").unwrap().matches(version) + }) && resolve_range_and_hash.is_some() + && fields_to_resolve.resolve_text_edits; + None + } + }) + .map(|it| text_edit_vec(line_index, it)); let (label, tooltip) = inlay_hint_label( snap, fields_to_resolve, @@ -637,22 +635,23 @@ fn inlay_hint_label( let (label, tooltip) = match &*label.parts { [InlayHintLabelPart { linked_location: None, .. }] => { let InlayHintLabelPart { text, tooltip, .. } = label.parts.pop().unwrap(); - let hint_tooltip = if needs_resolve && fields_to_resolve.resolve_hint_tooltip { - *something_to_resolve |= tooltip.is_some(); - None - } else { - match tooltip.and_then(|it| it.computed()) { - Some(ide::InlayTooltip::String(s)) => { - Some(lsp_types::InlayHintTooltip::String(s)) - } - Some(ide::InlayTooltip::Markdown(s)) => { - Some(lsp_types::InlayHintTooltip::MarkupContent(lsp_types::MarkupContent { - kind: lsp_types::MarkupKind::Markdown, - value: s, - })) - } - None => None, + let tooltip = tooltip.and_then(|it| match it { + LazyProperty::Computed(it) => Some(it), + LazyProperty::Lazy => { + *something_to_resolve |= + needs_resolve && fields_to_resolve.resolve_hint_tooltip; + None } + }); + let hint_tooltip = match tooltip { + Some(ide::InlayTooltip::String(s)) => Some(lsp_types::InlayHintTooltip::String(s)), + Some(ide::InlayTooltip::Markdown(s)) => { + Some(lsp_types::InlayHintTooltip::MarkupContent(lsp_types::MarkupContent { + kind: lsp_types::MarkupKind::Markdown, + value: s, + })) + } + None => None, }; (lsp_types::InlayHintLabel::String(text), hint_tooltip) } @@ -661,34 +660,38 @@ fn inlay_hint_label( .parts .into_iter() .map(|part| { - let tooltip = if needs_resolve && fields_to_resolve.resolve_label_tooltip { - *something_to_resolve |= part.tooltip.is_some(); - None - } else { - match part.tooltip.and_then(|it| it.computed()) { - Some(ide::InlayTooltip::String(s)) => { - Some(lsp_types::InlayHintLabelPartTooltip::String(s)) - } - Some(ide::InlayTooltip::Markdown(s)) => { - Some(lsp_types::InlayHintLabelPartTooltip::MarkupContent( - lsp_types::MarkupContent { - kind: lsp_types::MarkupKind::Markdown, - value: s, - }, - )) - } - None => None, + let tooltip = part.tooltip.and_then(|it| match it { + LazyProperty::Computed(it) => Some(it), + LazyProperty::Lazy => { + *something_to_resolve |= fields_to_resolve.resolve_label_tooltip; + None } + }); + let tooltip = match tooltip { + Some(ide::InlayTooltip::String(s)) => { + Some(lsp_types::InlayHintLabelPartTooltip::String(s)) + } + Some(ide::InlayTooltip::Markdown(s)) => { + Some(lsp_types::InlayHintLabelPartTooltip::MarkupContent( + lsp_types::MarkupContent { + kind: lsp_types::MarkupKind::Markdown, + value: s, + }, + )) + } + None => None, }; - let location = if needs_resolve && fields_to_resolve.resolve_label_location { - *something_to_resolve |= part.linked_location.is_some(); - None - } else { - part.linked_location - .and_then(|it| it.computed()) - .map(|range| location(snap, range)) - .transpose()? - }; + let location = part + .linked_location + .and_then(|it| match it { + LazyProperty::Computed(it) => Some(it), + LazyProperty::Lazy => { + *something_to_resolve |= fields_to_resolve.resolve_label_location; + None + } + }) + .map(|range| location(snap, range)) + .transpose()?; Ok(lsp_types::InlayHintLabelPart { value: part.text, tooltip, From 41e6a8747de3bce1524807cf0dfe5b14513bb560 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 24 Jan 2025 14:45:38 +0100 Subject: [PATCH 4/4] Lazily compute location links in type hints again --- crates/ide/src/inlay_hints.rs | 21 ++++++++++++++------- crates/ide/src/inlay_hints/closing_brace.rs | 3 ++- crates/ide/src/lib.rs | 3 ++- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index 088a11bcb4cc..1f723c85df7a 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs @@ -650,7 +650,8 @@ struct InlayHintLabelBuilder<'a> { db: &'a RootDatabase, result: InlayHintLabel, last_part: String, - location: Option, + resolve: bool, + location: Option>, } impl fmt::Write for InlayHintLabelBuilder<'_> { @@ -663,11 +664,16 @@ impl HirWrite for InlayHintLabelBuilder<'_> { fn start_location_link(&mut self, def: ModuleDefId) { never!(self.location.is_some(), "location link is already started"); self.make_new_part(); - let Some(location) = ModuleDef::from(def).try_to_nav(self.db) else { return }; - let location = location.call_site(); - let location = - FileRange { file_id: location.file_id, range: location.focus_or_full_range() }; - self.location = Some(location); + + self.location = Some(if self.resolve { + LazyProperty::Lazy + } else { + LazyProperty::Computed({ + let Some(location) = ModuleDef::from(def).try_to_nav(self.db) else { return }; + let location = location.call_site(); + FileRange { file_id: location.file_id, range: location.focus_or_full_range() } + }) + }); } fn end_location_link(&mut self) { @@ -681,7 +687,7 @@ impl InlayHintLabelBuilder<'_> { if !text.is_empty() { self.result.parts.push(InlayHintLabelPart { text, - linked_location: self.location.take().map(LazyProperty::Computed), + linked_location: self.location.take(), tooltip: None, }); } @@ -753,6 +759,7 @@ fn label_of_ty( last_part: String::new(), location: None, result: InlayHintLabel::default(), + resolve: config.fields_to_resolve.resolve_label_location, }; let _ = rec(sema, famous_defs, config.max_length, ty, &mut label_builder, config, edition); let r = label_builder.finish(); diff --git a/crates/ide/src/inlay_hints/closing_brace.rs b/crates/ide/src/inlay_hints/closing_brace.rs index bd36e2c3be6f..3767d34e2c7a 100644 --- a/crates/ide/src/inlay_hints/closing_brace.rs +++ b/crates/ide/src/inlay_hints/closing_brace.rs @@ -12,7 +12,8 @@ use syntax::{ }; use crate::{ - inlay_hints::LazyProperty, InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, InlayKind, + inlay_hints::LazyProperty, InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, + InlayKind, }; pub(super) fn hints( diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 6ec95ccb62a5..41a3302c0953 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -91,7 +91,8 @@ pub use crate::{ inlay_hints::{ AdjustmentHints, AdjustmentHintsMode, ClosureReturnTypeHints, DiscriminantHints, GenericParameterHints, InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart, - InlayHintPosition, InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints, LazyProperty + InlayHintPosition, InlayHintsConfig, InlayKind, InlayTooltip, LazyProperty, + LifetimeElisionHints, }, join_lines::JoinLinesConfig, markup::Markup,