Skip to content

Commit 80c5c8f

Browse files
try to peak into adts for significant droppers
1 parent 8f09388 commit 80c5c8f

File tree

3 files changed

+37
-15
lines changed

3 files changed

+37
-15
lines changed

compiler/rustc_middle/src/query/mod.rs

+11
Original file line numberDiff line numberDiff line change
@@ -1430,6 +1430,17 @@ rustc_queries! {
14301430
cache_on_disk_if { false }
14311431
}
14321432

1433+
/// A list of types where a type requires drop if and only if any of those types
1434+
/// has significant drop. A type marked with the attribute `rustc_insignificant_dtor`
1435+
/// is considered to not be significant. A drop is significant if it is implemented
1436+
/// by the user or does anything that will have any observable behavior (other than
1437+
/// freeing up memory). If the type is known to have a significant destructor then
1438+
/// `Err(AlwaysRequiresDrop)` is returned.
1439+
query list_significant_drop_tys(ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> Result<&'tcx ty::List<Ty<'tcx>>, AlwaysRequiresDrop> {
1440+
desc { |tcx| "computing when `{}` has a significant destructor", ty.value }
1441+
cache_on_disk_if { false }
1442+
}
1443+
14331444
/// Computes the layout of a type. Note that this implicitly
14341445
/// executes in "reveal all" mode, and will normalize the input type.
14351446
query layout_of(

compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs

+8-14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use itertools::Itertools;
22
use rustc_data_structures::unord::UnordSet;
3-
use rustc_hir::def_id::{DefId, LocalDefId};
3+
use rustc_hir::def_id::LocalDefId;
44
use rustc_index::bit_set::BitSet;
55
use rustc_macros::LintDiagnostic;
66
use rustc_middle::mir::{
@@ -13,7 +13,7 @@ use rustc_mir_dataflow::move_paths::{MoveData, MovePathIndex};
1313
use rustc_mir_dataflow::{Analysis, MaybeReachable};
1414
use rustc_session::lint;
1515
use rustc_span::Span;
16-
use tracing::debug;
16+
use tracing::{debug, instrument};
1717

1818
fn place_has_common_prefix<'tcx>(left: &Place<'tcx>, right: &Place<'tcx>) -> bool {
1919
left.local == right.local
@@ -68,9 +68,10 @@ fn print_ty_without_trimming(ty: Ty<'_>) -> String {
6868
ty::print::with_no_trimmed_paths!(format!("{}", ty))
6969
}
7070

71+
#[instrument(level = "debug", skip(tcx, param_env))]
7172
fn extract_component_with_significant_dtor<'tcx>(
7273
tcx: TyCtxt<'tcx>,
73-
_body_did: DefId,
74+
param_env: ty::ParamEnv<'tcx>,
7475
ty: Ty<'tcx>,
7576
) -> (String, Vec<Span>) {
7677
let ty_def_span = |ty: Ty<'_>| match ty.kind() {
@@ -104,10 +105,7 @@ fn extract_component_with_significant_dtor<'tcx>(
104105
// I honestly don't know how to extract the span reliably from a param arbitrarily nested
105106
ty::Param(_) => None,
106107
};
107-
let Some(adt_def) = ty.ty_adt_def() else {
108-
return (print_ty_without_trimming(ty), vec![]);
109-
};
110-
let Ok(tys) = tcx.adt_significant_drop_tys(adt_def.did()) else {
108+
let Ok(tys) = tcx.list_significant_drop_tys(param_env.and(ty)) else {
111109
return (print_ty_without_trimming(ty), vec![]);
112110
};
113111
let ty_names = tys.iter().map(print_ty_without_trimming).join(", ");
@@ -164,7 +162,7 @@ pub(crate) fn run_lint<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &Body<
164162
}
165163

166164
dump_mir(tcx, false, "lint_tail_expr_drop_order", &0 as _, body, |_, _| Ok(()));
167-
let param_env = tcx.param_env(def_id);
165+
let param_env = tcx.param_env(def_id).with_reveal_all_normalized(tcx);
168166
let is_closure_like = tcx.is_closure_like(def_id.to_def_id());
169167
let move_data = MoveData::gather_moves(body, tcx, param_env, |_| true);
170168
let maybe_init = MaybeInitializedPlaces::new(tcx, body, &move_data);
@@ -216,15 +214,11 @@ pub(crate) fn run_lint<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &Body<
216214
let observer_local_decl = &body.local_decls[move_path.place.local];
217215
let (ty_drop_components, ty_spans) = extract_component_with_significant_dtor(
218216
tcx,
219-
def_id.to_def_id(),
217+
param_env,
220218
linted_local_decl.ty,
221219
);
222220
let (observer_ty_drop_components, observer_ty_spans) =
223-
extract_component_with_significant_dtor(
224-
tcx,
225-
def_id.to_def_id(),
226-
observer_ty,
227-
);
221+
extract_component_with_significant_dtor(tcx, param_env, observer_ty);
228222
debug!(?candidate, ?place, ?move_path.place);
229223
tcx.emit_node_span_lint(
230224
lint::builtin::TAIL_EXPR_DROP_ORDER,

compiler/rustc_ty_utils/src/needs_drop.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_middle::ty::util::{AlwaysRequiresDrop, needs_drop_components};
88
use rustc_middle::ty::{self, EarlyBinder, GenericArgsRef, Ty, TyCtxt};
99
use rustc_session::Limit;
1010
use rustc_span::sym;
11-
use tracing::debug;
11+
use tracing::{debug, instrument};
1212

1313
use crate::errors::NeedsDropOverflow;
1414

@@ -400,13 +400,30 @@ fn adt_significant_drop_tys(
400400
.map(|components| tcx.mk_type_list(&components))
401401
}
402402

403+
#[instrument(level = "debug", skip(tcx))]
404+
fn list_significant_drop_tys<'tcx>(
405+
tcx: TyCtxt<'tcx>,
406+
ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
407+
) -> Result<&'tcx ty::List<Ty<'tcx>>, AlwaysRequiresDrop> {
408+
drop_tys_helper(
409+
tcx,
410+
ty.value, // identical to `tcx.make_adt(def, identity_args)`
411+
ty.param_env,
412+
adt_consider_insignificant_dtor(tcx),
413+
true,
414+
)
415+
.collect::<Result<Vec<_>, _>>()
416+
.map(|components| tcx.mk_type_list(&components))
417+
}
418+
403419
pub(crate) fn provide(providers: &mut Providers) {
404420
*providers = Providers {
405421
needs_drop_raw,
406422
needs_async_drop_raw,
407423
has_significant_drop_raw,
408424
adt_drop_tys,
409425
adt_significant_drop_tys,
426+
list_significant_drop_tys,
410427
..*providers
411428
};
412429
}

0 commit comments

Comments
 (0)