Skip to content

Commit c55eefe

Browse files
Try to explain borrow for tail expr temporary drop order change in 2024
1 parent 4a099b2 commit c55eefe

9 files changed

+81
-42
lines changed

Diff for: compiler/rustc_borrowck/messages.ftl

+3-2
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,9 @@ 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 = a temporary value will be dropped here before the execution exits the block in Edition 2024, which will raise borrow checking error
217-
.label = consider using a `let` binding to create a longer lived value; or replacing the `{"{"} .. {"}"}` block with curly brackets `( .. )`; or folding the rest of the expression into the surrounding `unsafe {"{"} .. {"}"}`
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
218219
219220
borrowck_ty_no_impl_copy =
220221
{$is_partial_move ->

Diff for: 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_infer::infer::NllRegionVariableOrigin;
@@ -61,10 +61,10 @@ impl<'tcx> BorrowExplanation<'tcx> {
6161
pub(crate) fn is_explained(&self) -> bool {
6262
!matches!(self, BorrowExplanation::Unexplained)
6363
}
64-
pub(crate) fn add_explanation_to_diagnostic(
64+
pub(crate) fn add_explanation_to_diagnostic<G: EmissionGuarantee>(
6565
&self,
6666
cx: &MirBorrowckCtxt<'_, '_, 'tcx>,
67-
err: &mut Diag<'_>,
67+
err: &mut Diag<'_, G>,
6868
borrow_desc: &str,
6969
borrow_span: Option<Span>,
7070
multiple_borrow_span: Option<(Span, Span)>,
@@ -346,10 +346,10 @@ impl<'tcx> BorrowExplanation<'tcx> {
346346
}
347347
}
348348

349-
fn add_object_lifetime_default_note(
349+
fn add_object_lifetime_default_note<G: EmissionGuarantee>(
350350
&self,
351351
tcx: TyCtxt<'tcx>,
352-
err: &mut Diag<'_>,
352+
err: &mut Diag<'_, G>,
353353
unsize_ty: Ty<'tcx>,
354354
) {
355355
if let ty::Adt(def, args) = unsize_ty.kind() {
@@ -403,9 +403,9 @@ impl<'tcx> BorrowExplanation<'tcx> {
403403
}
404404
}
405405

406-
fn add_lifetime_bound_suggestion_to_diagnostic(
406+
fn add_lifetime_bound_suggestion_to_diagnostic<G: EmissionGuarantee>(
407407
&self,
408-
err: &mut Diag<'_>,
408+
err: &mut Diag<'_, G>,
409409
category: &ConstraintCategory<'tcx>,
410410
span: Span,
411411
region_name: &RegionName,
@@ -432,14 +432,14 @@ impl<'tcx> BorrowExplanation<'tcx> {
432432
}
433433
}
434434

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

Diff for: compiler/rustc_borrowck/src/diagnostics/mod.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::collections::BTreeMap;
44

55
use rustc_abi::{FieldIdx, VariantIdx};
66
use rustc_data_structures::fx::FxIndexMap;
7-
use rustc_errors::{Applicability, Diag, MultiSpan};
7+
use rustc_errors::{Applicability, Diag, EmissionGuarantee, MultiSpan};
88
use rustc_hir::def::{CtorKind, Namespace};
99
use rustc_hir::{self as hir, CoroutineKind, LangItem};
1010
use rustc_index::IndexSlice;
@@ -626,9 +626,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
626626

627627
/// Add a note to region errors and borrow explanations when higher-ranked regions in predicates
628628
/// implicitly introduce an "outlives `'static`" constraint.
629-
fn add_placeholder_from_predicate_note(
629+
fn add_placeholder_from_predicate_note<G: EmissionGuarantee>(
630630
&self,
631-
err: &mut Diag<'_>,
631+
err: &mut Diag<'_, G>,
632632
path: &[OutlivesConstraint<'tcx>],
633633
) {
634634
let predicate_span = path.iter().find_map(|constraint| {
@@ -651,9 +651,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
651651

652652
/// Add a label to region errors and borrow explanations when outlives constraints arise from
653653
/// proving a type implements `Sized` or `Copy`.
654-
fn add_sized_or_copy_bound_info(
654+
fn add_sized_or_copy_bound_info<G: EmissionGuarantee>(
655655
&self,
656-
err: &mut Diag<'_>,
656+
err: &mut Diag<'_, G>,
657657
blamed_category: ConstraintCategory<'tcx>,
658658
path: &[OutlivesConstraint<'tcx>],
659659
) {
@@ -1042,6 +1042,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
10421042
kind,
10431043
};
10441044
}
1045+
10451046
normal_ret
10461047
}
10471048

Diff for: 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) => {

Diff for: compiler/rustc_borrowck/src/lib.rs

+14-5
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use std::ops::{ControlFlow, Deref};
2424
use rustc_abi::FieldIdx;
2525
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
2626
use rustc_data_structures::graph::dominators::Dominators;
27+
use rustc_errors::LintDiagnostic;
2728
use rustc_hir as hir;
2829
use rustc_hir::CRATE_HIR_ID;
2930
use rustc_hir::def_id::LocalDefId;
@@ -1192,17 +1193,25 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
11921193
|borrow_index| borrows_in_scope.contains(borrow_index),
11931194
|this, _borrow_index, borrow| {
11941195
if matches!(borrow.kind, BorrowKind::Fake(_)) {
1195-
return Control::Continue;
1196+
return ControlFlow::Continue(());
11961197
}
11971198
let borrowed = this.retrieve_borrow_spans(borrow).var_or_use_path_span();
1198-
this.infcx.tcx.emit_node_span_lint(
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(
11991205
TAIL_EXPR_DROP_ORDER,
12001206
CRATE_HIR_ID,
1201-
place_span,
1202-
session_diagnostics::TailExprDropOrder { borrowed },
1207+
borrowed,
1208+
|diag| {
1209+
session_diagnostics::TailExprDropOrder { borrowed }.decorate_lint(diag);
1210+
explain.add_explanation_to_diagnostic(&this, diag, "", None, None);
1211+
},
12031212
);
12041213
// We may stop at the first case
1205-
Control::Break
1214+
ControlFlow::Break(())
12061215
},
12071216
);
12081217
}

Diff for: tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir

+1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ fn method_1(_1: Guard) -> () {
7474

7575
bb7: {
7676
backward incompatible drop(_2);
77+
backward incompatible drop(_4);
7778
backward incompatible drop(_5);
7879
goto -> bb21;
7980
}

Diff for: tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir

+1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ fn method_1(_1: Guard) -> () {
7474

7575
bb7: {
7676
backward incompatible drop(_2);
77+
backward incompatible drop(_4);
7778
backward incompatible drop(_5);
7879
goto -> bb21;
7980
}

Diff for: tests/ui/drop/lint-tail-expr-drop-order-borrowck.rs

+20-6
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,20 @@
77

88
fn should_lint_with_potential_borrowck_err() {
99
let _ = { String::new().as_str() }.len();
10-
//~^ ERROR: a temporary value will be dropped here
10+
//~^ ERROR: relative drop order changing
1111
//~| WARN: this changes meaning in Rust 2024
12-
//~| NOTE: consider using a `let` binding
12+
//~| NOTE: this temporary value will be dropped at the end of the block
13+
//~| borrow later used by call
1314
//~| NOTE: for more information, see
1415
}
1516

1617
fn should_lint_with_unsafe_block() {
1718
fn f(_: usize) {}
1819
f(unsafe { String::new().as_str() }.len());
19-
//~^ ERROR: a temporary value will be dropped here
20+
//~^ ERROR: relative drop order changing
2021
//~| WARN: this changes meaning in Rust 2024
21-
//~| NOTE: consider using a `let` binding
22+
//~| NOTE: this temporary value will be dropped at the end of the block
23+
//~| borrow later used by call
2224
//~| NOTE: for more information, see
2325
}
2426

@@ -27,11 +29,23 @@ fn should_lint_with_big_block() {
2729
fn f<T>(_: T) {}
2830
f({
2931
&mut || 0
30-
//~^ ERROR: a temporary value will be dropped here
32+
//~^ ERROR: relative drop order changing
3133
//~| WARN: this changes meaning in Rust 2024
32-
//~| NOTE: consider using a `let` binding
34+
//~| NOTE: this temporary value will be dropped at the end of the block
35+
//~| borrow later used here
3336
//~| NOTE: for more information, see
3437
})
3538
}
3639

40+
fn another_temp_that_is_copy_in_arg() {
41+
fn f() {}
42+
fn g(_: &()) {}
43+
g({ &f() });
44+
//~^ ERROR: relative drop order changing
45+
//~| WARN: this changes meaning in Rust 2024
46+
//~| NOTE: this temporary value will be dropped at the end of the block
47+
//~| borrow later used by call
48+
//~| NOTE: for more information, see
49+
}
50+
3751
fn main() {}
+25-13
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error: a temporary value will be dropped here before the execution exits the block in Edition 2024, which will raise borrow checking error
2-
--> $DIR/lint-tail-expr-drop-order-borrowck.rs:9:36
1+
error: relative drop order changing in Rust 2024
2+
--> $DIR/lint-tail-expr-drop-order-borrowck.rs:9:15
33
|
44
LL | let _ = { String::new().as_str() }.len();
5-
| ------------- ^
5+
| ^^^^^^^^^^^^^ --- borrow later used by call
66
| |
7-
| consider using a `let` binding to create a longer lived value; or replacing the `{ .. }` block with curly brackets `( .. )`; or folding the rest of the expression into the surrounding `unsafe { .. }`
7+
| this temporary value will be dropped at the end of the block
88
|
99
= warning: this changes meaning in Rust 2024
1010
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
@@ -14,27 +14,39 @@ note: the lint level is defined here
1414
LL | #![deny(tail_expr_drop_order)]
1515
| ^^^^^^^^^^^^^^^^^^^^
1616

17-
error: a temporary value will be dropped here before the execution exits the block in Edition 2024, which will raise borrow checking error
18-
--> $DIR/lint-tail-expr-drop-order-borrowck.rs:18:37
17+
error: relative drop order changing in Rust 2024
18+
--> $DIR/lint-tail-expr-drop-order-borrowck.rs:19:16
1919
|
2020
LL | f(unsafe { String::new().as_str() }.len());
21-
| ------------- ^
21+
| ^^^^^^^^^^^^^ --- borrow later used by call
2222
| |
23-
| consider using a `let` binding to create a longer lived value; or replacing the `{ .. }` block with curly brackets `( .. )`; or folding the rest of the expression into the surrounding `unsafe { .. }`
23+
| this temporary value will be dropped at the end of the block
2424
|
2525
= warning: this changes meaning in Rust 2024
2626
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
2727

28-
error: a temporary value will be dropped here before the execution exits the block in Edition 2024, which will raise borrow checking error
29-
--> $DIR/lint-tail-expr-drop-order-borrowck.rs:29:17
28+
error: relative drop order changing in Rust 2024
29+
--> $DIR/lint-tail-expr-drop-order-borrowck.rs:31:9
3030
|
3131
LL | &mut || 0
32-
| --------^
32+
| ^^^^^^^^^
3333
| |
34-
| consider using a `let` binding to create a longer lived value; or replacing the `{ .. }` block with curly brackets `( .. )`; or folding the rest of the expression into the surrounding `unsafe { .. }`
34+
| this temporary value will be dropped at the end of the block
35+
| borrow later used here
3536
|
3637
= warning: this changes meaning in Rust 2024
3738
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
3839

39-
error: aborting due to 3 previous errors
40+
error: relative drop order changing in Rust 2024
41+
--> $DIR/lint-tail-expr-drop-order-borrowck.rs:43:9
42+
|
43+
LL | g({ &f() });
44+
| - ^^^^ this temporary value will be dropped at the end of the block
45+
| |
46+
| borrow later used by call
47+
|
48+
= warning: this changes meaning in Rust 2024
49+
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
50+
51+
error: aborting due to 4 previous errors
4052

0 commit comments

Comments
 (0)