Skip to content

Commit f3f1847

Browse files
authored
Rollup merge of #145041 - lcnr:borrowck-limitations-error, r=BoxyUwU
rework GAT borrowck limitation error The old one depends on the `ConstraintCategory` of the constraint which meant we did not emit this note if we had to prove the higher ranked trait bound due to e.g. normalization. This made it annoying brittle and caused MIR borrowck errors to be order dependent, fixes the issue in #140737 (comment). r? types cc ```@amandasystems```
2 parents 181480d + 3ebf611 commit f3f1847

22 files changed

+133
-58
lines changed

compiler/rustc_borrowck/messages.ftl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ borrowck_lifetime_constraints_error =
9090
lifetime may not live long enough
9191
9292
borrowck_limitations_implies_static =
93-
due to current limitations in the borrow checker, this implies a `'static` lifetime
93+
due to a current limitation of the type system, this implies a `'static` lifetime
9494
9595
borrowck_move_closure_suggestion =
9696
consider adding 'move' keyword before the nested closure

compiler/rustc_borrowck/src/diagnostics/mod.rs

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ use rustc_abi::{FieldIdx, VariantIdx};
66
use rustc_data_structures::fx::FxIndexMap;
77
use rustc_errors::{Applicability, Diag, EmissionGuarantee, MultiSpan, listify};
88
use rustc_hir::def::{CtorKind, Namespace};
9-
use rustc_hir::{self as hir, CoroutineKind, LangItem};
9+
use rustc_hir::{
10+
self as hir, CoroutineKind, GenericBound, LangItem, WhereBoundPredicate, WherePredicateKind,
11+
};
1012
use rustc_index::{IndexSlice, IndexVec};
1113
use rustc_infer::infer::{BoundRegionConversionTime, NllRegionVariableOrigin};
1214
use rustc_infer::traits::SelectionError;
@@ -658,25 +660,66 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
658660

659661
/// Add a note to region errors and borrow explanations when higher-ranked regions in predicates
660662
/// implicitly introduce an "outlives `'static`" constraint.
663+
///
664+
/// This is very similar to `fn suggest_static_lifetime_for_gat_from_hrtb` which handles this
665+
/// note for failed type tests instead of outlives errors.
661666
fn add_placeholder_from_predicate_note<G: EmissionGuarantee>(
662667
&self,
663-
err: &mut Diag<'_, G>,
668+
diag: &mut Diag<'_, G>,
664669
path: &[OutlivesConstraint<'tcx>],
665670
) {
666-
let predicate_span = path.iter().find_map(|constraint| {
671+
let tcx = self.infcx.tcx;
672+
let Some((gat_hir_id, generics)) = path.iter().find_map(|constraint| {
667673
let outlived = constraint.sub;
668674
if let Some(origin) = self.regioncx.definitions.get(outlived)
669-
&& let NllRegionVariableOrigin::Placeholder(_) = origin.origin
670-
&& let ConstraintCategory::Predicate(span) = constraint.category
675+
&& let NllRegionVariableOrigin::Placeholder(placeholder) = origin.origin
676+
&& let Some(id) = placeholder.bound.kind.get_id()
677+
&& let Some(placeholder_id) = id.as_local()
678+
&& let gat_hir_id = tcx.local_def_id_to_hir_id(placeholder_id)
679+
&& let Some(generics_impl) =
680+
tcx.parent_hir_node(tcx.parent_hir_id(gat_hir_id)).generics()
671681
{
672-
Some(span)
682+
Some((gat_hir_id, generics_impl))
673683
} else {
674684
None
675685
}
676-
});
686+
}) else {
687+
return;
688+
};
677689

678-
if let Some(span) = predicate_span {
679-
err.span_note(span, "due to current limitations in the borrow checker, this implies a `'static` lifetime");
690+
// Look for the where-bound which introduces the placeholder.
691+
// As we're using the HIR, we need to handle both `for<'a> T: Trait<'a>`
692+
// and `T: for<'a> Trait`<'a>.
693+
for pred in generics.predicates {
694+
let WherePredicateKind::BoundPredicate(WhereBoundPredicate {
695+
bound_generic_params,
696+
bounds,
697+
..
698+
}) = pred.kind
699+
else {
700+
continue;
701+
};
702+
if bound_generic_params
703+
.iter()
704+
.rfind(|bgp| tcx.local_def_id_to_hir_id(bgp.def_id) == gat_hir_id)
705+
.is_some()
706+
{
707+
diag.span_note(pred.span, fluent::borrowck_limitations_implies_static);
708+
return;
709+
}
710+
for bound in bounds.iter() {
711+
if let GenericBound::Trait(bound) = bound {
712+
if bound
713+
.bound_generic_params
714+
.iter()
715+
.rfind(|bgp| tcx.local_def_id_to_hir_id(bgp.def_id) == gat_hir_id)
716+
.is_some()
717+
{
718+
diag.span_note(bound.span, fluent::borrowck_limitations_implies_static);
719+
return;
720+
}
721+
}
722+
}
680723
}
681724
}
682725

compiler/rustc_borrowck/src/diagnostics/region_errors.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
215215
diag: &mut Diag<'_>,
216216
lower_bound: RegionVid,
217217
) {
218-
let mut suggestions = vec![];
219218
let tcx = self.infcx.tcx;
220219

221220
// find generic associated types in the given region 'lower_bound'
@@ -237,9 +236,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
237236
.collect::<Vec<_>>();
238237
debug!(?gat_id_and_generics);
239238

240-
// find higher-ranked trait bounds bounded to the generic associated types
239+
// Look for the where-bound which introduces the placeholder.
240+
// As we're using the HIR, we need to handle both `for<'a> T: Trait<'a>`
241+
// and `T: for<'a> Trait`<'a>.
241242
let mut hrtb_bounds = vec![];
242-
gat_id_and_generics.iter().flatten().for_each(|(gat_hir_id, generics)| {
243+
gat_id_and_generics.iter().flatten().for_each(|&(gat_hir_id, generics)| {
243244
for pred in generics.predicates {
244245
let BoundPredicate(WhereBoundPredicate { bound_generic_params, bounds, .. }) =
245246
pred.kind
@@ -248,17 +249,32 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
248249
};
249250
if bound_generic_params
250251
.iter()
251-
.rfind(|bgp| tcx.local_def_id_to_hir_id(bgp.def_id) == *gat_hir_id)
252+
.rfind(|bgp| tcx.local_def_id_to_hir_id(bgp.def_id) == gat_hir_id)
252253
.is_some()
253254
{
254255
for bound in *bounds {
255256
hrtb_bounds.push(bound);
256257
}
258+
} else {
259+
for bound in *bounds {
260+
if let Trait(trait_bound) = bound {
261+
if trait_bound
262+
.bound_generic_params
263+
.iter()
264+
.rfind(|bgp| tcx.local_def_id_to_hir_id(bgp.def_id) == gat_hir_id)
265+
.is_some()
266+
{
267+
hrtb_bounds.push(bound);
268+
return;
269+
}
270+
}
271+
}
257272
}
258273
}
259274
});
260275
debug!(?hrtb_bounds);
261276

277+
let mut suggestions = vec![];
262278
hrtb_bounds.iter().for_each(|bound| {
263279
let Trait(PolyTraitRef { trait_ref, span: trait_span, .. }) = bound else {
264280
return;

tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,6 @@ LL | force_send(async_load(&not_static));
2222
...
2323
LL | }
2424
| - `not_static` dropped here while still borrowed
25-
|
26-
note: due to current limitations in the borrow checker, this implies a `'static` lifetime
27-
--> $DIR/implementation-not-general-enough-ice-133252.rs:16:18
28-
|
29-
LL | fn force_send<T: Send>(_: T) {}
30-
| ^^^^
3125

3226
error: aborting due to 2 previous errors
3327

tests/ui/generic-associated-types/bugs/hrtb-implied-1.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ LL | print_items::<WindowsMut<'_>>(windows);
99
LL | }
1010
| - temporary value is freed at the end of this statement
1111
|
12-
note: due to current limitations in the borrow checker, this implies a `'static` lifetime
13-
--> $DIR/hrtb-implied-1.rs:26:26
12+
note: due to a current limitation of the type system, this implies a `'static` lifetime
13+
--> $DIR/hrtb-implied-1.rs:26:5
1414
|
1515
LL | for<'a> I::Item<'a>: Debug,
16-
| ^^^^^
16+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
1717

1818
error: aborting due to 1 previous error
1919

tests/ui/generic-associated-types/bugs/hrtb-implied-2.stderr

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ LL | let _next = iter2.next();
1515
= note: requirement occurs because of a mutable reference to `Eat<&mut I, F>`
1616
= note: mutable references are invariant over their type parameter
1717
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
18-
= note: due to current limitations in the borrow checker, this implies a `'static` lifetime
18+
note: due to a current limitation of the type system, this implies a `'static` lifetime
19+
--> $DIR/hrtb-implied-2.rs:31:8
20+
|
21+
LL | F: FnMut(I::Item<'_>),
22+
| ^^^^^^^^^^^^^^^^^^
1923

2024
error: aborting due to 1 previous error
2125

tests/ui/generic-associated-types/bugs/hrtb-implied-3.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ LL | trivial_bound(iter);
1111
| `iter` escapes the function body here
1212
| argument requires that `'1` must outlive `'static`
1313
|
14-
note: due to current limitations in the borrow checker, this implies a `'static` lifetime
15-
--> $DIR/hrtb-implied-3.rs:14:26
14+
note: due to a current limitation of the type system, this implies a `'static` lifetime
15+
--> $DIR/hrtb-implied-3.rs:14:5
1616
|
1717
LL | for<'a> I::Item<'a>: Sized,
18-
| ^^^^^
18+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
1919

2020
error: aborting due to 1 previous error
2121

tests/ui/generic-associated-types/collectivity-regression.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | | let _x = x;
77
LL | | };
88
| |_____^
99
|
10-
note: due to current limitations in the borrow checker, this implies a `'static` lifetime
10+
note: due to a current limitation of the type system, this implies a `'static` lifetime
1111
--> $DIR/collectivity-regression.rs:11:16
1212
|
1313
LL | for<'a> T: Get<Value<'a> = ()>,

tests/ui/generic-associated-types/extended/lending_iterator.stderr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ error: `Self` does not live long enough
1212
|
1313
LL | <B as FromLendingIterator<A>>::from_iter(self)
1414
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15+
|
16+
note: due to a current limitation of the type system, this implies a `'static` lifetime
17+
--> $DIR/lending_iterator.rs:4:21
18+
|
19+
LL | fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self;
20+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1521

1622
error: aborting due to 2 previous errors
1723

tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ LL | fn give_some<'a>() {
1515
LL | want_hrtb::<&'a u32>()
1616
| ^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
1717
|
18-
note: due to current limitations in the borrow checker, this implies a `'static` lifetime
18+
note: due to a current limitation of the type system, this implies a `'static` lifetime
1919
--> $DIR/hrtb-just-for-static.rs:9:15
2020
|
2121
LL | where T : for<'a> Foo<&'a isize>

0 commit comments

Comments
 (0)