Skip to content

Commit fe9b975

Browse files
committed
Auto merge of rust-lang#135351 - cuviper:beta-next, r=cuviper
[beta] stage0 bump and backports - bump stage0 to 1.84.0 - Run borrowck tests on BIDs and emit tail-expr-drop-order lints for violations rust-lang#134523 r? cuviper
2 parents e30eeff + ce4e43f commit fe9b975

18 files changed

+662
-500
lines changed

compiler/rustc_borrowck/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,10 @@ borrowck_suggest_create_fresh_reborrow =
213213
borrowck_suggest_iterate_over_slice =
214214
consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop
215215
216+
borrowck_tail_expr_drop_order = relative drop order changing in Rust 2024
217+
.label = this temporary value will be dropped at the end of the block
218+
.note = consider using a `let` binding to ensure the value will live long enough
219+
216220
borrowck_ty_no_impl_copy =
217221
{$is_partial_move ->
218222
[true] partial move

compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
use std::assert_matches::assert_matches;
77

8-
use rustc_errors::{Applicability, Diag};
8+
use rustc_errors::{Applicability, Diag, EmissionGuarantee};
99
use rustc_hir as hir;
1010
use rustc_hir::intravisit::Visitor;
1111
use rustc_index::IndexSlice;
@@ -60,12 +60,12 @@ impl<'tcx> BorrowExplanation<'tcx> {
6060
pub(crate) fn is_explained(&self) -> bool {
6161
!matches!(self, BorrowExplanation::Unexplained)
6262
}
63-
pub(crate) fn add_explanation_to_diagnostic(
63+
pub(crate) fn add_explanation_to_diagnostic<G: EmissionGuarantee>(
6464
&self,
6565
tcx: TyCtxt<'tcx>,
6666
body: &Body<'tcx>,
6767
local_names: &IndexSlice<Local, Option<Symbol>>,
68-
err: &mut Diag<'_>,
68+
err: &mut Diag<'_, G>,
6969
borrow_desc: &str,
7070
borrow_span: Option<Span>,
7171
multiple_borrow_span: Option<(Span, Span)>,
@@ -348,10 +348,10 @@ impl<'tcx> BorrowExplanation<'tcx> {
348348
}
349349
}
350350

351-
fn add_object_lifetime_default_note(
351+
fn add_object_lifetime_default_note<G: EmissionGuarantee>(
352352
&self,
353353
tcx: TyCtxt<'tcx>,
354-
err: &mut Diag<'_>,
354+
err: &mut Diag<'_, G>,
355355
unsize_ty: Ty<'tcx>,
356356
) {
357357
if let ty::Adt(def, args) = unsize_ty.kind() {
@@ -405,9 +405,9 @@ impl<'tcx> BorrowExplanation<'tcx> {
405405
}
406406
}
407407

408-
fn add_lifetime_bound_suggestion_to_diagnostic(
408+
fn add_lifetime_bound_suggestion_to_diagnostic<G: EmissionGuarantee>(
409409
&self,
410-
err: &mut Diag<'_>,
410+
err: &mut Diag<'_, G>,
411411
category: &ConstraintCategory<'tcx>,
412412
span: Span,
413413
region_name: &RegionName,
@@ -434,14 +434,14 @@ impl<'tcx> BorrowExplanation<'tcx> {
434434
}
435435
}
436436

437-
fn suggest_rewrite_if_let(
437+
fn suggest_rewrite_if_let<G: EmissionGuarantee>(
438438
tcx: TyCtxt<'_>,
439439
expr: &hir::Expr<'_>,
440440
pat: &str,
441441
init: &hir::Expr<'_>,
442442
conseq: &hir::Expr<'_>,
443443
alt: Option<&hir::Expr<'_>>,
444-
err: &mut Diag<'_>,
444+
err: &mut Diag<'_, G>,
445445
) {
446446
let source_map = tcx.sess.source_map();
447447
err.span_note(

compiler/rustc_borrowck/src/diagnostics/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1001,6 +1001,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
10011001
kind,
10021002
};
10031003
}
1004+
10041005
normal_ret
10051006
}
10061007

compiler/rustc_borrowck/src/diagnostics/region_name.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::fmt::{self, Display};
55
use std::iter;
66

77
use rustc_data_structures::fx::IndexEntry;
8-
use rustc_errors::Diag;
8+
use rustc_errors::{Diag, EmissionGuarantee};
99
use rustc_hir as hir;
1010
use rustc_hir::def::{DefKind, Res};
1111
use rustc_middle::ty::print::RegionHighlightMode;
@@ -108,7 +108,7 @@ impl RegionName {
108108
}
109109
}
110110

111-
pub(crate) fn highlight_region_name(&self, diag: &mut Diag<'_>) {
111+
pub(crate) fn highlight_region_name<G: EmissionGuarantee>(&self, diag: &mut Diag<'_, G>) {
112112
match &self.source {
113113
RegionNameSource::NamedLateParamRegion(span)
114114
| RegionNameSource::NamedEarlyParamRegion(span) => {

compiler/rustc_borrowck/src/lib.rs

+90-15
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,17 @@
1515
#![warn(unreachable_pub)]
1616
// tidy-alphabetical-end
1717

18+
use std::borrow::Cow;
1819
use std::cell::RefCell;
1920
use std::marker::PhantomData;
2021
use std::ops::Deref;
2122

2223
use rustc_abi::FieldIdx;
2324
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
2425
use rustc_data_structures::graph::dominators::Dominators;
26+
use rustc_errors::LintDiagnostic;
2527
use rustc_hir as hir;
28+
use rustc_hir::CRATE_HIR_ID;
2629
use rustc_hir::def_id::LocalDefId;
2730
use rustc_index::bit_set::{BitSet, MixedBitSet};
2831
use rustc_index::{IndexSlice, IndexVec};
@@ -42,7 +45,7 @@ use rustc_mir_dataflow::move_paths::{
4245
InitIndex, InitLocation, LookupResult, MoveData, MovePathIndex,
4346
};
4447
use rustc_mir_dataflow::{Analysis, EntryStates, Results, ResultsVisitor, visit_results};
45-
use rustc_session::lint::builtin::UNUSED_MUT;
48+
use rustc_session::lint::builtin::{TAIL_EXPR_DROP_ORDER, UNUSED_MUT};
4649
use rustc_span::{Span, Symbol};
4750
use smallvec::SmallVec;
4851
use tracing::{debug, instrument};
@@ -636,9 +639,11 @@ impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<
636639
| StatementKind::Coverage(..)
637640
// These do not actually affect borrowck
638641
| StatementKind::ConstEvalCounter
639-
// This do not affect borrowck
640-
| StatementKind::BackwardIncompatibleDropHint { .. }
641642
| StatementKind::StorageLive(..) => {}
643+
// This does not affect borrowck
644+
StatementKind::BackwardIncompatibleDropHint { place, reason: BackwardIncompatibleDropReason::Edition2024 } => {
645+
self.check_backward_incompatible_drop(location, (**place, span), state);
646+
}
642647
StatementKind::StorageDead(local) => {
643648
self.access_place(
644649
location,
@@ -1007,6 +1012,24 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
10071012
}
10081013
}
10091014

1015+
fn borrows_in_scope<'s>(
1016+
&self,
1017+
location: Location,
1018+
state: &'s BorrowckDomain,
1019+
) -> Cow<'s, BitSet<BorrowIndex>> {
1020+
if let Some(polonius) = &self.polonius_output {
1021+
// Use polonius output if it has been enabled.
1022+
let location = self.location_table.start_index(location);
1023+
let mut polonius_output = BitSet::new_empty(self.borrow_set.len());
1024+
for &idx in polonius.errors_at(location) {
1025+
polonius_output.insert(idx);
1026+
}
1027+
Cow::Owned(polonius_output)
1028+
} else {
1029+
Cow::Borrowed(&state.borrows)
1030+
}
1031+
}
1032+
10101033
#[instrument(level = "debug", skip(self, state))]
10111034
fn check_access_for_conflict(
10121035
&mut self,
@@ -1018,18 +1041,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
10181041
) -> bool {
10191042
let mut error_reported = false;
10201043

1021-
// Use polonius output if it has been enabled.
1022-
let mut polonius_output;
1023-
let borrows_in_scope = if let Some(polonius) = &self.polonius_output {
1024-
let location = self.location_table.start_index(location);
1025-
polonius_output = BitSet::new_empty(self.borrow_set.len());
1026-
for &idx in polonius.errors_at(location) {
1027-
polonius_output.insert(idx);
1028-
}
1029-
&polonius_output
1030-
} else {
1031-
&state.borrows
1032-
};
1044+
let borrows_in_scope = self.borrows_in_scope(location, state);
10331045

10341046
each_borrow_involving_path(
10351047
self,
@@ -1149,6 +1161,69 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
11491161
error_reported
11501162
}
11511163

1164+
/// Through #123739, backward incompatible drops (BIDs) are introduced.
1165+
/// We would like to emit lints whether borrow checking fails at these future drop locations.
1166+
#[instrument(level = "debug", skip(self, state))]
1167+
fn check_backward_incompatible_drop(
1168+
&mut self,
1169+
location: Location,
1170+
(place, place_span): (Place<'tcx>, Span),
1171+
state: &BorrowckDomain,
1172+
) {
1173+
let tcx = self.infcx.tcx;
1174+
// If this type does not need `Drop`, then treat it like a `StorageDead`.
1175+
// This is needed because we track the borrows of refs to thread locals,
1176+
// and we'll ICE because we don't track borrows behind shared references.
1177+
let sd = if place.ty(self.body, tcx).ty.needs_drop(tcx, self.body.typing_env(tcx)) {
1178+
AccessDepth::Drop
1179+
} else {
1180+
AccessDepth::Shallow(None)
1181+
};
1182+
1183+
let borrows_in_scope = self.borrows_in_scope(location, state);
1184+
1185+
// This is a very simplified version of `Self::check_access_for_conflict`.
1186+
// We are here checking on BIDs and specifically still-live borrows of data involving the BIDs.
1187+
each_borrow_involving_path(
1188+
self,
1189+
self.infcx.tcx,
1190+
self.body,
1191+
(sd, place),
1192+
self.borrow_set,
1193+
|borrow_index| borrows_in_scope.contains(borrow_index),
1194+
|this, _borrow_index, borrow| {
1195+
if matches!(borrow.kind, BorrowKind::Fake(_)) {
1196+
return Control::Continue;
1197+
}
1198+
let borrowed = this.retrieve_borrow_spans(borrow).var_or_use_path_span();
1199+
let explain = this.explain_why_borrow_contains_point(
1200+
location,
1201+
borrow,
1202+
Some((WriteKind::StorageDeadOrDrop, place)),
1203+
);
1204+
this.infcx.tcx.node_span_lint(
1205+
TAIL_EXPR_DROP_ORDER,
1206+
CRATE_HIR_ID,
1207+
borrowed,
1208+
|diag| {
1209+
session_diagnostics::TailExprDropOrder { borrowed }.decorate_lint(diag);
1210+
explain.add_explanation_to_diagnostic(
1211+
this.infcx.tcx,
1212+
this.body,
1213+
&this.local_names,
1214+
diag,
1215+
"",
1216+
None,
1217+
None,
1218+
);
1219+
},
1220+
);
1221+
// We may stop at the first case
1222+
Control::Break
1223+
},
1224+
);
1225+
}
1226+
11521227
fn mutate_place(
11531228
&mut self,
11541229
location: Location,

compiler/rustc_borrowck/src/session_diagnostics.rs

+7
Original file line numberDiff line numberDiff line change
@@ -480,3 +480,10 @@ pub(crate) struct SimdIntrinsicArgConst {
480480
pub arg: usize,
481481
pub intrinsic: String,
482482
}
483+
484+
#[derive(LintDiagnostic)]
485+
#[diag(borrowck_tail_expr_drop_order)]
486+
pub(crate) struct TailExprDropOrder {
487+
#[label]
488+
pub borrowed: Span,
489+
}

compiler/rustc_mir_build/src/builder/scope.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1131,15 +1131,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
11311131

11321132
/// Schedule emission of a backwards incompatible drop lint hint.
11331133
/// Applicable only to temporary values for now.
1134+
#[instrument(level = "debug", skip(self))]
11341135
pub(crate) fn schedule_backwards_incompatible_drop(
11351136
&mut self,
11361137
span: Span,
11371138
region_scope: region::Scope,
11381139
local: Local,
11391140
) {
1140-
if !self.local_decls[local].ty.has_significant_drop(self.tcx, self.typing_env()) {
1141-
return;
1142-
}
1141+
// Note that we are *not* gating BIDs here on whether they have significant destructor.
1142+
// We need to know all of them so that we can capture potential borrow-checking errors.
11431143
for scope in self.scopes.scopes.iter_mut().rev() {
11441144
// Since we are inserting linting MIR statement, we have to invalidate the caches
11451145
scope.invalidate_cache();

compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -351,14 +351,19 @@ pub(crate) fn run_lint<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &Body<
351351
{
352352
return;
353353
}
354+
355+
// FIXME(typing_env): This should be able to reveal the opaques local to the
356+
// body using the typeck results.
357+
let typing_env = ty::TypingEnv::non_body_analysis(tcx, def_id);
358+
354359
// ## About BIDs in blocks ##
355360
// Track the set of blocks that contain a backwards-incompatible drop (BID)
356361
// and, for each block, the vector of locations.
357362
//
358363
// We group them per-block because they tend to scheduled in the same drop ladder block.
359364
let mut bid_per_block = IndexMap::default();
360365
let mut bid_places = UnordSet::new();
361-
let typing_env = ty::TypingEnv::post_analysis(tcx, def_id);
366+
362367
let mut ty_dropped_components = UnordMap::default();
363368
for (block, data) in body.basic_blocks.iter_enumerated() {
364369
for (statement_index, stmt) in data.statements.iter().enumerate() {

0 commit comments

Comments
 (0)