about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2025-09-28 21:13:53 +0000
committerEsteban Küber <esteban@kuber.com.ar>2025-09-28 21:13:53 +0000
commitc5313fed76a99942edb4c7f94607fa3d2d6da21c (patch)
tree85da949e5e0de1d094bb20c8b2911d0da1691385
parent58f5260b960004090bfa9e7ef5068d6554ac9f33 (diff)
downloadrust-c5313fed76a99942edb4c7f94607fa3d2d6da21c.tar.gz
rust-c5313fed76a99942edb4c7f94607fa3d2d6da21c.zip
Point at multiple outlives requirements instead of just the first one
```
error[E0716]: temporary value dropped while borrowed
  --> $DIR/multiple-sources-for-outlives-requirement.rs:5:38
   |
LL | fn foo<'b>() {
   |        -- lifetime `'b` defined here
LL |     outlives_indir::<'_, 'b, _>(&mut 1u32);
   |     ---------------------------------^^^^-- temporary value is freed at the end of this statement
   |     |                                |
   |     |                                creates a temporary value which is freed while still in use
   |     argument requires that borrow lasts for `'b`
   |
note: requirements that the value outlives `'b` introduced here
  --> $DIR/multiple-sources-for-outlives-requirement.rs:1:23
   |
LL | fn outlives_indir<'a: 'b, 'b, T: 'a>(_x: T) {}
   |                       ^^         ^^
```
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs13
-rw-r--r--tests/ui/regions/multiple-sources-for-outlives-requirement.rs11
-rw-r--r--tests/ui/regions/multiple-sources-for-outlives-requirement.stderr20
3 files changed, 39 insertions, 5 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 67e33b37416..638d89f5bcb 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -417,18 +417,21 @@ impl<'tcx> BorrowExplanation<'tcx> {
                     self.add_object_lifetime_default_note(tcx, err, unsize_ty);
                 }
 
-                if let Some(pred) = path
+                let mut preds = path
                     .iter()
                     .filter_map(|constraint| match constraint.category {
                         ConstraintCategory::Predicate(pred) if !pred.is_dummy() => Some(pred),
                         _ => None,
                     })
-                    .next()
-                {
+                    .collect::<Vec<Span>>();
+                preds.sort();
+                preds.dedup();
+                if !preds.is_empty() {
+                    let s = if preds.len() == 1 { "" } else { "s" };
                     err.span_note(
-                        pred,
+                        preds,
                         format!(
-                            "requirement that the value outlives `{region_name}` introduced here"
+                            "requirement{s} that the value outlives `{region_name}` introduced here"
                         ),
                     );
                 }
diff --git a/tests/ui/regions/multiple-sources-for-outlives-requirement.rs b/tests/ui/regions/multiple-sources-for-outlives-requirement.rs
new file mode 100644
index 00000000000..720cd1cf6ee
--- /dev/null
+++ b/tests/ui/regions/multiple-sources-for-outlives-requirement.rs
@@ -0,0 +1,11 @@
+fn outlives_indir<'a: 'b, 'b, T: 'a>(_x: T) {}
+//~^ NOTE: requirements that the value outlives `'b` introduced here
+
+fn foo<'b>() { //~ NOTE: lifetime `'b` defined here
+    outlives_indir::<'_, 'b, _>(&mut 1u32); //~ ERROR: temporary value dropped while borrowed
+    //~^ NOTE: argument requires that borrow lasts for `'b`
+    //~| NOTE: creates a temporary value which is freed while still in use
+    //~| NOTE: temporary value is freed at the end of this statement
+}
+
+fn main() {}
diff --git a/tests/ui/regions/multiple-sources-for-outlives-requirement.stderr b/tests/ui/regions/multiple-sources-for-outlives-requirement.stderr
new file mode 100644
index 00000000000..4cdaf950e15
--- /dev/null
+++ b/tests/ui/regions/multiple-sources-for-outlives-requirement.stderr
@@ -0,0 +1,20 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/multiple-sources-for-outlives-requirement.rs:5:38
+   |
+LL | fn foo<'b>() {
+   |        -- lifetime `'b` defined here
+LL |     outlives_indir::<'_, 'b, _>(&mut 1u32);
+   |     ---------------------------------^^^^-- temporary value is freed at the end of this statement
+   |     |                                |
+   |     |                                creates a temporary value which is freed while still in use
+   |     argument requires that borrow lasts for `'b`
+   |
+note: requirements that the value outlives `'b` introduced here
+  --> $DIR/multiple-sources-for-outlives-requirement.rs:1:23
+   |
+LL | fn outlives_indir<'a: 'b, 'b, T: 'a>(_x: T) {}
+   |                       ^^         ^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0716`.