Split bounds from predicates

This commit is contained in:
Matthew Jasper 2020-06-24 19:13:44 +01:00
parent a7ead3bd53
commit d297147e62
10 changed files with 153 additions and 231 deletions

View File

@ -937,7 +937,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
.tables
.inferred_outlives
.get(self, item_id)
.map(|predicates| predicates.decode((self, tcx)))
.map(|predicates| tcx.arena.alloc_from_iter(predicates.decode((self, tcx))))
.unwrap_or_default()
}
@ -949,6 +949,19 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
self.root.tables.super_predicates.get(self, item_id).unwrap().decode((self, tcx))
}
fn get_explicit_item_bounds(
&self,
item_id: DefIndex,
tcx: TyCtxt<'tcx>,
) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
self.root
.tables
.explicit_item_bounds
.get(self, item_id)
.map(|bounds| tcx.arena.alloc_from_iter(bounds.decode((self, tcx))))
.unwrap_or_default()
}
fn get_generics(&self, item_id: DefIndex, sess: &Session) -> ty::Generics {
self.root.tables.generics.get(self, item_id).unwrap().decode((self, sess))
}

View File

@ -89,6 +89,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
explicit_predicates_of => { cdata.get_explicit_predicates(def_id.index, tcx) }
inferred_outlives_of => { cdata.get_inferred_outlives(def_id.index, tcx) }
super_predicates_of => { cdata.get_super_predicates(def_id.index, tcx) }
explicit_item_bounds => { cdata.get_explicit_item_bounds(def_id.index, tcx) }
trait_def => { cdata.get_trait_def(def_id.index, tcx.sess) }
adt_def => { cdata.get_adt_def(def_id.index, tcx) }
adt_destructor => {

View File

@ -965,6 +965,14 @@ impl EncodeContext<'a, 'tcx> {
record!(self.tables.super_predicates[def_id] <- self.tcx.super_predicates_of(def_id));
}
fn encode_explicit_item_bounds(&mut self, def_id: DefId) {
debug!("EncodeContext::encode_explicit_item_bounds({:?})", def_id);
let bounds = self.tcx.explicit_item_bounds(def_id);
if !bounds.is_empty() {
record!(self.tables.explicit_item_bounds[def_id] <- bounds);
}
}
fn encode_info_for_trait_item(&mut self, def_id: DefId) {
debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id);
let tcx = self.tcx;
@ -1017,7 +1025,10 @@ impl EncodeContext<'a, 'tcx> {
has_self: trait_item.fn_has_self_parameter,
}))
}
ty::AssocKind::Type => EntryKind::AssocType(container),
ty::AssocKind::Type => {
self.encode_explicit_item_bounds(def_id);
EntryKind::AssocType(container)
}
});
record!(self.tables.visibility[def_id] <- trait_item.vis);
record!(self.tables.span[def_id] <- ast_item.span);

View File

@ -295,13 +295,11 @@ define_tables! {
generics: Table<DefIndex, Lazy<ty::Generics>>,
explicit_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
expn_that_defined: Table<DefIndex, Lazy<ExpnId>>,
// FIXME(eddyb) this would ideally be `Lazy<[...]>` but `ty::Predicate`
// doesn't handle shorthands in its own (de)serialization impls,
// as it's an `enum` for which we want to derive (de)serialization,
// so the `ty::codec` APIs handle the whole `&'tcx [...]` at once.
// Also, as an optimization, a missing entry indicates an empty `&[]`.
inferred_outlives: Table<DefIndex, Lazy!(&'tcx [(ty::Predicate<'tcx>, Span)])>,
// As an optimization, a missing entry indicates an empty `&[]`.
inferred_outlives: Table<DefIndex, Lazy!([(ty::Predicate<'tcx>, Span)])>,
super_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
// As an optimization, a missing entry indicates an empty `&[]`.
explicit_item_bounds: Table<DefIndex, Lazy!([(ty::Predicate<'tcx>, Span)])>,
mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
mir_abstract_consts: Table<DefIndex, Lazy!(&'tcx [mir::abstract_const::Node<'tcx>])>,

View File

@ -169,8 +169,13 @@ rustc_queries! {
/// ^^^^^^^^^^^^^^^
///
/// `key` is the `DefId` of the associated type or opaque type.
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`.
query item_bounds(key: DefId) -> &'tcx ty::List<ty::Predicate<'tcx>> {
desc { |tcx| "finding projection predicates for `{}`", tcx.def_path_str(key) }
desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) }
}
query projection_ty_from_predicates(key: (DefId, DefId)) -> Option<ty::ProjectionTy<'tcx>> {

View File

@ -607,12 +607,12 @@ pub trait PrettyPrinter<'tcx>:
}
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
// by looking up the projections associated with the def_id.
let bounds = self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs);
let bounds = self.tcx().item_bounds(def_id).subst(self.tcx(), substs);
let mut first = true;
let mut is_sized = false;
p!("impl");
for predicate in bounds.predicates {
for predicate in bounds {
// Note: We can't use `to_opt_poly_trait_ref` here as `predicate`
// may contain unbound variables. We therefore do this manually.
//

View File

@ -10,7 +10,7 @@ use rustc_infer::infer::free_regions::FreeRegionRelations;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{self, InferCtxt, InferOk};
use rustc_middle::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor};
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef};
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::config::nightly_options;
use rustc_span::Span;
@ -428,14 +428,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// If there are required region bounds, we can use them.
if opaque_defn.has_required_region_bounds {
let predicates_of = tcx.predicates_of(def_id);
debug!("constrain_opaque_type: predicates: {:#?}", predicates_of,);
let bounds = predicates_of.instantiate(tcx, opaque_defn.substs);
let bounds = tcx.explicit_item_bounds(def_id);
debug!("constrain_opaque_type: predicates: {:#?}", bounds);
let bounds: Vec<_> =
bounds.iter().map(|(bound, _)| bound.subst(tcx, opaque_defn.substs)).collect();
debug!("constrain_opaque_type: bounds={:#?}", bounds);
let opaque_type = tcx.mk_opaque(def_id, opaque_defn.substs);
let required_region_bounds =
required_region_bounds(tcx, opaque_type, bounds.predicates.into_iter());
required_region_bounds(tcx, opaque_type, bounds.into_iter());
debug_assert!(!required_region_bounds.is_empty());
for required_region in required_region_bounds {
@ -1112,9 +1113,10 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
let ty_var = infcx
.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });
let predicates_of = tcx.predicates_of(def_id);
debug!("instantiate_opaque_types: predicates={:#?}", predicates_of,);
let bounds = predicates_of.instantiate(tcx, substs);
let item_bounds = tcx.explicit_item_bounds(def_id);
debug!("instantiate_opaque_types: bounds={:#?}", item_bounds);
let bounds: Vec<_> =
item_bounds.iter().map(|(bound, _)| bound.subst(tcx, substs)).collect();
let param_env = tcx.param_env(def_id);
let InferOk { value: bounds, obligations } =
@ -1123,8 +1125,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
debug!("instantiate_opaque_types: bounds={:?}", bounds);
let required_region_bounds =
required_region_bounds(tcx, ty, bounds.predicates.iter().cloned());
let required_region_bounds = required_region_bounds(tcx, ty, bounds.iter().copied());
debug!("instantiate_opaque_types: required_region_bounds={:?}", required_region_bounds);
// Make sure that we are in fact defining the *entire* type
@ -1153,7 +1154,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
);
debug!("instantiate_opaque_types: ty_var={:?}", ty_var);
for predicate in &bounds.predicates {
for predicate in &bounds {
if let ty::PredicateAtom::Projection(projection) = predicate.skip_binders() {
if projection.ty.references_error() {
// No point on adding these obligations since there's a type error involved.
@ -1162,8 +1163,8 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
}
}
self.obligations.reserve(bounds.predicates.len());
for predicate in bounds.predicates {
self.obligations.reserve(bounds.len());
for predicate in bounds {
// Change the predicate to refer to the type variable,
// which will be the concrete type instead of the opaque type.
// This also instantiates nested instances of `impl Trait`.

View File

@ -71,12 +71,8 @@ impl<'tcx> Bounds<'tcx> {
self.region_bounds
.iter()
.map(|&(region_bound, span)| {
// Account for the binder being introduced below; no need to shift `param_ty`
// because, at present at least, it either only refers to early-bound regions,
// or it's a generic associated type that deliberately has escaping bound vars.
let region_bound = ty::fold::shift_region(tcx, region_bound, 1);
let outlives = ty::OutlivesPredicate(param_ty, region_bound);
(ty::Binder::bind(outlives).to_predicate(tcx), span)
(ty::Binder::dummy(outlives).to_predicate(tcx), span)
})
.chain(self.trait_bounds.iter().map(|&(bound_trait_ref, span, constness)| {
let predicate = bound_trait_ref.with_constness(constness).to_predicate(tcx);

View File

@ -70,6 +70,7 @@ pub fn provide(providers: &mut Providers) {
opt_const_param_of: type_of::opt_const_param_of,
type_of: type_of::type_of,
item_bounds: item_bounds::item_bounds,
explicit_item_bounds: item_bounds::explicit_item_bounds,
generics_of,
predicates_of,
predicates_defined_on,
@ -1728,7 +1729,6 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
let mut is_trait = None;
let mut is_default_impl_trait = None;
let mut is_trait_associated_type = None;
let icx = ItemCtxt::new(tcx, def_id);
let constness = icx.default_constness_for_trait_bounds();
@ -1741,12 +1741,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
let mut predicates: FxIndexSet<(ty::Predicate<'_>, Span)> = FxIndexSet::default();
let ast_generics = match node {
Node::TraitItem(item) => {
if let hir::TraitItemKind::Type(bounds, _) = item.kind {
is_trait_associated_type = Some((bounds, item.span));
}
&item.generics
}
Node::TraitItem(item) => &item.generics,
Node::ImplItem(item) => &item.generics,
@ -1764,44 +1759,26 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
| ItemKind::Struct(_, ref generics)
| ItemKind::Union(_, ref generics) => generics,
ItemKind::Trait(_, _, ref generics, .., items) => {
is_trait = Some((ty::TraitRef::identity(tcx, def_id), items));
ItemKind::Trait(_, _, ref generics, ..) => {
is_trait = Some(ty::TraitRef::identity(tcx, def_id));
generics
}
ItemKind::TraitAlias(ref generics, _) => {
is_trait = Some((ty::TraitRef::identity(tcx, def_id), &[]));
is_trait = Some(ty::TraitRef::identity(tcx, def_id));
generics
}
ItemKind::OpaqueTy(OpaqueTy {
ref bounds,
bounds: _,
impl_trait_fn,
ref generics,
origin: _,
}) => {
let bounds_predicates = ty::print::with_no_queries(|| {
let substs = InternalSubsts::identity_for_item(tcx, def_id);
let opaque_ty = tcx.mk_opaque(def_id, substs);
// Collect the bounds, i.e., the `A + B + 'c` in `impl A + B + 'c`.
let bounds = AstConv::compute_bounds(
&icx,
opaque_ty,
bounds,
SizedByDefault::Yes,
tcx.def_span(def_id),
);
bounds.predicates(tcx, opaque_ty)
});
if impl_trait_fn.is_some() {
// opaque types
return ty::GenericPredicates {
parent: None,
predicates: tcx.arena.alloc_from_iter(bounds_predicates),
};
// return-position impl trait
// TODO: Investigate why we have this special case?
return ty::GenericPredicates { parent: None, predicates: &[] };
} else {
// named opaque types
predicates.extend(bounds_predicates);
// type alias impl trait
generics
}
}
@ -1827,7 +1804,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
// and the explicit where-clauses, but to get the full set of predicates
// on a trait we need to add in the supertrait bounds and bounds found on
// associated types.
if let Some((_trait_ref, _)) = is_trait {
if let Some(_trait_ref) = is_trait {
predicates.extend(tcx.super_predicates_of(def_id).predicates.iter().cloned());
}
@ -1994,24 +1971,6 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
}
}
// Add predicates from associated type bounds (`type X: Bound`)
if tcx.features().generic_associated_types {
// New behavior: bounds declared on associate type are predicates of that
// associated type. Not the default because it needs more testing.
if let Some((bounds, span)) = is_trait_associated_type {
let projection_ty =
tcx.mk_projection(def_id, InternalSubsts::identity_for_item(tcx, def_id));
predicates.extend(associated_item_bounds(tcx, def_id, bounds, projection_ty, span))
}
} else if let Some((self_trait_ref, trait_items)) = is_trait {
// Current behavior: bounds declared on associate type are predicates
// of its parent trait.
predicates.extend(trait_items.iter().flat_map(|trait_item_ref| {
trait_associated_item_predicates(tcx, def_id, self_trait_ref, trait_item_ref)
}))
}
if tcx.features().const_evaluatable_checked {
predicates.extend(const_evaluatable_predicates_of(tcx, def_id.expect_local()));
}
@ -2155,55 +2114,6 @@ fn projection_ty_from_predicates(
projection_ty
}
fn trait_associated_item_predicates(
tcx: TyCtxt<'tcx>,
def_id: DefId,
self_trait_ref: ty::TraitRef<'tcx>,
trait_item_ref: &hir::TraitItemRef,
) -> Vec<(ty::Predicate<'tcx>, Span)> {
let trait_item = tcx.hir().trait_item(trait_item_ref.id);
let item_def_id = tcx.hir().local_def_id(trait_item_ref.id.hir_id);
let bounds = match trait_item.kind {
hir::TraitItemKind::Type(ref bounds, _) => bounds,
_ => return Vec::new(),
};
if !tcx.generics_of(item_def_id).params.is_empty() {
// For GATs the substs provided to the mk_projection call below are
// wrong. We should emit a feature gate error if we get here so skip
// this type.
tcx.sess.delay_span_bug(trait_item.span, "gats used without feature gate");
return Vec::new();
}
let assoc_ty = tcx.mk_projection(
tcx.hir().local_def_id(trait_item.hir_id).to_def_id(),
self_trait_ref.substs,
);
associated_item_bounds(tcx, def_id, bounds, assoc_ty, trait_item.span)
}
fn associated_item_bounds(
tcx: TyCtxt<'tcx>,
def_id: DefId,
bounds: &'tcx [hir::GenericBound<'tcx>],
projection_ty: Ty<'tcx>,
span: Span,
) -> Vec<(ty::Predicate<'tcx>, Span)> {
let bounds = AstConv::compute_bounds(
&ItemCtxt::new(tcx, def_id),
projection_ty,
bounds,
SizedByDefault::Yes,
span,
);
let predicates = bounds.predicates(tcx, projection_ty);
predicates
}
/// Converts a specific `GenericBound` from the AST into a set of
/// predicates that apply to the self type. A vector is returned
/// because this can be anywhere from zero predicates (`T: ?Sized` adds no

View File

@ -1,126 +1,113 @@
use rustc_hir::def::DefKind;
use super::ItemCtxt;
use crate::astconv::{AstConv, SizedByDefault};
use rustc_hir as hir;
use rustc_infer::traits::util;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::def_id::DefId;
use rustc_span::Span;
/// For associated types we allow bounds written on the associated type
/// (`type X: Trait`) to be used as candidates. We also allow the same bounds
/// when desugared as bounds on the trait `where Self::X: Trait`.
/// For associated types we include both bounds written on the type
/// (`type X: Trait`) and predicates from the trait: `where Self::X: Trait`.
///
/// Note that this filtering is done with the items identity substs to
/// simplify checking that these bounds are met in impls. This means that
/// a bound such as `for<'b> <Self as X<'b>>::U: Clone` can't be used, as in
/// `hr-associated-type-bound-1.rs`.
fn associated_type_bounds(
tcx: TyCtxt<'_>,
fn associated_type_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
assoc_item_def_id: DefId,
) -> &'_ ty::List<ty::Predicate<'_>> {
let generic_trait_bounds = tcx.predicates_of(assoc_item_def_id);
// We include predicates from the trait as well to handle
// `where Self::X: Trait`.
let item_bounds = generic_trait_bounds.instantiate_identity(tcx);
let item_predicates = util::elaborate_predicates(tcx, item_bounds.predicates.into_iter());
bounds: &'tcx [hir::GenericBound<'tcx>],
span: Span,
) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
let item_ty = tcx.mk_projection(
assoc_item_def_id,
InternalSubsts::identity_for_item(tcx, assoc_item_def_id),
);
let assoc_item_ty = ty::ProjectionTy {
item_def_id: assoc_item_def_id,
substs: InternalSubsts::identity_for_item(tcx, assoc_item_def_id),
};
let bounds = AstConv::compute_bounds(
&ItemCtxt::new(tcx, assoc_item_def_id),
item_ty,
bounds,
SizedByDefault::Yes,
span,
);
let predicates = item_predicates.filter_map(|obligation| {
let pred = obligation.predicate;
match pred.kind() {
ty::PredicateKind::Trait(tr, _) => {
if let ty::Projection(p) = *tr.skip_binder().self_ty().kind() {
if p == assoc_item_ty {
return Some(pred);
}
}
}
let trait_def_id = tcx.associated_item(assoc_item_def_id).container.id();
let trait_predicates = tcx.predicates_of(trait_def_id);
let bounds_from_parent =
trait_predicates.predicates.iter().copied().filter(|(pred, _)| match pred.kind() {
ty::PredicateKind::Trait(tr, _) => tr.skip_binder().self_ty() == item_ty,
ty::PredicateKind::Projection(proj) => {
if let ty::Projection(p) = *proj.skip_binder().projection_ty.self_ty().kind() {
if p == assoc_item_ty {
return Some(pred);
}
}
proj.skip_binder().projection_ty.self_ty() == item_ty
}
ty::PredicateKind::TypeOutlives(outlives) => {
if let ty::Projection(p) = *outlives.skip_binder().0.kind() {
if p == assoc_item_ty {
return Some(pred);
}
}
}
_ => {}
}
None
});
ty::PredicateKind::TypeOutlives(outlives) => outlives.skip_binder().0 == item_ty,
_ => false,
});
let result = tcx.mk_predicates(predicates);
debug!("associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id), result);
result
let all_bounds = tcx
.arena
.alloc_from_iter(bounds.predicates(tcx, item_ty).into_iter().chain(bounds_from_parent));
debug!("associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id), all_bounds);
all_bounds
}
/// Opaque types don't have the same issues as associated types: the only
/// predicates on an opaque type (excluding those it inherits from its parent
/// item) should be of the form we're expecting.
fn opaque_type_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List<ty::Predicate<'_>> {
let substs = InternalSubsts::identity_for_item(tcx, def_id);
/// Opaque types don't inherit bounds from their parent: for return position
/// impl trait it isn't possible to write a suitable predicate on the
/// containing function and for type-alias impl trait we don't have a backwards
/// compatibility issue.
fn opaque_type_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
opaque_def_id: DefId,
bounds: &'tcx [hir::GenericBound<'tcx>],
span: Span,
) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
let item_ty =
tcx.mk_opaque(opaque_def_id, InternalSubsts::identity_for_item(tcx, opaque_def_id));
let bounds = tcx.predicates_of(def_id);
let predicates =
util::elaborate_predicates(tcx, bounds.predicates.iter().map(|&(pred, _)| pred));
let filtered_predicates = predicates.filter_map(|obligation| {
let pred = obligation.predicate;
match pred.kind() {
ty::PredicateKind::Trait(tr, _) => {
if let ty::Opaque(opaque_def_id, opaque_substs) = *tr.skip_binder().self_ty().kind()
{
if opaque_def_id == def_id && opaque_substs == substs {
return Some(pred);
}
}
}
ty::PredicateKind::Projection(proj) => {
if let ty::Opaque(opaque_def_id, opaque_substs) =
*proj.skip_binder().projection_ty.self_ty().kind()
{
if opaque_def_id == def_id && opaque_substs == substs {
return Some(pred);
}
}
}
ty::PredicateKind::TypeOutlives(outlives) => {
if let ty::Opaque(opaque_def_id, opaque_substs) = *outlives.skip_binder().0.kind() {
if opaque_def_id == def_id && opaque_substs == substs {
return Some(pred);
}
} else {
// These can come from elaborating other predicates
return None;
}
}
// These can come from elaborating other predicates
ty::PredicateKind::RegionOutlives(_) => return None,
_ => {}
}
tcx.sess.delay_span_bug(
obligation.cause.span(tcx),
&format!("unexpected predicate {:?} on opaque type", pred),
);
None
let bounds = ty::print::with_no_queries(|| {
AstConv::compute_bounds(
&ItemCtxt::new(tcx, opaque_def_id),
item_ty,
bounds,
SizedByDefault::Yes,
span,
)
});
let result = tcx.mk_predicates(filtered_predicates);
debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(def_id), result);
result
let bounds = bounds.predicates(tcx, item_ty);
debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(opaque_def_id), bounds);
tcx.arena.alloc_slice(&bounds)
}
pub(super) fn explicit_item_bounds(
tcx: TyCtxt<'_>,
def_id: DefId,
) -> &'_ [(ty::Predicate<'_>, Span)] {
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
match tcx.hir().get(hir_id) {
hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Type(bounds, _),
span,
..
}) => associated_type_bounds(tcx, def_id, bounds, *span),
hir::Node::Item(hir::Item {
kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }),
span,
..
}) => opaque_type_bounds(tcx, def_id, bounds, *span),
_ => bug!("item_bounds called on {:?}", def_id),
}
}
pub(super) fn item_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List<ty::Predicate<'_>> {
match tcx.def_kind(def_id) {
DefKind::AssocTy => associated_type_bounds(tcx, def_id),
DefKind::OpaqueTy => opaque_type_bounds(tcx, def_id),
k => bug!("item_bounds called on {}", k.descr(def_id)),
}
tcx.mk_predicates(
util::elaborate_predicates(
tcx,
tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound),
)
.map(|obligation| obligation.predicate),
)
}