]> git.lizzy.rs Git - rust.git/commitdiff
Use Predicate ConstraintCategory when normalizing
authorJack Huey <31162821+jackh726@users.noreply.github.com>
Wed, 31 Aug 2022 01:50:22 +0000 (21:50 -0400)
committerJack Huey <31162821+jackh726@users.noreply.github.com>
Wed, 14 Sep 2022 00:18:49 +0000 (20:18 -0400)
14 files changed:
compiler/rustc_borrowck/src/constraints/mod.rs
compiler/rustc_borrowck/src/diagnostics/region_errors.rs
compiler/rustc_borrowck/src/type_check/canonical.rs
compiler/rustc_borrowck/src/type_check/mod.rs
compiler/rustc_trait_selection/src/traits/query/normalize.rs
src/test/ui/generic-associated-types/bugs/hrtb-implied-2.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/bugs/hrtb-implied-2.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/bugs/hrtb-implied-3.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/bugs/hrtb-implied-3.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/trait-objects.extended.stderr
src/test/ui/higher-rank-trait-bounds/hrtb-just-for-static.stderr
src/test/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.stderr
src/test/ui/issues/issue-26217.stderr
src/test/ui/nll/type-test-universe.stderr

index 6d323b03cdaa3f1640e96cc74b004173e853ffb9..df04128135b8986c2a976af99df433447e1f1af2 100644 (file)
@@ -21,10 +21,7 @@ pub(crate) struct OutlivesConstraintSet<'tcx> {
 
 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;
index c276719c227b011f91b8b4a3eb4e606541aa0011..34be2874fcb738d527c9f64923eb2aa7921f006e 100644 (file)
@@ -31,7 +31,7 @@
 };
 
 use super::{OutlivesSuggestionBuilder, RegionName};
-use crate::region_infer::BlameConstraint;
+use crate::region_infer::{BlameConstraint, ExtraConstraintInfo};
 use crate::{
     nll::ConstraintDescription,
     region_infer::{values::RegionElement, TypeTest},
@@ -354,12 +354,11 @@ pub(crate) fn report_region_error(
     ) {
         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);
 
@@ -468,6 +467,14 @@ pub(crate) fn report_region_error(
             }
         }
 
+        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);
     }
 
@@ -559,6 +566,7 @@ fn report_fnmut_error(
     /// LL |     ref_obj(x)
     ///    |     ^^^^^^^^^^ `x` escapes the function body here
     /// ```
+    #[instrument(level = "debug", skip(self))]
     fn report_escaping_data_error(
         &self,
         errci: &ErrorConstraintInfo<'tcx>,
index 8a3972a12c5431cfbe2a189e99185e088fe0daf7..9271a2f4dc718f345fb32bad3814386fda2b2738 100644 (file)
@@ -104,6 +104,7 @@ pub(super) fn prove_trait_ref(
         );
     }
 
+    #[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
@@ -118,8 +119,9 @@ pub(super) fn normalize_and_prove_instantiated_predicates(
             .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);
         }
     }
 
@@ -155,15 +157,27 @@ pub(super) fn prove_predicate(
         })
     }
 
-    #[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| {
index 1143dd5489d9b9931a02eab3cf29cc5aeed5ddda..3ad89cfe02fc1ac3d923e2be1f5348da91176af2 100644 (file)
@@ -311,6 +311,8 @@ fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location:
     }
 
     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());
 
@@ -1810,6 +1812,8 @@ fn aggregate_field_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() {
index f65fc5bad0d9184144b37fa1fe0a3a41d2f6611d..a3f8f4e2ed0eda65b37b5b5920ba082a82618d2c 100644 (file)
@@ -48,10 +48,11 @@ fn normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
         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![] });
diff --git a/src/test/ui/generic-associated-types/bugs/hrtb-implied-2.rs b/src/test/ui/generic-associated-types/bugs/hrtb-implied-2.rs
new file mode 100644 (file)
index 0000000..8e6c534
--- /dev/null
@@ -0,0 +1,40 @@
+// 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() {}
diff --git a/src/test/ui/generic-associated-types/bugs/hrtb-implied-2.stderr b/src/test/ui/generic-associated-types/bugs/hrtb-implied-2.stderr
new file mode 100644 (file)
index 0000000..1ee2703
--- /dev/null
@@ -0,0 +1,22 @@
+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`.
diff --git a/src/test/ui/generic-associated-types/bugs/hrtb-implied-3.rs b/src/test/ui/generic-associated-types/bugs/hrtb-implied-3.rs
new file mode 100644 (file)
index 0000000..bc9e6c8
--- /dev/null
@@ -0,0 +1,23 @@
+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() {}
diff --git a/src/test/ui/generic-associated-types/bugs/hrtb-implied-3.stderr b/src/test/ui/generic-associated-types/bugs/hrtb-implied-3.stderr
new file mode 100644 (file)
index 0000000..c67e024
--- /dev/null
@@ -0,0 +1,22 @@
+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`.
index 086177cc106dc224dfcdcd99dc42db122f22b250..45b64d2b0248376fcbf0d65067ab7410be818f3e 100644 (file)
@@ -11,6 +11,8 @@ LL |     x.size_hint().0
    |     |
    |     `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
 
index b4312091edb279f9a987b73efe3e97634be548aa..31e11e12835166a4aca0c219a9cfd58ecc0f3b0b 100644 (file)
@@ -14,6 +14,12 @@ LL | fn give_some<'a>() {
    |              -- 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
index 1461e7fd2ddd7fbddddb647509cda2b91bfcfe72..5e75a4cc8afa5021cb0da986e4d1c29990ce3e1c 100644 (file)
@@ -46,6 +46,12 @@ LL | fn foo_hrtb_bar_not<'b, T>(mut t: T)
 ...
 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
index c7601caacdca3fb4e56bc147a45e82e0a05fb767..73c772205c3dadb34e48d29c2bb9369afaf3d5a6 100644 (file)
@@ -5,6 +5,12 @@ LL | fn bar<'a>() {
    |        -- 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
 
index 242486c360a8090ea7f215d4448e6039250c8136..31e17d64b8caf4b41165d3da1e29aa3270bc3695 100644 (file)
@@ -11,6 +11,12 @@ LL | fn test2<'a>() {
    |          -- 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