Skip to content

Commit d3ce333

Browse files
committed
Auto merge of rust-lang#14742 - Veykril:closure-capture-inlays, r=Veykril
feat: Closure capture inlay hints I opted for a fictional `move(foo, &bar, &mut qux)` syntax here, disabled by default as these are not correct rust syntax and hence could cause confusion. ![image](https://user-images.githubusercontent.com/3757771/236447484-649a4ea6-ad61-496e-bad8-765a5236150e.png)
2 parents ff8b969 + 4c5fd19 commit d3ce333

File tree

11 files changed

+278
-37
lines changed

11 files changed

+278
-37
lines changed

crates/hir-ty/src/infer/closure.rs

+4-16
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ impl HirPlace {
148148
}
149149

150150
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
151-
pub(crate) enum CaptureKind {
151+
pub enum CaptureKind {
152152
ByRef(BorrowKind),
153153
ByValue,
154154
}
@@ -166,23 +166,11 @@ impl CapturedItem {
166166
self.place.local
167167
}
168168

169-
pub fn display_kind(&self) -> &'static str {
170-
match self.kind {
171-
CaptureKind::ByRef(k) => match k {
172-
BorrowKind::Shared => "immutable borrow",
173-
BorrowKind::Shallow => {
174-
never!("shallow borrow should not happen in closure captures");
175-
"shallow borrow"
176-
},
177-
BorrowKind::Unique => "unique immutable borrow ([read more](https://doc.rust-lang.org/stable/reference/types/closure.html#unique-immutable-borrows-in-captures))",
178-
BorrowKind::Mut { .. } => "mutable borrow",
179-
},
180-
CaptureKind::ByValue => "move",
181-
}
169+
pub fn kind(&self) -> CaptureKind {
170+
self.kind
182171
}
183172

184-
pub fn display_place(&self, owner: ClosureId, db: &dyn HirDatabase) -> String {
185-
let owner = db.lookup_intern_closure(owner.into()).0;
173+
pub fn display_place(&self, owner: DefWithBodyId, db: &dyn HirDatabase) -> String {
186174
let body = db.body(owner);
187175
let mut result = body[self.place.local].name.to_string();
188176
let mut field_need_paren = false;

crates/hir-ty/src/lib.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,9 @@ pub use autoderef::autoderef;
6161
pub use builder::{ParamKind, TyBuilder};
6262
pub use chalk_ext::*;
6363
pub use infer::{
64-
closure::CapturedItem, could_coerce, could_unify, Adjust, Adjustment, AutoBorrow, BindingMode,
65-
InferenceDiagnostic, InferenceResult, OverloadedDeref, PointerCast,
64+
closure::{CaptureKind, CapturedItem},
65+
could_coerce, could_unify, Adjust, Adjustment, AutoBorrow, BindingMode, InferenceDiagnostic,
66+
InferenceResult, OverloadedDeref, PointerCast,
6667
};
6768
pub use interner::Interner;
6869
pub use lower::{

crates/hir/src/lib.rs

+32-5
Original file line numberDiff line numberDiff line change
@@ -2611,6 +2611,10 @@ impl LocalSource {
26112611
self.source.file_id.original_file(db.upcast())
26122612
}
26132613

2614+
pub fn file(&self) -> HirFileId {
2615+
self.source.file_id
2616+
}
2617+
26142618
pub fn name(&self) -> Option<ast::Name> {
26152619
self.source.value.name()
26162620
}
@@ -3210,7 +3214,11 @@ impl Closure {
32103214
let owner = db.lookup_intern_closure((self.id).into()).0;
32113215
let infer = &db.infer(owner);
32123216
let info = infer.closure_info(&self.id);
3213-
info.0.iter().cloned().map(|capture| ClosureCapture { owner, capture }).collect()
3217+
info.0
3218+
.iter()
3219+
.cloned()
3220+
.map(|capture| ClosureCapture { owner, closure: self.id, capture })
3221+
.collect()
32143222
}
32153223

32163224
pub fn fn_trait(&self, db: &dyn HirDatabase) -> FnTrait {
@@ -3224,6 +3232,7 @@ impl Closure {
32243232
#[derive(Clone, Debug, PartialEq, Eq)]
32253233
pub struct ClosureCapture {
32263234
owner: DefWithBodyId,
3235+
closure: ClosureId,
32273236
capture: hir_ty::CapturedItem,
32283237
}
32293238

@@ -3232,15 +3241,33 @@ impl ClosureCapture {
32323241
Local { parent: self.owner, binding_id: self.capture.local() }
32333242
}
32343243

3235-
pub fn display_kind(&self) -> &'static str {
3236-
self.capture.display_kind()
3244+
pub fn kind(&self) -> CaptureKind {
3245+
match self.capture.kind() {
3246+
hir_ty::CaptureKind::ByRef(
3247+
hir_ty::mir::BorrowKind::Shallow | hir_ty::mir::BorrowKind::Shared,
3248+
) => CaptureKind::SharedRef,
3249+
hir_ty::CaptureKind::ByRef(hir_ty::mir::BorrowKind::Unique) => {
3250+
CaptureKind::UniqueSharedRef
3251+
}
3252+
hir_ty::CaptureKind::ByRef(hir_ty::mir::BorrowKind::Mut { .. }) => {
3253+
CaptureKind::MutableRef
3254+
}
3255+
hir_ty::CaptureKind::ByValue => CaptureKind::Move,
3256+
}
32373257
}
32383258

3239-
pub fn display_place(&self, owner: ClosureId, db: &dyn HirDatabase) -> String {
3240-
self.capture.display_place(owner, db)
3259+
pub fn display_place(&self, db: &dyn HirDatabase) -> String {
3260+
self.capture.display_place(self.owner, db)
32413261
}
32423262
}
32433263

3264+
pub enum CaptureKind {
3265+
SharedRef,
3266+
UniqueSharedRef,
3267+
MutableRef,
3268+
Move,
3269+
}
3270+
32443271
#[derive(Clone, PartialEq, Eq, Debug)]
32453272
pub struct Type {
32463273
env: Arc<TraitEnvironment>,

crates/ide/src/hover/render.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ use std::fmt::Display;
33

44
use either::Either;
55
use hir::{
6-
Adt, AsAssocItem, AttributeTemplate, HasAttrs, HasSource, HirDisplay, Semantics, TypeInfo,
6+
Adt, AsAssocItem, AttributeTemplate, CaptureKind, HasAttrs, HasSource, HirDisplay, Semantics,
7+
TypeInfo,
78
};
89
use ide_db::{
910
base_db::SourceDatabase,
@@ -58,8 +59,14 @@ pub(super) fn closure_expr(
5859
let mut captures = c
5960
.captured_items(sema.db)
6061
.into_iter()
61-
.map(|x| {
62-
format!("* `{}` by {}", x.display_place(c.clone().into(), sema.db), x.display_kind())
62+
.map(|it| {
63+
let borrow_kind= match it.kind() {
64+
CaptureKind::SharedRef => "immutable borrow",
65+
CaptureKind::UniqueSharedRef => "unique immutable borrow ([read more](https://doc.rust-lang.org/stable/reference/types/closure.html#unique-immutable-borrows-in-captures))",
66+
CaptureKind::MutableRef => "mutable borrow",
67+
CaptureKind::Move => "move",
68+
};
69+
format!("* `{}` by {}", it.display_place(sema.db), borrow_kind)
6370
})
6471
.join("\n");
6572
if captures.trim().is_empty() {

crates/ide/src/inlay_hints.rs

+17-11
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,17 @@ use text_edit::TextEdit;
2020

2121
use crate::{navigation_target::TryToNav, FileId};
2222

23-
mod closing_brace;
24-
mod implicit_static;
25-
mod fn_lifetime_fn;
26-
mod closure_ret;
2723
mod adjustment;
28-
mod chaining;
29-
mod param_name;
30-
mod binding_mode;
3124
mod bind_pat;
25+
mod binding_mode;
26+
mod chaining;
27+
mod closing_brace;
28+
mod closure_ret;
29+
mod closure_captures;
3230
mod discriminant;
31+
mod fn_lifetime_fn;
32+
mod implicit_static;
33+
mod param_name;
3334

3435
#[derive(Clone, Debug, PartialEq, Eq)]
3536
pub struct InlayHintsConfig {
@@ -42,6 +43,7 @@ pub struct InlayHintsConfig {
4243
pub adjustment_hints_mode: AdjustmentHintsMode,
4344
pub adjustment_hints_hide_outside_unsafe: bool,
4445
pub closure_return_type_hints: ClosureReturnTypeHints,
46+
pub closure_capture_hints: bool,
4547
pub binding_mode_hints: bool,
4648
pub lifetime_elision_hints: LifetimeElisionHints,
4749
pub param_names_for_lifetime_elision_hints: bool,
@@ -88,6 +90,8 @@ pub enum AdjustmentHintsMode {
8890
PreferPostfix,
8991
}
9092

93+
// FIXME: Clean up this mess, the kinds are mainly used for setting different rendering properties in the lsp layer
94+
// We should probably turns this into such a property holding struct. Or clean this up in some other form.
9195
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
9296
pub enum InlayKind {
9397
BindingMode,
@@ -98,6 +102,7 @@ pub enum InlayKind {
98102
Adjustment,
99103
AdjustmentPostfix,
100104
Lifetime,
105+
ClosureCapture,
101106
Parameter,
102107
Type,
103108
Discriminant,
@@ -444,10 +449,10 @@ fn hints(
444449
ast::Expr::MethodCallExpr(it) => {
445450
param_name::hints(hints, sema, config, ast::Expr::from(it))
446451
}
447-
ast::Expr::ClosureExpr(it) => closure_ret::hints(hints, famous_defs, config, file_id, it),
448-
// We could show reborrows for all expressions, but usually that is just noise to the user
449-
// and the main point here is to show why "moving" a mutable reference doesn't necessarily move it
450-
// ast::Expr::PathExpr(_) => reborrow_hints(hints, sema, config, &expr),
452+
ast::Expr::ClosureExpr(it) => {
453+
closure_captures::hints(hints, famous_defs, config, file_id, it.clone());
454+
closure_ret::hints(hints, famous_defs, config, file_id, it)
455+
},
451456
_ => None,
452457
}
453458
},
@@ -535,6 +540,7 @@ mod tests {
535540
chaining_hints: false,
536541
lifetime_elision_hints: LifetimeElisionHints::Never,
537542
closure_return_type_hints: ClosureReturnTypeHints::Never,
543+
closure_capture_hints: false,
538544
adjustment_hints: AdjustmentHints::Never,
539545
adjustment_hints_mode: AdjustmentHintsMode::Prefix,
540546
adjustment_hints_hide_outside_unsafe: false,

0 commit comments

Comments
 (0)