about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_middle/src/query/mod.rs24
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs16
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs20
-rw-r--r--compiler/rustc_typeck/src/check/check.rs12
5 files changed, 69 insertions, 8 deletions
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 8b94818d8e6..808a0793a94 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -159,9 +159,8 @@ rustc_queries! {
         /// Returns the list of bounds that can be used for
         /// `SelectionCandidate::ProjectionCandidate` and
         /// `ProjectionTyCandidate::TraitDef`.
-        /// Specifically this is the bounds (equivalent to) those
-        /// written on the trait's type definition, or those
-        /// after the `impl` keyword
+        /// Specifically this is the bounds written on the trait's type
+        /// definition, or those after the `impl` keyword
         ///
         /// type X: Bound + 'lt
         ///         ^^^^^^^^^^^
@@ -169,11 +168,28 @@ rustc_queries! {
         ///      ^^^^^^^^^^^^^^^
         ///
         /// `key` is the `DefId` of the associated type or opaque type.
+        ///
+        /// Bounds from the parent (e.g. with nested impl trait) are not included.
         query explicit_item_bounds(key: DefId) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
             desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) }
         }
 
-        /// Elaborated the predicates from `explicit_item_bounds`.
+        /// Elaborated version of the predicates from `explicit_item_bounds`.
+        ///
+        /// Example for
+        ///
+        /// trait MyTrait {
+        ///     type MyAType: Eq + ?Sized`
+        /// }
+        ///
+        /// `explicit_item_bounds` returns `[<Self as MyTrait>::MyAType: Eq]`,
+        /// and `item_bounds` returns
+        /// [
+        ///     <Self as Trait>::MyAType: Eq,
+        ///     <Self as Trait>::MyAType: PartialEq<<Self as Trait>::MyAType>
+        /// ]
+        ///
+        /// Bounds from the parent (e.g. with nested impl trait) are not included.
         query item_bounds(key: DefId) -> &'tcx ty::List<ty::Predicate<'tcx>> {
             desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) }
         }
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index ab4226c4ed6..af90bc80d4d 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -1156,6 +1156,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         self.infcx.selection_cache.insert(param_env.and(trait_ref), dep_node, candidate);
     }
 
+    /// Matches a predicate against the bounds of its self type.
+    ///
+    /// Given an obligation like `<T as Foo>::Bar: Baz` where the self type is
+    /// a projection, look at the bounds of `T::Bar`, see if we can find a
+    /// `Baz` bound and it there is one it returns it.
     fn match_projection_obligation_against_definition_bounds(
         &mut self,
         obligation: &TraitObligation<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index 3d52453a5c7..0a4ce34c7f8 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -6,7 +6,7 @@ use smallvec::SmallVec;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::subst::{GenericArg, Subst, SubstsRef};
-use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
+use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
 
 use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext};
 pub use rustc_infer::traits::util::*;
@@ -365,14 +365,24 @@ pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool {
 /// trait X<A> { type Y<'a>: PartialEq<A> }
 ///
 /// Say that we know that `<() as X<B>>::Y<'c> = i32` and we need to check that
-/// the `PartialEq` bound applies. This function would return
-/// `i32: PartialEq<B>`.
+/// the `PartialEq` bound applies. We would then call this function with:
+///
+/// - `bound` = `<Self as X<A>>::Y<'a>: PartialEq`
+/// - `normalized_projection_ty` = `i32`
+/// - `assoc_item_substs` = `[(), B, 'c]`
+///
+/// This method would then return `i32: PartialEq<B>`.
 pub fn subst_assoc_item_bound<'tcx>(
     tcx: TyCtxt<'tcx>,
     bound: ty::Predicate<'tcx>,
     normalized_projection_ty: Ty<'tcx>,
     assoc_item_substs: &[GenericArg<'tcx>],
 ) -> ty::Predicate<'tcx> {
+    // We're substituting these inside the closure passed to map_bound, so they
+    // can't have escaping bound regions.
+    assert!(!normalized_projection_ty.has_escaping_bound_vars());
+    assert!(!assoc_item_substs.iter().all(|arg| arg.has_escaping_bound_vars()));
+
     let translate_predicate_substs = move |predicate_substs: SubstsRef<'tcx>| {
         tcx.mk_substs(
             iter::once(normalized_projection_ty.into())
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 9fd635c64a0..df816bbd348 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -337,8 +337,26 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
     /// into `self.out`.
     fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) {
         // A projection is well-formed if
-        // (a) its predicates hold
+        //
+        // (a) its predicates hold (*)
         // (b) its substs are wf
+        //
+        // (*) The predicates of an associated type include the predicates of
+        //     the trait that it's contained in. For example, given
+        //
+        // trait A<T>: Clone {
+        //     type X where T: Copy;
+        // }
+        //
+        // The predicates of `<() as A<i32>>::X` are:
+        // [
+        //     `(): Sized`
+        //     `(): Clone`
+        //     `(): A<i32>`
+        //     `i32: Sized`
+        //     `i32: Clone`
+        //     `i32: Copy`
+        // ]
         let obligations = self.nominal_obligations(data.item_def_id, data.substs);
         self.out.extend(obligations);
 
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index f5e6ff07b88..fbb19617c7f 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -524,6 +524,18 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
 }
 
 /// Check that the concrete type behind `impl Trait` actually implements `Trait`.
+///
+/// This is mostly checked at the places that specify the opaque type, but we
+/// check those cases in the `param_env` of that function, which may have
+/// bounds not on this opaque type:
+///
+/// type X<T> = impl Clone
+/// fn f<T: Clone>(t: T) -> X<T> {
+///     t
+/// }
+///
+/// Without this check the above code is incorrectly accepted: we would ICE if
+/// some tried, for example, to clone an `Option<X<&mut ()>>`.
 fn check_opaque_meets_bounds<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,