1
Fork 0

Address review comments

This commit is contained in:
Matthew Jasper 2020-07-02 21:45:28 +01:00
parent 21eccbb587
commit 8787090964
5 changed files with 69 additions and 8 deletions

View file

@ -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>,

View file

@ -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())

View file

@ -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);