diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index d7d3171664..cc44ae8fc8 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs @@ -306,6 +306,7 @@ pub struct InlayHintsConfig { pub generic_parameter_hints: GenericParameterHints, pub chaining_hints: bool, pub adjustment_hints: AdjustmentHints, + pub adjustment_hints_disable_reborrows: bool, pub adjustment_hints_mode: AdjustmentHintsMode, pub adjustment_hints_hide_outside_unsafe: bool, pub closure_return_type_hints: ClosureReturnTypeHints, @@ -430,7 +431,7 @@ pub enum LifetimeElisionHints { #[derive(Clone, Debug, PartialEq, Eq)] pub enum AdjustmentHints { Always, - ReborrowOnly, + BorrowsOnly, Never, } @@ -886,6 +887,7 @@ mod tests { closure_return_type_hints: ClosureReturnTypeHints::Never, closure_capture_hints: false, adjustment_hints: AdjustmentHints::Never, + adjustment_hints_disable_reborrows: false, adjustment_hints_mode: AdjustmentHintsMode::Prefix, adjustment_hints_hide_outside_unsafe: false, binding_mode_hints: false, diff --git a/crates/ide/src/inlay_hints/adjustment.rs b/crates/ide/src/inlay_hints/adjustment.rs index e39a5f8889..0fd587a728 100644 --- a/crates/ide/src/inlay_hints/adjustment.rs +++ b/crates/ide/src/inlay_hints/adjustment.rs @@ -47,7 +47,22 @@ pub(super) fn hints( let descended = sema.descend_node_into_attributes(expr.clone()).pop(); let desc_expr = descended.as_ref().unwrap_or(expr); - let adjustments = sema.expr_adjustments(desc_expr).filter(|it| !it.is_empty())?; + let mut adjustments = sema.expr_adjustments(desc_expr).filter(|it| !it.is_empty())?; + + if config.adjustment_hints_disable_reborrows { + // Remove consecutive deref-ref, i.e. reborrows. + let mut i = 0; + while i < adjustments.len().saturating_sub(1) { + let [current, next, ..] = &adjustments[i..] else { unreachable!() }; + if matches!(current.kind, Adjust::Deref(None)) + && matches!(next.kind, Adjust::Borrow(AutoBorrow::Ref(_))) + { + adjustments.splice(i..i + 2, []); + } else { + i += 1; + } + } + } if let ast::Expr::BlockExpr(_) | ast::Expr::IfExpr(_) | ast::Expr::MatchExpr(_) = desc_expr { // Don't show unnecessary reborrows for these, they will just repeat the inner ones again @@ -716,6 +731,38 @@ fn hello(it: &&[impl T]) { //^^(&** //^^) } +"#, + ); + } + + #[test] + fn disable_reborrows() { + check_with_config( + InlayHintsConfig { + adjustment_hints: AdjustmentHints::Always, + adjustment_hints_disable_reborrows: true, + ..DISABLED_CONFIG + }, + r#" +#![rustc_coherence_is_core] + +trait ToOwned { + type Owned; + fn to_owned(&self) -> Self::Owned; +} + +struct String; +impl ToOwned for str { + type Owned = String; + fn to_owned(&self) -> Self::Owned { String } +} + +fn a(s: &String) {} + +fn main() { + let s = "".to_owned(); + a(&s) +} "#, ); } diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs index 14b6529c61..8c3275df1b 100644 --- a/crates/ide/src/static_index.rs +++ b/crates/ide/src/static_index.rs @@ -169,6 +169,7 @@ impl StaticIndex<'_> { closure_return_type_hints: crate::ClosureReturnTypeHints::WithBlock, lifetime_elision_hints: crate::LifetimeElisionHints::Never, adjustment_hints: crate::AdjustmentHints::Never, + adjustment_hints_disable_reborrows: true, adjustment_hints_mode: AdjustmentHintsMode::Prefix, adjustment_hints_hide_outside_unsafe: false, implicit_drop_hints: false, diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index 6c0aa19f57..b17186f8d7 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -1137,6 +1137,7 @@ impl flags::AnalysisStats { }, chaining_hints: true, adjustment_hints: ide::AdjustmentHints::Always, + adjustment_hints_disable_reborrows: true, adjustment_hints_mode: ide::AdjustmentHintsMode::Postfix, adjustment_hints_hide_outside_unsafe: false, closure_return_type_hints: ide::ClosureReturnTypeHints::Always, diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index d4cd56dc55..c2252185a3 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -226,6 +226,14 @@ config_data! { inlayHints_discriminantHints_enable: DiscriminantHintsDef = DiscriminantHintsDef::Never, + /// Disable reborrows in expression adjustments inlay hints. + /// + /// Reborrows are a pair of a builtin deref then borrow, i.e. `&*`. They are inserted by the compiler but are mostly useless to the programmer. + /// + /// Note: if the deref is not builtin (an overloaded deref), or the borrow is `&raw const`/`&raw mut`, they are not removed. + inlayHints_expressionAdjustmentHints_disableReborrows: bool = + true, + /// Show inlay hints for type adjustments. inlayHints_expressionAdjustmentHints_enable: AdjustmentHintsDef = AdjustmentHintsDef::Never, @@ -1888,12 +1896,14 @@ impl Config { AdjustmentHintsDef::Always => ide::AdjustmentHints::Always, AdjustmentHintsDef::Never => match self.inlayHints_reborrowHints_enable() { ReborrowHintsDef::Always | ReborrowHintsDef::Mutable => { - ide::AdjustmentHints::ReborrowOnly + ide::AdjustmentHints::BorrowsOnly } ReborrowHintsDef::Never => ide::AdjustmentHints::Never, }, - AdjustmentHintsDef::Reborrow => ide::AdjustmentHints::ReborrowOnly, + AdjustmentHintsDef::Borrows => ide::AdjustmentHints::BorrowsOnly, }, + adjustment_hints_disable_reborrows: *self + .inlayHints_expressionAdjustmentHints_disableReborrows(), adjustment_hints_mode: match self.inlayHints_expressionAdjustmentHints_mode() { AdjustmentHintsModeDef::Prefix => ide::AdjustmentHintsMode::Prefix, AdjustmentHintsModeDef::Postfix => ide::AdjustmentHintsMode::Postfix, @@ -2822,7 +2832,8 @@ enum ReborrowHintsDef { #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(rename_all = "snake_case")] enum AdjustmentHintsDef { - Reborrow, + #[serde(alias = "Reborrow")] + Borrows, #[serde(with = "true_or_always")] #[serde(untagged)] Always, diff --git a/docs/book/src/configuration_generated.md b/docs/book/src/configuration_generated.md index 6ee956fe0d..9a51212462 100644 --- a/docs/book/src/configuration_generated.md +++ b/docs/book/src/configuration_generated.md @@ -959,6 +959,17 @@ Default: `"never"` Show enum variant discriminant hints. +## rust-analyzer.inlayHints.expressionAdjustmentHints.disableReborrows {#inlayHints.expressionAdjustmentHints.disableReborrows} + +Default: `true` + +Disable reborrows in expression adjustments inlay hints. + +Reborrows are a pair of a builtin deref then borrow, i.e. `&*`. They are inserted by the compiler but are mostly useless to the programmer. + +Note: if the deref is not builtin (an overloaded deref), or the borrow is `&raw const`/`&raw mut`, they are not removed. + + ## rust-analyzer.inlayHints.expressionAdjustmentHints.enable {#inlayHints.expressionAdjustmentHints.enable} Default: `"never"` diff --git a/editors/code/package.json b/editors/code/package.json index 4975ca8586..2b2e25e11c 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -2209,6 +2209,16 @@ } } }, + { + "title": "Inlay Hints", + "properties": { + "rust-analyzer.inlayHints.expressionAdjustmentHints.disableReborrows": { + "markdownDescription": "Disable reborrows in expression adjustments inlay hints.\n\nReborrows are a pair of a builtin deref then borrow, i.e. `&*`. They are inserted by the compiler but are mostly useless to the programmer.\n\nNote: if the deref is not builtin (an overloaded deref), or the borrow is `&raw const`/`&raw mut`, they are not removed.", + "default": true, + "type": "boolean" + } + } + }, { "title": "Inlay Hints", "properties": {