mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 21:05:02 +00:00
feat: Visualize compiler inserted reborrows via inlay hints
This commit is contained in:
parent
2598575a35
commit
37b48ceb8f
9 changed files with 126 additions and 13 deletions
|
@ -19,6 +19,7 @@ pub struct InlayHintsConfig {
|
|||
pub type_hints: bool,
|
||||
pub parameter_hints: bool,
|
||||
pub chaining_hints: bool,
|
||||
pub reborrow_hints: bool,
|
||||
pub closure_return_type_hints: bool,
|
||||
pub lifetime_elision_hints: LifetimeElisionHints,
|
||||
pub param_names_for_lifetime_elision_hints: bool,
|
||||
|
@ -35,6 +36,7 @@ pub enum LifetimeElisionHints {
|
|||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum InlayKind {
|
||||
ImplicitReborrow,
|
||||
TypeHint,
|
||||
ParameterHint,
|
||||
ClosureReturnTypeHint,
|
||||
|
@ -116,17 +118,16 @@ fn hints(
|
|||
if let Some(expr) = ast::Expr::cast(node.clone()) {
|
||||
chaining_hints(hints, sema, &famous_defs, config, &expr);
|
||||
match expr {
|
||||
ast::Expr::CallExpr(it) => {
|
||||
param_name_hints(hints, sema, config, ast::Expr::from(it));
|
||||
}
|
||||
ast::Expr::CallExpr(it) => param_name_hints(hints, sema, config, ast::Expr::from(it)),
|
||||
ast::Expr::MethodCallExpr(it) => {
|
||||
param_name_hints(hints, sema, config, ast::Expr::from(it));
|
||||
param_name_hints(hints, sema, config, ast::Expr::from(it))
|
||||
}
|
||||
ast::Expr::ClosureExpr(it) => {
|
||||
closure_ret_hints(hints, sema, &famous_defs, config, it);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
ast::Expr::ClosureExpr(it) => closure_ret_hints(hints, sema, &famous_defs, config, it),
|
||||
// We could show reborrows for all expressions, but usually that is just noise to the user
|
||||
// and the main point here is to show why "moving" a mutable reference doesn't necessarily move it
|
||||
ast::Expr::PathExpr(_) => reborrow_hints(hints, sema, config, &expr),
|
||||
_ => None,
|
||||
};
|
||||
} else if let Some(it) = ast::IdentPat::cast(node.clone()) {
|
||||
bind_pat_hints(hints, sema, config, &it);
|
||||
} else if let Some(it) = ast::Fn::cast(node) {
|
||||
|
@ -365,6 +366,28 @@ fn closure_ret_hints(
|
|||
Some(())
|
||||
}
|
||||
|
||||
fn reborrow_hints(
|
||||
acc: &mut Vec<InlayHint>,
|
||||
sema: &Semantics<RootDatabase>,
|
||||
config: &InlayHintsConfig,
|
||||
expr: &ast::Expr,
|
||||
) -> Option<()> {
|
||||
if !config.reborrow_hints {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mutability = sema.is_implicit_reborrow(expr)?;
|
||||
acc.push(InlayHint {
|
||||
range: expr.syntax().text_range(),
|
||||
kind: InlayKind::ImplicitReborrow,
|
||||
label: match mutability {
|
||||
hir::Mutability::Shared => SmolStr::new_inline("&*"),
|
||||
hir::Mutability::Mut => SmolStr::new_inline("&mut *"),
|
||||
},
|
||||
});
|
||||
Some(())
|
||||
}
|
||||
|
||||
fn chaining_hints(
|
||||
acc: &mut Vec<InlayHint>,
|
||||
sema: &Semantics<RootDatabase>,
|
||||
|
@ -834,6 +857,7 @@ mod tests {
|
|||
lifetime_elision_hints: LifetimeElisionHints::Never,
|
||||
hide_named_constructor_hints: false,
|
||||
closure_return_type_hints: false,
|
||||
reborrow_hints: false,
|
||||
param_names_for_lifetime_elision_hints: false,
|
||||
max_length: None,
|
||||
};
|
||||
|
@ -841,6 +865,7 @@ mod tests {
|
|||
type_hints: true,
|
||||
parameter_hints: true,
|
||||
chaining_hints: true,
|
||||
reborrow_hints: true,
|
||||
closure_return_type_hints: true,
|
||||
lifetime_elision_hints: LifetimeElisionHints::Always,
|
||||
..DISABLED_CONFIG
|
||||
|
@ -2115,6 +2140,41 @@ impl () {
|
|||
// ^^^<'0, '1>
|
||||
// ^'0 ^'1 ^'0
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hints_implicit_reborrow() {
|
||||
check_with_config(
|
||||
InlayHintsConfig { reborrow_hints: true, ..DISABLED_CONFIG },
|
||||
r#"
|
||||
fn __() {
|
||||
let unique = &mut ();
|
||||
let r_mov = unique;
|
||||
let foo: &mut _ = unique;
|
||||
//^^^^^^ &mut *
|
||||
ref_mut_id(unique);
|
||||
//^^^^^^ &mut *
|
||||
let shared = ref_id(unique);
|
||||
//^^^^^^ &*
|
||||
let mov = shared;
|
||||
let r_mov: &_ = shared;
|
||||
ref_id(shared);
|
||||
|
||||
identity(unique);
|
||||
identity(shared);
|
||||
}
|
||||
fn identity<T>(t: T) -> T {
|
||||
t
|
||||
}
|
||||
fn ref_mut_id(x: &mut ()) -> &mut () {
|
||||
x
|
||||
//^ &mut *
|
||||
}
|
||||
fn ref_id(x: &()) -> &() {
|
||||
x
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue