Skip to content

Commit 6e6a0b0

Browse files
committed
Auto merge of rust-lang#16000 - HKalbasi:drop-inlay-hint, r=HKalbasi
Initial support for implicit drop inlay hint cc rust-lang#15785
2 parents c2f1334 + 4d55cac commit 6e6a0b0

File tree

12 files changed

+284
-25
lines changed

12 files changed

+284
-25
lines changed

crates/hir-ty/src/mir.rs

+14
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,10 @@ impl ProjectionStore {
269269
impl ProjectionId {
270270
pub const EMPTY: ProjectionId = ProjectionId(0);
271271

272+
pub fn is_empty(self) -> bool {
273+
self == ProjectionId::EMPTY
274+
}
275+
272276
pub fn lookup(self, store: &ProjectionStore) -> &[PlaceElem] {
273277
store.id_to_proj.get(&self).unwrap()
274278
}
@@ -1069,6 +1073,10 @@ pub struct MirBody {
10691073
}
10701074

10711075
impl MirBody {
1076+
pub fn local_to_binding_map(&self) -> ArenaMap<LocalId, BindingId> {
1077+
self.binding_locals.iter().map(|(it, y)| (*y, it)).collect()
1078+
}
1079+
10721080
fn walk_places(&mut self, mut f: impl FnMut(&mut Place, &mut ProjectionStore)) {
10731081
fn for_operand(
10741082
op: &mut Operand,
@@ -1188,3 +1196,9 @@ pub enum MirSpan {
11881196
}
11891197

11901198
impl_from!(ExprId, PatId for MirSpan);
1199+
1200+
impl From<&ExprId> for MirSpan {
1201+
fn from(value: &ExprId) -> Self {
1202+
(*value).into()
1203+
}
1204+
}

crates/hir-ty/src/mir/lower.rs

+34-20
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,14 @@ pub enum MirLowerError {
105105
/// A token to ensuring that each drop scope is popped at most once, thanks to the compiler that checks moves.
106106
struct DropScopeToken;
107107
impl DropScopeToken {
108-
fn pop_and_drop(self, ctx: &mut MirLowerCtx<'_>, current: BasicBlockId) -> BasicBlockId {
108+
fn pop_and_drop(
109+
self,
110+
ctx: &mut MirLowerCtx<'_>,
111+
current: BasicBlockId,
112+
span: MirSpan,
113+
) -> BasicBlockId {
109114
std::mem::forget(self);
110-
ctx.pop_drop_scope_internal(current)
115+
ctx.pop_drop_scope_internal(current, span)
111116
}
112117

113118
/// It is useful when we want a drop scope is syntaxically closed, but we don't want to execute any drop
@@ -582,7 +587,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
582587
self.lower_loop(current, place, *label, expr_id.into(), |this, begin| {
583588
let scope = this.push_drop_scope();
584589
if let Some((_, mut current)) = this.lower_expr_as_place(begin, *body, true)? {
585-
current = scope.pop_and_drop(this, current);
590+
current = scope.pop_and_drop(this, current, body.into());
586591
this.set_goto(current, begin, expr_id.into());
587592
} else {
588593
scope.pop_assume_dropped(this);
@@ -720,7 +725,8 @@ impl<'ctx> MirLowerCtx<'ctx> {
720725
.ok_or(MirLowerError::ContinueWithoutLoop)?,
721726
};
722727
let begin = loop_data.begin;
723-
current = self.drop_until_scope(loop_data.drop_scope_index, current);
728+
current =
729+
self.drop_until_scope(loop_data.drop_scope_index, current, expr_id.into());
724730
self.set_goto(current, begin, expr_id.into());
725731
Ok(None)
726732
}
@@ -759,7 +765,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
759765
self.current_loop_blocks.as_ref().unwrap().drop_scope_index,
760766
),
761767
};
762-
current = self.drop_until_scope(drop_scope, current);
768+
current = self.drop_until_scope(drop_scope, current, expr_id.into());
763769
self.set_goto(current, end, expr_id.into());
764770
Ok(None)
765771
}
@@ -773,7 +779,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
773779
return Ok(None);
774780
}
775781
}
776-
current = self.drop_until_scope(0, current);
782+
current = self.drop_until_scope(0, current, expr_id.into());
777783
self.set_terminator(current, TerminatorKind::Return, expr_id.into());
778784
Ok(None)
779785
}
@@ -1782,7 +1788,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
17821788
return Ok(None);
17831789
};
17841790
self.push_fake_read(c, p, expr.into());
1785-
current = scope2.pop_and_drop(self, c);
1791+
current = scope2.pop_and_drop(self, c, expr.into());
17861792
}
17871793
}
17881794
}
@@ -1793,7 +1799,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
17931799
};
17941800
current = c;
17951801
}
1796-
current = scope.pop_and_drop(self, current);
1802+
current = scope.pop_and_drop(self, current, span);
17971803
Ok(Some(current))
17981804
}
17991805

@@ -1873,9 +1879,14 @@ impl<'ctx> MirLowerCtx<'ctx> {
18731879
}
18741880
}
18751881

1876-
fn drop_until_scope(&mut self, scope_index: usize, mut current: BasicBlockId) -> BasicBlockId {
1882+
fn drop_until_scope(
1883+
&mut self,
1884+
scope_index: usize,
1885+
mut current: BasicBlockId,
1886+
span: MirSpan,
1887+
) -> BasicBlockId {
18771888
for scope in self.drop_scopes[scope_index..].to_vec().iter().rev() {
1878-
self.emit_drop_and_storage_dead_for_scope(scope, &mut current);
1889+
self.emit_drop_and_storage_dead_for_scope(scope, &mut current, span);
18791890
}
18801891
current
18811892
}
@@ -1891,17 +1902,22 @@ impl<'ctx> MirLowerCtx<'ctx> {
18911902
}
18921903

18931904
/// Don't call directly
1894-
fn pop_drop_scope_internal(&mut self, mut current: BasicBlockId) -> BasicBlockId {
1905+
fn pop_drop_scope_internal(
1906+
&mut self,
1907+
mut current: BasicBlockId,
1908+
span: MirSpan,
1909+
) -> BasicBlockId {
18951910
let scope = self.drop_scopes.pop().unwrap();
1896-
self.emit_drop_and_storage_dead_for_scope(&scope, &mut current);
1911+
self.emit_drop_and_storage_dead_for_scope(&scope, &mut current, span);
18971912
current
18981913
}
18991914

19001915
fn pop_drop_scope_assert_finished(
19011916
&mut self,
19021917
mut current: BasicBlockId,
1918+
span: MirSpan,
19031919
) -> Result<BasicBlockId> {
1904-
current = self.pop_drop_scope_internal(current);
1920+
current = self.pop_drop_scope_internal(current, span);
19051921
if !self.drop_scopes.is_empty() {
19061922
implementation_error!("Mismatched count between drop scope push and pops");
19071923
}
@@ -1912,20 +1928,18 @@ impl<'ctx> MirLowerCtx<'ctx> {
19121928
&mut self,
19131929
scope: &DropScope,
19141930
current: &mut Idx<BasicBlock>,
1931+
span: MirSpan,
19151932
) {
19161933
for &l in scope.locals.iter().rev() {
19171934
if !self.result.locals[l].ty.clone().is_copy(self.db, self.owner) {
19181935
let prev = std::mem::replace(current, self.new_basic_block());
19191936
self.set_terminator(
19201937
prev,
19211938
TerminatorKind::Drop { place: l.into(), target: *current, unwind: None },
1922-
MirSpan::Unknown,
1939+
span,
19231940
);
19241941
}
1925-
self.push_statement(
1926-
*current,
1927-
StatementKind::StorageDead(l).with_span(MirSpan::Unknown),
1928-
);
1942+
self.push_statement(*current, StatementKind::StorageDead(l).with_span(span));
19291943
}
19301944
}
19311945
}
@@ -2002,7 +2016,7 @@ pub fn mir_body_for_closure_query(
20022016
|_| true,
20032017
)?;
20042018
if let Some(current) = ctx.lower_expr_to_place(*root, return_slot().into(), current)? {
2005-
let current = ctx.pop_drop_scope_assert_finished(current)?;
2019+
let current = ctx.pop_drop_scope_assert_finished(current, root.into())?;
20062020
ctx.set_terminator(current, TerminatorKind::Return, (*root).into());
20072021
}
20082022
let mut upvar_map: FxHashMap<LocalId, Vec<(&CapturedItem, usize)>> = FxHashMap::default();
@@ -2146,7 +2160,7 @@ pub fn lower_to_mir(
21462160
ctx.lower_params_and_bindings([].into_iter(), binding_picker)?
21472161
};
21482162
if let Some(current) = ctx.lower_expr_to_place(root_expr, return_slot().into(), current)? {
2149-
let current = ctx.pop_drop_scope_assert_finished(current)?;
2163+
let current = ctx.pop_drop_scope_assert_finished(current, root_expr.into())?;
21502164
ctx.set_terminator(current, TerminatorKind::Return, root_expr.into());
21512165
}
21522166
Ok(ctx.result)

crates/hir-ty/src/mir/pretty.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ impl<'a> MirPrettyCtx<'a> {
145145
let indent = mem::take(&mut self.indent);
146146
let mut ctx = MirPrettyCtx {
147147
body: &body,
148-
local_to_binding: body.binding_locals.iter().map(|(it, y)| (*y, it)).collect(),
148+
local_to_binding: body.local_to_binding_map(),
149149
result,
150150
indent,
151151
..*self
@@ -167,7 +167,7 @@ impl<'a> MirPrettyCtx<'a> {
167167
}
168168

169169
fn new(body: &'a MirBody, hir_body: &'a Body, db: &'a dyn HirDatabase) -> Self {
170-
let local_to_binding = body.binding_locals.iter().map(|(it, y)| (*y, it)).collect();
170+
let local_to_binding = body.local_to_binding_map();
171171
MirPrettyCtx {
172172
body,
173173
db,

crates/hir/src/lib.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ use hir_ty::{
6767
known_const_to_ast,
6868
layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding},
6969
method_resolution::{self, TyFingerprint},
70-
mir::{self, interpret_mir},
70+
mir::interpret_mir,
7171
primitive::UintTy,
7272
traits::FnTrait,
7373
AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, GenericArg,
@@ -129,9 +129,10 @@ pub use {
129129
hir_ty::{
130130
display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite},
131131
layout::LayoutError,
132-
mir::MirEvalError,
133132
PointerCast, Safety,
134133
},
134+
// FIXME: Properly encapsulate mir
135+
hir_ty::{mir, Interner as ChalkTyInterner},
135136
};
136137

137138
// These are negative re-exports: pub using these names is forbidden, they

crates/ide/src/inlay_hints.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ mod discriminant;
3131
mod fn_lifetime_fn;
3232
mod implicit_static;
3333
mod param_name;
34+
mod implicit_drop;
3435

3536
#[derive(Clone, Debug, PartialEq, Eq)]
3637
pub struct InlayHintsConfig {
@@ -45,6 +46,7 @@ pub struct InlayHintsConfig {
4546
pub closure_return_type_hints: ClosureReturnTypeHints,
4647
pub closure_capture_hints: bool,
4748
pub binding_mode_hints: bool,
49+
pub implicit_drop_hints: bool,
4850
pub lifetime_elision_hints: LifetimeElisionHints,
4951
pub param_names_for_lifetime_elision_hints: bool,
5052
pub hide_named_constructor_hints: bool,
@@ -124,6 +126,7 @@ pub enum InlayKind {
124126
Lifetime,
125127
Parameter,
126128
Type,
129+
Drop,
127130
}
128131

129132
#[derive(Debug)]
@@ -503,7 +506,10 @@ fn hints(
503506
ast::Item(it) => match it {
504507
// FIXME: record impl lifetimes so they aren't being reused in assoc item lifetime inlay hints
505508
ast::Item::Impl(_) => None,
506-
ast::Item::Fn(it) => fn_lifetime_fn::hints(hints, config, it),
509+
ast::Item::Fn(it) => {
510+
implicit_drop::hints(hints, sema, config, &it);
511+
fn_lifetime_fn::hints(hints, config, it)
512+
},
507513
// static type elisions
508514
ast::Item::Static(it) => implicit_static::hints(hints, config, Either::Left(it)),
509515
ast::Item::Const(it) => implicit_static::hints(hints, config, Either::Right(it)),
@@ -591,6 +597,7 @@ mod tests {
591597
max_length: None,
592598
closing_brace_hints_min_lines: None,
593599
fields_to_resolve: InlayFieldsToResolve::empty(),
600+
implicit_drop_hints: false,
594601
};
595602
pub(super) const TEST_CONFIG: InlayHintsConfig = InlayHintsConfig {
596603
type_hints: true,

0 commit comments

Comments
 (0)