impl<'tcx> OutlivesConstraintSet<'tcx> {
pub(crate) fn push(&mut self, constraint: OutlivesConstraint<'tcx>) {
- debug!(
- "OutlivesConstraintSet::push({:?}: {:?} @ {:?}",
- constraint.sup, constraint.sub, constraint.locations
- );
+ debug!("OutlivesConstraintSet::push({:?})", constraint);
if constraint.sup == constraint.sub {
// 'a: 'a is pretty uninteresting
return;
};
use super::{OutlivesSuggestionBuilder, RegionName};
-use crate::region_infer::BlameConstraint;
+use crate::region_infer::{BlameConstraint, ExtraConstraintInfo};
use crate::{
nll::ConstraintDescription,
region_infer::{values::RegionElement, TypeTest},
) {
debug!("report_region_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
- let BlameConstraint { category, cause, variance_info, .. } = self
- .regioncx
- .best_blame_constraint(fr, fr_origin, |r| {
+ let (blame_constraint, extra_info) =
+ self.regioncx.best_blame_constraint(fr, fr_origin, |r| {
self.regioncx.provides_universal_region(r, fr, outlived_fr)
- })
- .0;
+ });
+ let BlameConstraint { category, cause, variance_info, .. } = blame_constraint;
debug!("report_region_error: category={:?} {:?} {:?}", category, cause, variance_info);
}
}
+ for extra in extra_info {
+ match extra {
+ ExtraConstraintInfo::PlaceholderFromPredicate(span) => {
+ diag.span_note(span, format!("due to current limitations in the borrow checker, this implies a `'static` lifetime"));
+ }
+ }
+ }
+
self.buffer_error(diag);
}
/// LL | ref_obj(x)
/// | ^^^^^^^^^^ `x` escapes the function body here
/// ```
+ #[instrument(level = "debug", skip(self))]
fn report_escaping_data_error(
&self,
errci: &ErrorConstraintInfo<'tcx>,
);
}
+ #[instrument(level = "debug", skip(self))]
pub(super) fn normalize_and_prove_instantiated_predicates(
&mut self,
// Keep this parameter for now, in case we start using
.zip(instantiated_predicates.spans.into_iter())
{
debug!(?predicate);
- let predicate = self.normalize(predicate, locations);
- self.prove_predicate(predicate, locations, ConstraintCategory::Predicate(span));
+ let category = ConstraintCategory::Predicate(span);
+ let predicate = self.normalize_with_category(predicate, locations, category);
+ self.prove_predicate(predicate, locations, category);
}
}
})
}
- #[instrument(skip(self), level = "debug")]
pub(super) fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T
+ where
+ T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
+ {
+ self.normalize_with_category(value, location, ConstraintCategory::Boring)
+ }
+
+ #[instrument(skip(self), level = "debug")]
+ pub(super) fn normalize_with_category<T>(
+ &mut self,
+ value: T,
+ location: impl NormalizeLocation,
+ category: ConstraintCategory<'tcx>,
+ ) -> T
where
T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
{
let param_env = self.param_env;
self.fully_perform_op(
location.to_locations(),
- ConstraintCategory::Boring,
+ category,
param_env.and(type_op::normalize::Normalize::new(value)),
)
.unwrap_or_else(|NoSolution| {
}
fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
+ debug!(?constant, ?location, "visit_constant");
+
self.super_constant(constant, location);
let ty = self.sanitize_type(constant, constant.literal.ty());
}
fn check_operand(&mut self, op: &Operand<'tcx>, location: Location) {
+ debug!(?op, ?location, "check_operand");
+
if let Operand::Constant(constant) = op {
let maybe_uneval = match constant.literal {
ConstantKind::Ty(ct) => match ct.kind() {
T: TypeFoldable<'tcx>,
{
debug!(
- "normalize::<{}>(value={:?}, param_env={:?})",
+ "normalize::<{}>(value={:?}, param_env={:?}, cause={:?})",
std::any::type_name::<T>(),
value,
self.param_env,
+ self.cause,
);
if !needs_normalization(&value, self.param_env.reveal()) {
return Ok(Normalized { value, obligations: vec![] });
--- /dev/null
+// check-fail
+// known-bug
+
+// This gives us problems because `for<'a> I::Item<'a>: Debug` should mean "for
+// all 'a where I::Item<'a> is WF", but really means "for all 'a possible"
+
+trait LendingIterator: Sized {
+ type Item<'a>
+ where
+ Self: 'a;
+ fn next(&mut self) -> Self::Item<'_>;
+}
+fn fails<I: LendingIterator, F>(iter: &mut I, f: F) -> bool
+where
+ F: FnMut(I::Item<'_>),
+{
+ let mut iter2 = Eat(iter, f);
+ let _next = iter2.next();
+ //~^ borrowed data escapes
+ true
+}
+impl<I: LendingIterator> LendingIterator for &mut I {
+ type Item<'a> = I::Item<'a> where Self:'a;
+ fn next(&mut self) -> Self::Item<'_> {
+ (**self).next()
+ }
+}
+
+struct Eat<I, F>(I, F);
+impl<I: LendingIterator, F> Iterator for Eat<I, F>
+where
+ F: FnMut(I::Item<'_>),
+{
+ type Item = ();
+ fn next(&mut self) -> Option<Self::Item> {
+ None
+ }
+}
+
+fn main() {}
--- /dev/null
+error[E0521]: borrowed data escapes outside of function
+ --> $DIR/hrtb-implied-2.rs:18:17
+ |
+LL | fn fails<I: LendingIterator, F>(iter: &mut I, f: F) -> bool
+ | ---- - let's call the lifetime of this reference `'1`
+ | |
+ | `iter` is a reference that is only valid in the function body
+...
+LL | let _next = iter2.next();
+ | ^^^^^^^^^^^^
+ | |
+ | `iter` escapes the function body here
+ | argument requires that `'1` must outlive `'static`
+ |
+ = note: requirement occurs because of a mutable reference to `Eat<&mut I, F>`
+ = note: mutable references are invariant over their type parameter
+ = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+ = note: due to current limitations in the borrow checker, this implies a `'static` lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0521`.
--- /dev/null
+trait LendingIterator {
+ type Item<'a>
+ where
+ Self: 'a;
+}
+
+impl LendingIterator for &str {
+ type Item<'a> = () where Self:'a;
+}
+
+fn trivial_bound<I>(_: I)
+where
+ I: LendingIterator,
+ for<'a> I::Item<'a>: Sized,
+{
+}
+
+fn fails(iter: &str) {
+ trivial_bound(iter);
+ //~^ borrowed data escapes
+}
+
+fn main() {}
--- /dev/null
+error[E0521]: borrowed data escapes outside of function
+ --> $DIR/hrtb-implied-3.rs:19:5
+ |
+LL | fn fails(iter: &str) {
+ | ---- - let's call the lifetime of this reference `'1`
+ | |
+ | `iter` is a reference that is only valid in the function body
+LL | trivial_bound(iter);
+ | ^^^^^^^^^^^^^^^^^^^
+ | |
+ | `iter` escapes the function body here
+ | argument requires that `'1` must outlive `'static`
+ |
+note: due to current limitations in the borrow checker, this implies a `'static` lifetime
+ --> $DIR/hrtb-implied-3.rs:14:26
+ |
+LL | for<'a> I::Item<'a>: Sized,
+ | ^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0521`.
| |
| `x` escapes the function body here
| argument requires that `'1` must outlive `'static`
+ |
+ = note: due to current limitations in the borrow checker, this implies a `'static` lifetime
error: aborting due to previous error
| -- lifetime `'a` defined here
LL | want_hrtb::<&'a u32>()
| ^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+ |
+note: due to current limitations in the borrow checker, this implies a `'static` lifetime
+ --> $DIR/hrtb-just-for-static.rs:9:15
+ |
+LL | where T : for<'a> Foo<&'a isize>
+ | ^^^^^^^^^^^^^^^^^^^^^^
error: implementation of `Foo` is not general enough
--> $DIR/hrtb-just-for-static.rs:30:5
...
LL | foo_hrtb_bar_not(&mut t);
| ^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'static`
+ |
+note: due to current limitations in the borrow checker, this implies a `'static` lifetime
+ --> $DIR/hrtb-perfect-forwarding.rs:37:8
+ |
+LL | T: for<'a> Foo<&'a isize> + Bar<&'b isize>,
+ | ^^^^^^^^^^^^^^^^^^^^^^
error: implementation of `Bar` is not general enough
--> $DIR/hrtb-perfect-forwarding.rs:43:5
| -- lifetime `'a` defined here
LL | foo::<&'a i32>();
| ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+ |
+note: due to current limitations in the borrow checker, this implies a `'static` lifetime
+ --> $DIR/issue-26217.rs:1:30
+ |
+LL | fn foo<T>() where for<'a> T: 'a {}
+ | ^^
error: aborting due to previous error
| -- lifetime `'a` defined here
LL | outlives_forall::<Value<'a>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+ |
+note: due to current limitations in the borrow checker, this implies a `'static` lifetime
+ --> $DIR/type-test-universe.rs:6:16
+ |
+LL | for<'u> T: 'u,
+ | ^^
error: aborting due to 2 previous errors