Address review comments
This commit is contained in:
parent
21eccbb587
commit
8787090964
5 changed files with 69 additions and 8 deletions
|
@ -159,9 +159,8 @@ rustc_queries! {
|
||||||
/// Returns the list of bounds that can be used for
|
/// Returns the list of bounds that can be used for
|
||||||
/// `SelectionCandidate::ProjectionCandidate` and
|
/// `SelectionCandidate::ProjectionCandidate` and
|
||||||
/// `ProjectionTyCandidate::TraitDef`.
|
/// `ProjectionTyCandidate::TraitDef`.
|
||||||
/// Specifically this is the bounds (equivalent to) those
|
/// Specifically this is the bounds written on the trait's type
|
||||||
/// written on the trait's type definition, or those
|
/// definition, or those after the `impl` keyword
|
||||||
/// after the `impl` keyword
|
|
||||||
///
|
///
|
||||||
/// type X: Bound + 'lt
|
/// type X: Bound + 'lt
|
||||||
/// ^^^^^^^^^^^
|
/// ^^^^^^^^^^^
|
||||||
|
@ -169,11 +168,28 @@ rustc_queries! {
|
||||||
/// ^^^^^^^^^^^^^^^
|
/// ^^^^^^^^^^^^^^^
|
||||||
///
|
///
|
||||||
/// `key` is the `DefId` of the associated type or opaque type.
|
/// `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)] {
|
query explicit_item_bounds(key: DefId) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
|
||||||
desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) }
|
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>> {
|
query item_bounds(key: DefId) -> &'tcx ty::List<ty::Predicate<'tcx>> {
|
||||||
desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) }
|
desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1156,6 +1156,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
self.infcx.selection_cache.insert(param_env.and(trait_ref), dep_node, candidate);
|
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(
|
fn match_projection_obligation_against_definition_bounds(
|
||||||
&mut self,
|
&mut self,
|
||||||
obligation: &TraitObligation<'tcx>,
|
obligation: &TraitObligation<'tcx>,
|
||||||
|
|
|
@ -6,7 +6,7 @@ use smallvec::SmallVec;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::ty::subst::{GenericArg, Subst, SubstsRef};
|
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};
|
use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext};
|
||||||
pub use rustc_infer::traits::util::*;
|
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> }
|
/// 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
|
/// 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
|
/// the `PartialEq` bound applies. We would then call this function with:
|
||||||
/// `i32: PartialEq<B>`.
|
///
|
||||||
|
/// - `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>(
|
pub fn subst_assoc_item_bound<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
bound: ty::Predicate<'tcx>,
|
bound: ty::Predicate<'tcx>,
|
||||||
normalized_projection_ty: Ty<'tcx>,
|
normalized_projection_ty: Ty<'tcx>,
|
||||||
assoc_item_substs: &[GenericArg<'tcx>],
|
assoc_item_substs: &[GenericArg<'tcx>],
|
||||||
) -> ty::Predicate<'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>| {
|
let translate_predicate_substs = move |predicate_substs: SubstsRef<'tcx>| {
|
||||||
tcx.mk_substs(
|
tcx.mk_substs(
|
||||||
iter::once(normalized_projection_ty.into())
|
iter::once(normalized_projection_ty.into())
|
||||||
|
|
|
@ -337,8 +337,26 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
||||||
/// into `self.out`.
|
/// into `self.out`.
|
||||||
fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) {
|
fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) {
|
||||||
// A projection is well-formed if
|
// A projection is well-formed if
|
||||||
// (a) its predicates hold
|
//
|
||||||
|
// (a) its predicates hold (*)
|
||||||
// (b) its substs are wf
|
// (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);
|
let obligations = self.nominal_obligations(data.item_def_id, data.substs);
|
||||||
self.out.extend(obligations);
|
self.out.extend(obligations);
|
||||||
|
|
||||||
|
|
|
@ -524,6 +524,18 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check that the concrete type behind `impl Trait` actually implements `Trait`.
|
/// 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>(
|
fn check_opaque_meets_bounds<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
def_id: LocalDefId,
|
def_id: LocalDefId,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue