From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_typeck/src/bounds.rs | 90 +++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 compiler/rustc_typeck/src/bounds.rs (limited to 'compiler/rustc_typeck/src/bounds.rs') diff --git a/compiler/rustc_typeck/src/bounds.rs b/compiler/rustc_typeck/src/bounds.rs new file mode 100644 index 000000000..6a28bb16a --- /dev/null +++ b/compiler/rustc_typeck/src/bounds.rs @@ -0,0 +1,90 @@ +//! Bounds are restrictions applied to some types after they've been converted into the +//! `ty` form from the HIR. + +use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; +use rustc_span::Span; + +/// Collects together a list of type bounds. These lists of bounds occur in many places +/// in Rust's syntax: +/// +/// ```text +/// trait Foo: Bar + Baz { } +/// ^^^^^^^^^ supertrait list bounding the `Self` type parameter +/// +/// fn foo() { } +/// ^^^^^^^^^ bounding the type parameter `T` +/// +/// impl dyn Bar + Baz +/// ^^^^^^^^^ bounding the forgotten dynamic type +/// ``` +/// +/// Our representation is a bit mixed here -- in some cases, we +/// include the self type (e.g., `trait_bounds`) but in others we do not +#[derive(Default, PartialEq, Eq, Clone, Debug)] +pub struct Bounds<'tcx> { + /// A list of region bounds on the (implicit) self type. So if you + /// had `T: 'a + 'b` this might would be a list `['a, 'b]` (but + /// the `T` is not explicitly included). + pub region_bounds: Vec<(ty::Binder<'tcx, ty::Region<'tcx>>, Span)>, + + /// A list of trait bounds. So if you had `T: Debug` this would be + /// `T: Debug`. Note that the self-type is explicit here. + pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span, ty::BoundConstness)>, + + /// A list of projection equality bounds. So if you had `T: + /// Iterator` this would include `::Item => u32`. Note that the self-type is explicit + /// here. + pub projection_bounds: Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>, + + /// `Some` if there is *no* `?Sized` predicate. The `span` + /// is the location in the source of the `T` declaration which can + /// be cited as the source of the `T: Sized` requirement. + pub implicitly_sized: Option, +} + +impl<'tcx> Bounds<'tcx> { + /// Converts a bounds list into a flat set of predicates (like + /// where-clauses). Because some of our bounds listings (e.g., + /// regions) don't include the self-type, you must supply the + /// self-type here (the `param_ty` parameter). + pub fn predicates<'out, 's>( + &'s self, + tcx: TyCtxt<'tcx>, + param_ty: Ty<'tcx>, + // the output must live shorter than the duration of the borrow of self and 'tcx. + ) -> impl Iterator, Span)> + 'out + where + 'tcx: 'out, + 's: 'out, + { + // If it could be sized, and is, add the `Sized` predicate. + let sized_predicate = self.implicitly_sized.and_then(|span| { + tcx.lang_items().sized_trait().map(move |sized| { + let trait_ref = ty::Binder::dummy(ty::TraitRef { + def_id: sized, + substs: tcx.mk_substs_trait(param_ty, &[]), + }); + (trait_ref.without_const().to_predicate(tcx), span) + }) + }); + + let region_preds = self.region_bounds.iter().map(move |&(region_bound, span)| { + let pred = region_bound + .map_bound(|region_bound| ty::OutlivesPredicate(param_ty, region_bound)) + .to_predicate(tcx); + (pred, span) + }); + let trait_bounds = + self.trait_bounds.iter().map(move |&(bound_trait_ref, span, constness)| { + let predicate = bound_trait_ref.with_constness(constness).to_predicate(tcx); + (predicate, span) + }); + let projection_bounds = self + .projection_bounds + .iter() + .map(move |&(projection, span)| (projection.to_predicate(tcx), span)); + + sized_predicate.into_iter().chain(region_preds).chain(trait_bounds).chain(projection_bounds) + } +} -- cgit v1.2.3