Skip to content

Commit e7ca6e1

Browse files
committed
Use Predicate ConstraintCategory when normalizing
1 parent 1eb71f0 commit e7ca6e1

File tree

14 files changed

+172
-15
lines changed

14 files changed

+172
-15
lines changed

compiler/rustc_borrowck/src/constraints/mod.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,7 @@ pub(crate) struct OutlivesConstraintSet<'tcx> {
2121

2222
impl<'tcx> OutlivesConstraintSet<'tcx> {
2323
pub(crate) fn push(&mut self, constraint: OutlivesConstraint<'tcx>) {
24-
debug!(
25-
"OutlivesConstraintSet::push({:?}: {:?} @ {:?}",
26-
constraint.sup, constraint.sub, constraint.locations
27-
);
24+
debug!("OutlivesConstraintSet::push({:?})", constraint);
2825
if constraint.sup == constraint.sub {
2926
// 'a: 'a is pretty uninteresting
3027
return;

compiler/rustc_borrowck/src/diagnostics/region_errors.rs

+14-6
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use crate::session_diagnostics::{
3131
};
3232

3333
use super::{OutlivesSuggestionBuilder, RegionName};
34-
use crate::region_infer::BlameConstraint;
34+
use crate::region_infer::{BlameConstraint, ExtraConstraintInfo};
3535
use crate::{
3636
nll::ConstraintDescription,
3737
region_infer::{values::RegionElement, TypeTest},
@@ -354,12 +354,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
354354
) {
355355
debug!("report_region_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
356356

357-
let BlameConstraint { category, cause, variance_info, .. } = self
358-
.regioncx
359-
.best_blame_constraint(fr, fr_origin, |r| {
357+
let (blame_constraint, extra_info) =
358+
self.regioncx.best_blame_constraint(fr, fr_origin, |r| {
360359
self.regioncx.provides_universal_region(r, fr, outlived_fr)
361-
})
362-
.0;
360+
});
361+
let BlameConstraint { category, cause, variance_info, .. } = blame_constraint;
363362

364363
debug!("report_region_error: category={:?} {:?} {:?}", category, cause, variance_info);
365364

@@ -468,6 +467,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
468467
}
469468
}
470469

470+
for extra in extra_info {
471+
match extra {
472+
ExtraConstraintInfo::PlaceholderFromPredicate(span) => {
473+
diag.span_note(span, format!("due to current limitations in the borrow checker, this implies a `'static` lifetime"));
474+
}
475+
}
476+
}
477+
471478
self.buffer_error(diag);
472479
}
473480

@@ -559,6 +566,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
559566
/// LL | ref_obj(x)
560567
/// | ^^^^^^^^^^ `x` escapes the function body here
561568
/// ```
569+
#[instrument(level = "debug", skip(self))]
562570
fn report_escaping_data_error(
563571
&self,
564572
errci: &ErrorConstraintInfo<'tcx>,

compiler/rustc_borrowck/src/type_check/canonical.rs

+18-4
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
104104
);
105105
}
106106

107+
#[instrument(level = "debug", skip(self))]
107108
pub(super) fn normalize_and_prove_instantiated_predicates(
108109
&mut self,
109110
// Keep this parameter for now, in case we start using
@@ -118,8 +119,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
118119
.zip(instantiated_predicates.spans.into_iter())
119120
{
120121
debug!(?predicate);
121-
let predicate = self.normalize(predicate, locations);
122-
self.prove_predicate(predicate, locations, ConstraintCategory::Predicate(span));
122+
let category = ConstraintCategory::Predicate(span);
123+
let predicate = self.normalize_with_category(predicate, locations, category);
124+
self.prove_predicate(predicate, locations, category);
123125
}
124126
}
125127

@@ -155,15 +157,27 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
155157
})
156158
}
157159

158-
#[instrument(skip(self), level = "debug")]
159160
pub(super) fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T
161+
where
162+
T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
163+
{
164+
self.normalize_with_category(value, location, ConstraintCategory::Boring)
165+
}
166+
167+
#[instrument(skip(self), level = "debug")]
168+
pub(super) fn normalize_with_category<T>(
169+
&mut self,
170+
value: T,
171+
location: impl NormalizeLocation,
172+
category: ConstraintCategory<'tcx>,
173+
) -> T
160174
where
161175
T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
162176
{
163177
let param_env = self.param_env;
164178
self.fully_perform_op(
165179
location.to_locations(),
166-
ConstraintCategory::Boring,
180+
category,
167181
param_env.and(type_op::normalize::Normalize::new(value)),
168182
)
169183
.unwrap_or_else(|NoSolution| {

compiler/rustc_borrowck/src/type_check/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
312312
}
313313

314314
fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
315+
debug!(?constant, ?location, "visit_constant");
316+
315317
self.super_constant(constant, location);
316318
let ty = self.sanitize_type(constant, constant.literal.ty());
317319

@@ -1811,6 +1813,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
18111813
}
18121814

18131815
fn check_operand(&mut self, op: &Operand<'tcx>, location: Location) {
1816+
debug!(?op, ?location, "check_operand");
1817+
18141818
if let Operand::Constant(constant) = op {
18151819
let maybe_uneval = match constant.literal {
18161820
ConstantKind::Ty(ct) => match ct.kind() {

compiler/rustc_trait_selection/src/traits/query/normalize.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,11 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
4848
T: TypeFoldable<'tcx>,
4949
{
5050
debug!(
51-
"normalize::<{}>(value={:?}, param_env={:?})",
51+
"normalize::<{}>(value={:?}, param_env={:?}, cause={:?})",
5252
std::any::type_name::<T>(),
5353
value,
5454
self.param_env,
55+
self.cause,
5556
);
5657
if !needs_normalization(&value, self.param_env.reveal()) {
5758
return Ok(Normalized { value, obligations: vec![] });
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// check-fail
2+
// known-bug
3+
4+
// This gives us problems because `for<'a> I::Item<'a>: Debug` should mean "for
5+
// all 'a where I::Item<'a> is WF", but really means "for all 'a possible"
6+
7+
trait LendingIterator: Sized {
8+
type Item<'a>
9+
where
10+
Self: 'a;
11+
fn next(&mut self) -> Self::Item<'_>;
12+
}
13+
fn fails<I: LendingIterator, F>(iter: &mut I, f: F) -> bool
14+
where
15+
F: FnMut(I::Item<'_>),
16+
{
17+
let mut iter2 = Eat(iter, f);
18+
let _next = iter2.next();
19+
//~^ borrowed data escapes
20+
true
21+
}
22+
impl<I: LendingIterator> LendingIterator for &mut I {
23+
type Item<'a> = I::Item<'a> where Self:'a;
24+
fn next(&mut self) -> Self::Item<'_> {
25+
(**self).next()
26+
}
27+
}
28+
29+
struct Eat<I, F>(I, F);
30+
impl<I: LendingIterator, F> Iterator for Eat<I, F>
31+
where
32+
F: FnMut(I::Item<'_>),
33+
{
34+
type Item = ();
35+
fn next(&mut self) -> Option<Self::Item> {
36+
None
37+
}
38+
}
39+
40+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0521]: borrowed data escapes outside of function
2+
--> $DIR/hrtb-implied-2.rs:18:17
3+
|
4+
LL | fn fails<I: LendingIterator, F>(iter: &mut I, f: F) -> bool
5+
| ---- - let's call the lifetime of this reference `'1`
6+
| |
7+
| `iter` is a reference that is only valid in the function body
8+
...
9+
LL | let _next = iter2.next();
10+
| ^^^^^^^^^^^^
11+
| |
12+
| `iter` escapes the function body here
13+
| argument requires that `'1` must outlive `'static`
14+
|
15+
= note: requirement occurs because of a mutable reference to `Eat<&mut I, F>`
16+
= note: mutable references are invariant over their type parameter
17+
= 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
19+
20+
error: aborting due to previous error
21+
22+
For more information about this error, try `rustc --explain E0521`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
trait LendingIterator {
2+
type Item<'a>
3+
where
4+
Self: 'a;
5+
}
6+
7+
impl LendingIterator for &str {
8+
type Item<'a> = () where Self:'a;
9+
}
10+
11+
fn trivial_bound<I>(_: I)
12+
where
13+
I: LendingIterator,
14+
for<'a> I::Item<'a>: Sized,
15+
{
16+
}
17+
18+
fn fails(iter: &str) {
19+
trivial_bound(iter);
20+
//~^ borrowed data escapes
21+
}
22+
23+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0521]: borrowed data escapes outside of function
2+
--> $DIR/hrtb-implied-3.rs:19:5
3+
|
4+
LL | fn fails(iter: &str) {
5+
| ---- - let's call the lifetime of this reference `'1`
6+
| |
7+
| `iter` is a reference that is only valid in the function body
8+
LL | trivial_bound(iter);
9+
| ^^^^^^^^^^^^^^^^^^^
10+
| |
11+
| `iter` escapes the function body here
12+
| argument requires that `'1` must outlive `'static`
13+
|
14+
note: due to current limitations in the borrow checker, this implies a `'static` lifetime
15+
--> $DIR/hrtb-implied-3.rs:14:26
16+
|
17+
LL | for<'a> I::Item<'a>: Sized,
18+
| ^^^^^
19+
20+
error: aborting due to previous error
21+
22+
For more information about this error, try `rustc --explain E0521`.

src/test/ui/generic-associated-types/trait-objects.extended.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ LL | x.size_hint().0
1111
| |
1212
| `x` escapes the function body here
1313
| argument requires that `'1` must outlive `'static`
14+
|
15+
= note: due to current limitations in the borrow checker, this implies a `'static` lifetime
1416

1517
error: aborting due to previous error
1618

src/test/ui/higher-rank-trait-bounds/hrtb-just-for-static.stderr

+6
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ LL | fn give_some<'a>() {
1414
| -- lifetime `'a` defined here
1515
LL | want_hrtb::<&'a u32>()
1616
| ^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
17+
|
18+
note: due to current limitations in the borrow checker, this implies a `'static` lifetime
19+
--> $DIR/hrtb-just-for-static.rs:9:15
20+
|
21+
LL | where T : for<'a> Foo<&'a isize>
22+
| ^^^^^^^^^^^^^^^^^^^^^^
1723

1824
error: implementation of `Foo` is not general enough
1925
--> $DIR/hrtb-just-for-static.rs:30:5

src/test/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.stderr

+6
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ LL | fn foo_hrtb_bar_not<'b, T>(mut t: T)
4646
...
4747
LL | foo_hrtb_bar_not(&mut t);
4848
| ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static`
49+
|
50+
note: due to current limitations in the borrow checker, this implies a `'static` lifetime
51+
--> $DIR/hrtb-perfect-forwarding.rs:37:8
52+
|
53+
LL | T: for<'a> Foo<&'a isize> + Bar<&'b isize>,
54+
| ^^^^^^^^^^^^^^^^^^^^^^
4955

5056
error: implementation of `Bar` is not general enough
5157
--> $DIR/hrtb-perfect-forwarding.rs:43:5

src/test/ui/issues/issue-26217.stderr

+6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ LL | fn bar<'a>() {
55
| -- lifetime `'a` defined here
66
LL | foo::<&'a i32>();
77
| ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
8+
|
9+
note: due to current limitations in the borrow checker, this implies a `'static` lifetime
10+
--> $DIR/issue-26217.rs:1:30
11+
|
12+
LL | fn foo<T>() where for<'a> T: 'a {}
13+
| ^^
814

915
error: aborting due to previous error
1016

src/test/ui/nll/type-test-universe.stderr

+6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ LL | fn test2<'a>() {
1111
| -- lifetime `'a` defined here
1212
LL | outlives_forall::<Value<'a>>();
1313
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
14+
|
15+
note: due to current limitations in the borrow checker, this implies a `'static` lifetime
16+
--> $DIR/type-test-universe.rs:6:16
17+
|
18+
LL | for<'u> T: 'u,
19+
| ^^
1420

1521
error: aborting due to 2 previous errors
1622

0 commit comments

Comments
 (0)