diff options
| -rw-r--r-- | compiler/rustc_middle/src/query/mod.rs | 24 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/select/mod.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/util.rs | 16 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/wf.rs | 20 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/check/check.rs | 12 |
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, |
