about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2025-01-06 03:25:45 +0000
committerMichael Goulet <michael@errs.io>2025-01-08 16:02:44 +0000
commitc55eefe8bc51f302cfc89d375198ca7211d4709b (patch)
tree40024a316d1007e00dd46abd862919d604cc563d
parent4a099b29cdb6a7841019406f0f2b5035a1fd9a08 (diff)
downloadrust-c55eefe8bc51f302cfc89d375198ca7211d4709b.tar.gz
rust-c55eefe8bc51f302cfc89d375198ca7211d4709b.zip
Try to explain borrow for tail expr temporary drop order change in 2024
-rw-r--r--compiler/rustc_borrowck/messages.ftl5
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs18
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs11
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs4
-rw-r--r--compiler/rustc_borrowck/src/lib.rs19
-rw-r--r--tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir1
-rw-r--r--tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir1
-rw-r--r--tests/ui/drop/lint-tail-expr-drop-order-borrowck.rs26
-rw-r--r--tests/ui/drop/lint-tail-expr-drop-order-borrowck.stderr38
9 files changed, 81 insertions, 42 deletions
diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl
index c1d5af59b1b..ada20e5c614 100644
--- a/compiler/rustc_borrowck/messages.ftl
+++ b/compiler/rustc_borrowck/messages.ftl
@@ -213,8 +213,9 @@ borrowck_suggest_create_fresh_reborrow =
 borrowck_suggest_iterate_over_slice =
     consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop
 
-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
-    .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 {"{"} .. {"}"}`
+borrowck_tail_expr_drop_order = relative drop order changing in Rust 2024
+    .label = this temporary value will be dropped at the end of the block
+    .note = consider using a `let` binding to ensure the value will live long enough
 
 borrowck_ty_no_impl_copy =
     {$is_partial_move ->
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 48f28f3f1de..a52dc447d76 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -5,7 +5,7 @@
 
 use std::assert_matches::assert_matches;
 
-use rustc_errors::{Applicability, Diag};
+use rustc_errors::{Applicability, Diag, EmissionGuarantee};
 use rustc_hir as hir;
 use rustc_hir::intravisit::Visitor;
 use rustc_infer::infer::NllRegionVariableOrigin;
@@ -61,10 +61,10 @@ impl<'tcx> BorrowExplanation<'tcx> {
     pub(crate) fn is_explained(&self) -> bool {
         !matches!(self, BorrowExplanation::Unexplained)
     }
-    pub(crate) fn add_explanation_to_diagnostic(
+    pub(crate) fn add_explanation_to_diagnostic<G: EmissionGuarantee>(
         &self,
         cx: &MirBorrowckCtxt<'_, '_, 'tcx>,
-        err: &mut Diag<'_>,
+        err: &mut Diag<'_, G>,
         borrow_desc: &str,
         borrow_span: Option<Span>,
         multiple_borrow_span: Option<(Span, Span)>,
@@ -346,10 +346,10 @@ impl<'tcx> BorrowExplanation<'tcx> {
         }
     }
 
-    fn add_object_lifetime_default_note(
+    fn add_object_lifetime_default_note<G: EmissionGuarantee>(
         &self,
         tcx: TyCtxt<'tcx>,
-        err: &mut Diag<'_>,
+        err: &mut Diag<'_, G>,
         unsize_ty: Ty<'tcx>,
     ) {
         if let ty::Adt(def, args) = unsize_ty.kind() {
@@ -403,9 +403,9 @@ impl<'tcx> BorrowExplanation<'tcx> {
         }
     }
 
-    fn add_lifetime_bound_suggestion_to_diagnostic(
+    fn add_lifetime_bound_suggestion_to_diagnostic<G: EmissionGuarantee>(
         &self,
-        err: &mut Diag<'_>,
+        err: &mut Diag<'_, G>,
         category: &ConstraintCategory<'tcx>,
         span: Span,
         region_name: &RegionName,
@@ -432,14 +432,14 @@ impl<'tcx> BorrowExplanation<'tcx> {
     }
 }
 
-fn suggest_rewrite_if_let(
+fn suggest_rewrite_if_let<G: EmissionGuarantee>(
     tcx: TyCtxt<'_>,
     expr: &hir::Expr<'_>,
     pat: &str,
     init: &hir::Expr<'_>,
     conseq: &hir::Expr<'_>,
     alt: Option<&hir::Expr<'_>>,
-    err: &mut Diag<'_>,
+    err: &mut Diag<'_, G>,
 ) {
     let source_map = tcx.sess.source_map();
     err.span_note(
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 0286ea6cd9d..d9d9ea75994 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -4,7 +4,7 @@ use std::collections::BTreeMap;
 
 use rustc_abi::{FieldIdx, VariantIdx};
 use rustc_data_structures::fx::FxIndexMap;
-use rustc_errors::{Applicability, Diag, MultiSpan};
+use rustc_errors::{Applicability, Diag, EmissionGuarantee, MultiSpan};
 use rustc_hir::def::{CtorKind, Namespace};
 use rustc_hir::{self as hir, CoroutineKind, LangItem};
 use rustc_index::IndexSlice;
@@ -626,9 +626,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
 
     /// Add a note to region errors and borrow explanations when higher-ranked regions in predicates
     /// implicitly introduce an "outlives `'static`" constraint.
-    fn add_placeholder_from_predicate_note(
+    fn add_placeholder_from_predicate_note<G: EmissionGuarantee>(
         &self,
-        err: &mut Diag<'_>,
+        err: &mut Diag<'_, G>,
         path: &[OutlivesConstraint<'tcx>],
     ) {
         let predicate_span = path.iter().find_map(|constraint| {
@@ -651,9 +651,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
 
     /// Add a label to region errors and borrow explanations when outlives constraints arise from
     /// proving a type implements `Sized` or `Copy`.
-    fn add_sized_or_copy_bound_info(
+    fn add_sized_or_copy_bound_info<G: EmissionGuarantee>(
         &self,
-        err: &mut Diag<'_>,
+        err: &mut Diag<'_, G>,
         blamed_category: ConstraintCategory<'tcx>,
         path: &[OutlivesConstraint<'tcx>],
     ) {
@@ -1042,6 +1042,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 kind,
             };
         }
+
         normal_ret
     }
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index bdb880b2bce..9349b46ec5b 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -5,7 +5,7 @@ use std::fmt::{self, Display};
 use std::iter;
 
 use rustc_data_structures::fx::IndexEntry;
-use rustc_errors::Diag;
+use rustc_errors::{Diag, EmissionGuarantee};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_middle::ty::print::RegionHighlightMode;
@@ -108,7 +108,7 @@ impl RegionName {
         }
     }
 
-    pub(crate) fn highlight_region_name(&self, diag: &mut Diag<'_>) {
+    pub(crate) fn highlight_region_name<G: EmissionGuarantee>(&self, diag: &mut Diag<'_, G>) {
         match &self.source {
             RegionNameSource::NamedLateParamRegion(span)
             | RegionNameSource::NamedEarlyParamRegion(span) => {
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 8b3870e5cc6..f90f7514102 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -24,6 +24,7 @@ use std::ops::{ControlFlow, Deref};
 use rustc_abi::FieldIdx;
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_data_structures::graph::dominators::Dominators;
+use rustc_errors::LintDiagnostic;
 use rustc_hir as hir;
 use rustc_hir::CRATE_HIR_ID;
 use rustc_hir::def_id::LocalDefId;
@@ -1192,17 +1193,25 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
             |borrow_index| borrows_in_scope.contains(borrow_index),
             |this, _borrow_index, borrow| {
                 if matches!(borrow.kind, BorrowKind::Fake(_)) {
-                    return Control::Continue;
+                    return ControlFlow::Continue(());
                 }
                 let borrowed = this.retrieve_borrow_spans(borrow).var_or_use_path_span();
-                this.infcx.tcx.emit_node_span_lint(
+                let explain = this.explain_why_borrow_contains_point(
+                    location,
+                    borrow,
+                    Some((WriteKind::StorageDeadOrDrop, place)),
+                );
+                this.infcx.tcx.node_span_lint(
                     TAIL_EXPR_DROP_ORDER,
                     CRATE_HIR_ID,
-                    place_span,
-                    session_diagnostics::TailExprDropOrder { borrowed },
+                    borrowed,
+                    |diag| {
+                        session_diagnostics::TailExprDropOrder { borrowed }.decorate_lint(diag);
+                        explain.add_explanation_to_diagnostic(&this, diag, "", None, None);
+                    },
                 );
                 // We may stop at the first case
-                Control::Break
+                ControlFlow::Break(())
             },
         );
     }
diff --git a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir
index e9bbe30bd77..ee6e16d20fd 100644
--- a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir
+++ b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir
@@ -74,6 +74,7 @@ fn method_1(_1: Guard) -> () {
 
     bb7: {
         backward incompatible drop(_2);
+        backward incompatible drop(_4);
         backward incompatible drop(_5);
         goto -> bb21;
     }
diff --git a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir
index e9bbe30bd77..ee6e16d20fd 100644
--- a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir
+++ b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir
@@ -74,6 +74,7 @@ fn method_1(_1: Guard) -> () {
 
     bb7: {
         backward incompatible drop(_2);
+        backward incompatible drop(_4);
         backward incompatible drop(_5);
         goto -> bb21;
     }
diff --git a/tests/ui/drop/lint-tail-expr-drop-order-borrowck.rs b/tests/ui/drop/lint-tail-expr-drop-order-borrowck.rs
index 1bd5655d7fe..6f64d83f8a0 100644
--- a/tests/ui/drop/lint-tail-expr-drop-order-borrowck.rs
+++ b/tests/ui/drop/lint-tail-expr-drop-order-borrowck.rs
@@ -7,18 +7,20 @@
 
 fn should_lint_with_potential_borrowck_err() {
     let _ = { String::new().as_str() }.len();
-    //~^ ERROR: a temporary value will be dropped here
+    //~^ ERROR: relative drop order changing
     //~| WARN: this changes meaning in Rust 2024
-    //~| NOTE: consider using a `let` binding
+    //~| NOTE: this temporary value will be dropped at the end of the block
+    //~| borrow later used by call
     //~| NOTE: for more information, see
 }
 
 fn should_lint_with_unsafe_block() {
     fn f(_: usize) {}
     f(unsafe { String::new().as_str() }.len());
-    //~^ ERROR: a temporary value will be dropped here
+    //~^ ERROR: relative drop order changing
     //~| WARN: this changes meaning in Rust 2024
-    //~| NOTE: consider using a `let` binding
+    //~| NOTE: this temporary value will be dropped at the end of the block
+    //~| borrow later used by call
     //~| NOTE: for more information, see
 }
 
@@ -27,11 +29,23 @@ fn should_lint_with_big_block() {
     fn f<T>(_: T) {}
     f({
         &mut || 0
-        //~^ ERROR: a temporary value will be dropped here
+        //~^ ERROR: relative drop order changing
         //~| WARN: this changes meaning in Rust 2024
-        //~| NOTE: consider using a `let` binding
+        //~| NOTE: this temporary value will be dropped at the end of the block
+        //~| borrow later used here
         //~| NOTE: for more information, see
     })
 }
 
+fn another_temp_that_is_copy_in_arg() {
+    fn f() {}
+    fn g(_: &()) {}
+    g({ &f() });
+    //~^ ERROR: relative drop order changing
+    //~| WARN: this changes meaning in Rust 2024
+    //~| NOTE: this temporary value will be dropped at the end of the block
+    //~| borrow later used by call
+    //~| NOTE: for more information, see
+}
+
 fn main() {}
diff --git a/tests/ui/drop/lint-tail-expr-drop-order-borrowck.stderr b/tests/ui/drop/lint-tail-expr-drop-order-borrowck.stderr
index 98ef0547c90..a55e366dd0b 100644
--- a/tests/ui/drop/lint-tail-expr-drop-order-borrowck.stderr
+++ b/tests/ui/drop/lint-tail-expr-drop-order-borrowck.stderr
@@ -1,10 +1,10 @@
-error: a temporary value will be dropped here before the execution exits the block in Edition 2024, which will raise borrow checking error
-  --> $DIR/lint-tail-expr-drop-order-borrowck.rs:9:36
+error: relative drop order changing in Rust 2024
+  --> $DIR/lint-tail-expr-drop-order-borrowck.rs:9:15
    |
 LL |     let _ = { String::new().as_str() }.len();
-   |               -------------        ^
+   |               ^^^^^^^^^^^^^            --- borrow later used by call
    |               |
-   |               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 { .. }`
+   |               this temporary value will be dropped at the end of the block
    |
    = warning: this changes meaning in Rust 2024
    = 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
 LL | #![deny(tail_expr_drop_order)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: a temporary value will be dropped here before the execution exits the block in Edition 2024, which will raise borrow checking error
-  --> $DIR/lint-tail-expr-drop-order-borrowck.rs:18:37
+error: relative drop order changing in Rust 2024
+  --> $DIR/lint-tail-expr-drop-order-borrowck.rs:19:16
    |
 LL |     f(unsafe { String::new().as_str() }.len());
-   |                -------------        ^
+   |                ^^^^^^^^^^^^^            --- borrow later used by call
    |                |
-   |                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 { .. }`
+   |                this temporary value will be dropped at the end of the block
    |
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
 
-error: a temporary value will be dropped here before the execution exits the block in Edition 2024, which will raise borrow checking error
-  --> $DIR/lint-tail-expr-drop-order-borrowck.rs:29:17
+error: relative drop order changing in Rust 2024
+  --> $DIR/lint-tail-expr-drop-order-borrowck.rs:31:9
    |
 LL |         &mut || 0
-   |         --------^
+   |         ^^^^^^^^^
    |         |
-   |         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 { .. }`
+   |         this temporary value will be dropped at the end of the block
+   |         borrow later used here
    |
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
 
-error: aborting due to 3 previous errors
+error: relative drop order changing in Rust 2024
+  --> $DIR/lint-tail-expr-drop-order-borrowck.rs:43:9
+   |
+LL |     g({ &f() });
+   |     -   ^^^^ this temporary value will be dropped at the end of the block
+   |     |
+   |     borrow later used by call
+   |
+   = warning: this changes meaning in Rust 2024
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
+
+error: aborting due to 4 previous errors