Skip to content

Commit e09242d

Browse files
committed
Final bits
1 parent f1767db commit e09242d

File tree

12 files changed

+124
-34
lines changed

12 files changed

+124
-34
lines changed

compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -272,9 +272,12 @@ impl<'tcx> BorrowExplanation<'tcx> {
272272

273273
for extra in extra_info {
274274
match extra {
275-
_ => {}
275+
ExtraConstraintInfo::PlaceholderFromPredicate(span) => {
276+
err.span_note(*span, format!("due to current limitations in the borrow checker, this implies a `'static` lifetime"));
277+
}
276278
}
277279
}
280+
278281
self.add_lifetime_bound_suggestion_to_diagnostic(err, &category, span, region_name);
279282
}
280283
_ => {}

compiler/rustc_borrowck/src/region_infer/mod.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,9 @@ enum Trace<'tcx> {
246246
}
247247

248248
#[derive(Clone, PartialEq, Eq, Debug)]
249-
pub enum ExtraConstraintInfo {}
249+
pub enum ExtraConstraintInfo {
250+
PlaceholderFromPredicate(Span),
251+
}
250252

251253
impl<'tcx> RegionInferenceContext<'tcx> {
252254
/// Creates a new region inference context with a total of
@@ -2028,7 +2030,17 @@ impl<'tcx> RegionInferenceContext<'tcx> {
20282030
.collect::<Vec<_>>()
20292031
);
20302032

2031-
let extra_info = vec![];
2033+
let mut extra_info = vec![];
2034+
for constraint in path.iter() {
2035+
let outlived = constraint.sub;
2036+
let Some(origin) = self.var_infos.get(outlived) else { continue; };
2037+
let RegionVariableOrigin::Nll(NllRegionVariableOrigin::Placeholder(p)) = origin.origin else { continue; };
2038+
debug!(?constraint, ?p);
2039+
let ConstraintCategory::Predicate(span) = constraint.category else { continue; };
2040+
extra_info.push(ExtraConstraintInfo::PlaceholderFromPredicate(span));
2041+
// We only want to point to one
2042+
break;
2043+
}
20322044

20332045
// We try to avoid reporting a `ConstraintCategory::Predicate` as our best constraint.
20342046
// Instead, we use it to produce an improved `ObligationCauseCode`.

compiler/rustc_borrowck/src/type_check/canonical.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
2525
/// constraints should occur within this method so that those
2626
/// constraints can be properly localized!**
2727
#[instrument(skip(self, op), level = "trace")]
28-
pub(super) fn fully_perform_op<R, Op>(
28+
pub(super) fn fully_perform_op<R: fmt::Debug, Op>(
2929
&mut self,
3030
locations: Locations,
3131
category: ConstraintCategory<'tcx>,
@@ -39,6 +39,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
3939

4040
let TypeOpOutput { output, constraints, error_info } = op.fully_perform(self.infcx)?;
4141

42+
debug!(?output, ?constraints);
43+
4244
if let Some(data) = constraints {
4345
self.push_region_constraints(locations, category, data);
4446
}

compiler/rustc_borrowck/src/type_check/constraint_conversion.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
8686
}
8787
}
8888

89-
pub(super) fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx>) {
89+
fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx>) {
9090
debug!("generate: constraints at: {:#?}", self.locations);
9191

9292
// Extract out various useful fields we'll need below.

compiler/rustc_infer/src/infer/canonical/query_response.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,9 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
130130
let region_constraints = self.with_region_constraints(|region_constraints| {
131131
make_query_region_constraints(
132132
tcx,
133-
region_obligations.iter().map(|r_o| (r_o.sup_type, r_o.sub_region)),
133+
region_obligations
134+
.iter()
135+
.map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())),
134136
region_constraints,
135137
)
136138
});
@@ -630,7 +632,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
630632
/// creates query region constraints.
631633
pub fn make_query_region_constraints<'tcx>(
632634
tcx: TyCtxt<'tcx>,
633-
outlives_obligations: impl Iterator<Item = (Ty<'tcx>, ty::Region<'tcx>)>,
635+
outlives_obligations: impl Iterator<Item = (Ty<'tcx>, ty::Region<'tcx>, ConstraintCategory<'tcx>)>,
634636
region_constraints: &RegionConstraintData<'tcx>,
635637
) -> QueryRegionConstraints<'tcx> {
636638
let RegionConstraintData { constraints, verifys, givens, member_constraints } =
@@ -644,6 +646,7 @@ pub fn make_query_region_constraints<'tcx>(
644646
let outlives: Vec<_> = constraints
645647
.iter()
646648
.map(|(k, origin)| {
649+
// no bound vars in the code above
647650
let constraint = ty::Binder::dummy(match *k {
648651
// Swap regions because we are going from sub (<=) to outlives
649652
// (>=).
@@ -659,17 +662,13 @@ pub fn make_query_region_constraints<'tcx>(
659662
}
660663
Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1),
661664
});
662-
663665
(constraint, origin.to_constraint_category())
664666
})
665667
.chain(
666668
outlives_obligations
667669
// no bound vars in the code above
668-
.map(|(ty, r)| {
669-
(
670-
ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), r)),
671-
ConstraintCategory::BoringNoLocation,
672-
)
670+
.map(|(ty, r, constraint_category)| {
671+
(ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), r)), constraint_category)
673672
}),
674673
)
675674
.collect();

compiler/rustc_infer/src/infer/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ impl<'tcx> SubregionOrigin<'tcx> {
433433
pub fn to_constraint_category(&self) -> ConstraintCategory<'tcx> {
434434
match self {
435435
Self::Subtype(type_trace) => type_trace.cause.to_constraint_category(),
436+
Self::AscribeUserTypeProvePredicate(span) => ConstraintCategory::Predicate(*span),
436437
_ => ConstraintCategory::BoringNoLocation,
437438
}
438439
}

compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ impl<F, G> CustomTypeOp<F, G> {
2323
}
2424
}
2525

26-
impl<'tcx, F, R, G> super::TypeOp<'tcx> for CustomTypeOp<F, G>
26+
impl<'tcx, F, R: fmt::Debug, G> super::TypeOp<'tcx> for CustomTypeOp<F, G>
2727
where
2828
F: for<'a, 'cx> FnOnce(&'a InferCtxt<'cx, 'tcx>) -> Fallible<InferOk<'tcx, R>>,
2929
G: Fn() -> String,
@@ -89,8 +89,8 @@ pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
8989
infcx.tcx,
9090
region_obligations
9191
.iter()
92-
.map(|r_o| (r_o.sup_type, r_o.sub_region))
93-
.map(|(ty, r)| (infcx.resolve_vars_if_possible(ty), r)),
92+
.map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category()))
93+
.map(|(ty, r, cc)| (infcx.resolve_vars_if_possible(ty), r, cc)),
9494
&region_constraint_data,
9595
);
9696

compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub use rustc_middle::traits::query::type_op::*;
2626
/// extract out the resulting region constraints (or an error if it
2727
/// cannot be completed).
2828
pub trait TypeOp<'tcx>: Sized + fmt::Debug {
29-
type Output;
29+
type Output: fmt::Debug;
3030
type ErrorInfo;
3131

3232
/// Processes the operation and all resulting obligations,

compiler/rustc_traits/src/type_op.rs

+23-17
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use rustc_hir::def_id::DefId;
33
use rustc_infer::infer::at::ToTrace;
44
use rustc_infer::infer::canonical::{Canonical, QueryResponse};
55
use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt};
6-
use rustc_infer::traits::TraitEngineExt as _;
6+
use rustc_infer::traits::{ObligationCauseCode, TraitEngineExt as _};
77
use rustc_middle::ty::query::Providers;
88
use rustc_middle::ty::subst::{GenericArg, Subst, UserSelfTy, UserSubsts};
99
use rustc_middle::ty::{
@@ -22,6 +22,7 @@ use rustc_trait_selection::traits::query::type_op::subtype::Subtype;
2222
use rustc_trait_selection::traits::query::{Fallible, NoSolution};
2323
use rustc_trait_selection::traits::{Normalized, Obligation, ObligationCause, TraitEngine};
2424
use std::fmt;
25+
use std::iter::zip;
2526

2627
pub(crate) fn provide(p: &mut Providers) {
2728
*p = Providers {
@@ -61,14 +62,15 @@ pub fn type_op_ascribe_user_type_with_span<'a, 'tcx: 'a>(
6162
mir_ty, def_id, user_substs
6263
);
6364

64-
let mut cx = AscribeUserTypeCx { infcx, param_env, fulfill_cx };
65-
cx.relate_mir_and_user_ty(mir_ty, def_id, user_substs, span)?;
65+
let mut cx = AscribeUserTypeCx { infcx, param_env, span: span.unwrap_or(DUMMY_SP), fulfill_cx };
66+
cx.relate_mir_and_user_ty(mir_ty, def_id, user_substs)?;
6667
Ok(())
6768
}
6869

6970
struct AscribeUserTypeCx<'me, 'tcx> {
7071
infcx: &'me InferCtxt<'me, 'tcx>,
7172
param_env: ParamEnv<'tcx>,
73+
span: Span,
7274
fulfill_cx: &'me mut dyn TraitEngine<'tcx>,
7375
}
7476

@@ -79,7 +81,7 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> {
7981
{
8082
self.infcx
8183
.partially_normalize_associated_types_in(
82-
ObligationCause::misc(DUMMY_SP, hir::CRATE_HIR_ID),
84+
ObligationCause::misc(self.span, hir::CRATE_HIR_ID),
8385
self.param_env,
8486
value,
8587
)
@@ -91,18 +93,13 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> {
9193
T: ToTrace<'tcx>,
9294
{
9395
self.infcx
94-
.at(&ObligationCause::dummy(), self.param_env)
96+
.at(&ObligationCause::dummy_with_span(self.span), self.param_env)
9597
.relate(a, variance, b)?
9698
.into_value_registering_obligations(self.infcx, self.fulfill_cx);
9799
Ok(())
98100
}
99101

100-
fn prove_predicate(&mut self, predicate: Predicate<'tcx>, span: Option<Span>) {
101-
let cause = if let Some(span) = span {
102-
ObligationCause::dummy_with_span(span)
103-
} else {
104-
ObligationCause::dummy()
105-
};
102+
fn prove_predicate(&mut self, predicate: Predicate<'tcx>, cause: ObligationCause<'tcx>) {
106103
self.fulfill_cx.register_predicate_obligation(
107104
self.infcx,
108105
Obligation::new(cause, self.param_env, predicate),
@@ -126,7 +123,6 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> {
126123
mir_ty: Ty<'tcx>,
127124
def_id: DefId,
128125
user_substs: UserSubsts<'tcx>,
129-
span: Option<Span>,
130126
) -> Result<(), NoSolution> {
131127
let UserSubsts { user_self_ty, substs } = user_substs;
132128
let tcx = self.tcx();
@@ -145,10 +141,20 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> {
145141
// outlives" error messages.
146142
let instantiated_predicates =
147143
self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs);
144+
145+
let cause = ObligationCause::dummy_with_span(self.span);
146+
148147
debug!(?instantiated_predicates);
149-
for instantiated_predicate in instantiated_predicates.predicates {
150-
let instantiated_predicate = self.normalize(instantiated_predicate);
151-
self.prove_predicate(instantiated_predicate, span);
148+
for (instantiated_predicate, predicate_span) in
149+
zip(instantiated_predicates.predicates, instantiated_predicates.spans)
150+
{
151+
let span = if self.span == DUMMY_SP { predicate_span } else { self.span };
152+
let cause = ObligationCause::new(
153+
span,
154+
hir::CRATE_HIR_ID,
155+
ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span),
156+
);
157+
self.prove_predicate(instantiated_predicate, cause);
152158
}
153159

154160
if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
@@ -161,7 +167,7 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> {
161167
self.prove_predicate(
162168
ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into()))
163169
.to_predicate(self.tcx()),
164-
span,
170+
cause.clone(),
165171
);
166172
}
167173

@@ -178,7 +184,7 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> {
178184
// which...could happen with normalization...
179185
self.prove_predicate(
180186
ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())).to_predicate(self.tcx()),
181-
span,
187+
cause,
182188
);
183189
Ok(())
184190
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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+
use std::fmt::Debug;
8+
9+
pub trait LendingIterator {
10+
type Item<'this>
11+
where
12+
Self: 'this;
13+
}
14+
15+
pub struct WindowsMut<'x> {
16+
slice: &'x (),
17+
}
18+
19+
impl<'y> LendingIterator for WindowsMut<'y> {
20+
type Item<'this> = &'this mut () where 'y: 'this;
21+
}
22+
23+
fn print_items<I>(_iter: I)
24+
where
25+
I: LendingIterator,
26+
for<'a> I::Item<'a>: Debug,
27+
{
28+
}
29+
30+
fn main() {
31+
let slice = &mut ();
32+
//~^ temporary value dropped while borrowed
33+
let windows = WindowsMut { slice };
34+
print_items::<WindowsMut<'_>>(windows);
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error[E0716]: temporary value dropped while borrowed
2+
--> $DIR/hrtb-implied-1.rs:31:22
3+
|
4+
LL | let slice = &mut ();
5+
| ^^ creates a temporary which is freed while still in use
6+
...
7+
LL | print_items::<WindowsMut<'_>>(windows);
8+
| -------------------------------------- argument requires that borrow lasts for `'static`
9+
LL | }
10+
| - temporary value is freed at the end of this statement
11+
|
12+
note: due to current limitations in the borrow checker, this implies a `'static` lifetime
13+
--> $DIR/hrtb-implied-1.rs:26:26
14+
|
15+
LL | for<'a> I::Item<'a>: Debug,
16+
| ^^^^^
17+
18+
error: aborting due to previous error
19+
20+
For more information about this error, try `rustc --explain E0716`.

src/test/ui/nll/local-outlives-static-via-hrtb.stderr

+12
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ LL | assert_static_via_hrtb(&local);
99
LL | assert_static_via_hrtb_with_assoc_type(&&local);
1010
LL | }
1111
| - `local` dropped here while still borrowed
12+
|
13+
note: due to current limitations in the borrow checker, this implies a `'static` lifetime
14+
--> $DIR/local-outlives-static-via-hrtb.rs:15:53
15+
|
16+
LL | fn assert_static_via_hrtb<G>(_: G) where for<'a> G: Outlives<'a> {}
17+
| ^^^^^^^^^^^^
1218

1319
error[E0597]: `local` does not live long enough
1420
--> $DIR/local-outlives-static-via-hrtb.rs:25:45
@@ -20,6 +26,12 @@ LL | assert_static_via_hrtb_with_assoc_type(&&local);
2026
| argument requires that `local` is borrowed for `'static`
2127
LL | }
2228
| - `local` dropped here while still borrowed
29+
|
30+
note: due to current limitations in the borrow checker, this implies a `'static` lifetime
31+
--> $DIR/local-outlives-static-via-hrtb.rs:19:20
32+
|
33+
LL | for<'a> &'a T: Reference<AssociatedType = &'a ()>,
34+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2335

2436
error: aborting due to 2 previous errors
2537

0 commit comments

Comments
 (0)