Skip to content

Commit 8787090

Browse files
committed
Address review comments
1 parent 21eccbb commit 8787090

File tree

5 files changed

+69
-8
lines changed

5 files changed

+69
-8
lines changed

compiler/rustc_middle/src/query/mod.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,21 +159,37 @@ rustc_queries! {
159159
/// Returns the list of bounds that can be used for
160160
/// `SelectionCandidate::ProjectionCandidate` and
161161
/// `ProjectionTyCandidate::TraitDef`.
162-
/// Specifically this is the bounds (equivalent to) those
163-
/// written on the trait's type definition, or those
164-
/// after the `impl` keyword
162+
/// Specifically this is the bounds written on the trait's type
163+
/// definition, or those after the `impl` keyword
165164
///
166165
/// type X: Bound + 'lt
167166
/// ^^^^^^^^^^^
168167
/// impl Debug + Display
169168
/// ^^^^^^^^^^^^^^^
170169
///
171170
/// `key` is the `DefId` of the associated type or opaque type.
171+
///
172+
/// Bounds from the parent (e.g. with nested impl trait) are not included.
172173
query explicit_item_bounds(key: DefId) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
173174
desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) }
174175
}
175176

176-
/// Elaborated the predicates from `explicit_item_bounds`.
177+
/// Elaborated version of the predicates from `explicit_item_bounds`.
178+
///
179+
/// Example for
180+
///
181+
/// trait MyTrait {
182+
/// type MyAType: Eq + ?Sized`
183+
/// }
184+
///
185+
/// `explicit_item_bounds` returns `[<Self as MyTrait>::MyAType: Eq]`,
186+
/// and `item_bounds` returns
187+
/// [
188+
/// <Self as Trait>::MyAType: Eq,
189+
/// <Self as Trait>::MyAType: PartialEq<<Self as Trait>::MyAType>
190+
/// ]
191+
///
192+
/// Bounds from the parent (e.g. with nested impl trait) are not included.
177193
query item_bounds(key: DefId) -> &'tcx ty::List<ty::Predicate<'tcx>> {
178194
desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) }
179195
}

compiler/rustc_trait_selection/src/traits/select/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,6 +1156,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11561156
self.infcx.selection_cache.insert(param_env.and(trait_ref), dep_node, candidate);
11571157
}
11581158

1159+
/// Matches a predicate against the bounds of its self type.
1160+
///
1161+
/// Given an obligation like `<T as Foo>::Bar: Baz` where the self type is
1162+
/// a projection, look at the bounds of `T::Bar`, see if we can find a
1163+
/// `Baz` bound and it there is one it returns it.
11591164
fn match_projection_obligation_against_definition_bounds(
11601165
&mut self,
11611166
obligation: &TraitObligation<'tcx>,

compiler/rustc_trait_selection/src/traits/util.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use smallvec::SmallVec;
66
use rustc_data_structures::fx::FxHashSet;
77
use rustc_hir::def_id::DefId;
88
use rustc_middle::ty::subst::{GenericArg, Subst, SubstsRef};
9-
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
9+
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
1010

1111
use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext};
1212
pub use rustc_infer::traits::util::*;
@@ -365,14 +365,24 @@ pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool {
365365
/// trait X<A> { type Y<'a>: PartialEq<A> }
366366
///
367367
/// Say that we know that `<() as X<B>>::Y<'c> = i32` and we need to check that
368-
/// the `PartialEq` bound applies. This function would return
369-
/// `i32: PartialEq<B>`.
368+
/// the `PartialEq` bound applies. We would then call this function with:
369+
///
370+
/// - `bound` = `<Self as X<A>>::Y<'a>: PartialEq`
371+
/// - `normalized_projection_ty` = `i32`
372+
/// - `assoc_item_substs` = `[(), B, 'c]`
373+
///
374+
/// This method would then return `i32: PartialEq<B>`.
370375
pub fn subst_assoc_item_bound<'tcx>(
371376
tcx: TyCtxt<'tcx>,
372377
bound: ty::Predicate<'tcx>,
373378
normalized_projection_ty: Ty<'tcx>,
374379
assoc_item_substs: &[GenericArg<'tcx>],
375380
) -> ty::Predicate<'tcx> {
381+
// We're substituting these inside the closure passed to map_bound, so they
382+
// can't have escaping bound regions.
383+
assert!(!normalized_projection_ty.has_escaping_bound_vars());
384+
assert!(!assoc_item_substs.iter().all(|arg| arg.has_escaping_bound_vars()));
385+
376386
let translate_predicate_substs = move |predicate_substs: SubstsRef<'tcx>| {
377387
tcx.mk_substs(
378388
iter::once(normalized_projection_ty.into())

compiler/rustc_trait_selection/src/traits/wf.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,8 +337,26 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
337337
/// into `self.out`.
338338
fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) {
339339
// A projection is well-formed if
340-
// (a) its predicates hold
340+
//
341+
// (a) its predicates hold (*)
341342
// (b) its substs are wf
343+
//
344+
// (*) The predicates of an associated type include the predicates of
345+
// the trait that it's contained in. For example, given
346+
//
347+
// trait A<T>: Clone {
348+
// type X where T: Copy;
349+
// }
350+
//
351+
// The predicates of `<() as A<i32>>::X` are:
352+
// [
353+
// `(): Sized`
354+
// `(): Clone`
355+
// `(): A<i32>`
356+
// `i32: Sized`
357+
// `i32: Clone`
358+
// `i32: Copy`
359+
// ]
342360
let obligations = self.nominal_obligations(data.item_def_id, data.substs);
343361
self.out.extend(obligations);
344362

compiler/rustc_typeck/src/check/check.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,18 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
524524
}
525525

526526
/// Check that the concrete type behind `impl Trait` actually implements `Trait`.
527+
///
528+
/// This is mostly checked at the places that specify the opaque type, but we
529+
/// check those cases in the `param_env` of that function, which may have
530+
/// bounds not on this opaque type:
531+
///
532+
/// type X<T> = impl Clone
533+
/// fn f<T: Clone>(t: T) -> X<T> {
534+
/// t
535+
/// }
536+
///
537+
/// Without this check the above code is incorrectly accepted: we would ICE if
538+
/// some tried, for example, to clone an `Option<X<&mut ()>>`.
527539
fn check_opaque_meets_bounds<'tcx>(
528540
tcx: TyCtxt<'tcx>,
529541
def_id: LocalDefId,

0 commit comments

Comments
 (0)