|
| 1 | +use std::fmt; |
| 2 | + |
| 3 | +use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; |
| 4 | +use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; |
| 5 | + |
| 6 | +use crate::inherent::*; |
| 7 | +use crate::visit::TypeVisitableExt as _; |
| 8 | +use crate::Interner; |
| 9 | + |
| 10 | +/// A complete reference to a trait. These take numerous guises in syntax, |
| 11 | +/// but perhaps the most recognizable form is in a where-clause: |
| 12 | +/// ```ignore (illustrative) |
| 13 | +/// T: Foo<U> |
| 14 | +/// ``` |
| 15 | +/// This would be represented by a trait-reference where the `DefId` is the |
| 16 | +/// `DefId` for the trait `Foo` and the args define `T` as parameter 0, |
| 17 | +/// and `U` as parameter 1. |
| 18 | +/// |
| 19 | +/// Trait references also appear in object types like `Foo<U>`, but in |
| 20 | +/// that case the `Self` parameter is absent from the generic parameters. |
| 21 | +#[derive(derivative::Derivative)] |
| 22 | +#[derivative( |
| 23 | + Clone(bound = ""), |
| 24 | + Copy(bound = ""), |
| 25 | + Hash(bound = ""), |
| 26 | + PartialEq(bound = ""), |
| 27 | + Eq(bound = "") |
| 28 | +)] |
| 29 | +#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] |
| 30 | +#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] |
| 31 | +pub struct TraitRef<I: Interner> { |
| 32 | + pub def_id: I::DefId, |
| 33 | + pub args: I::GenericArgs, |
| 34 | + /// This field exists to prevent the creation of `TraitRef` without |
| 35 | + /// calling [`TraitRef::new`]. |
| 36 | + _use_trait_ref_new_instead: (), |
| 37 | +} |
| 38 | + |
| 39 | +impl<I: Interner> TraitRef<I> { |
| 40 | + pub fn new( |
| 41 | + interner: I, |
| 42 | + trait_def_id: I::DefId, |
| 43 | + args: impl IntoIterator<Item: Into<I::GenericArg>>, |
| 44 | + ) -> Self { |
| 45 | + let args = interner.check_and_mk_args(trait_def_id, args); |
| 46 | + Self { def_id: trait_def_id, args, _use_trait_ref_new_instead: () } |
| 47 | + } |
| 48 | + |
| 49 | + pub fn from_method(interner: I, trait_id: I::DefId, args: I::GenericArgs) -> TraitRef<I> { |
| 50 | + let generics = interner.generics_of(trait_id); |
| 51 | + TraitRef::new(interner, trait_id, args.into_iter().take(generics.count())) |
| 52 | + } |
| 53 | + |
| 54 | + /// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi` |
| 55 | + /// are the parameters defined on trait. |
| 56 | + pub fn identity(interner: I, def_id: I::DefId) -> TraitRef<I> { |
| 57 | + TraitRef::new(interner, def_id, I::GenericArgs::identity_for_item(interner, def_id)) |
| 58 | + } |
| 59 | + |
| 60 | + pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self { |
| 61 | + TraitRef::new( |
| 62 | + interner, |
| 63 | + self.def_id, |
| 64 | + [self_ty.into()].into_iter().chain(self.args.into_iter().skip(1)), |
| 65 | + ) |
| 66 | + } |
| 67 | + |
| 68 | + #[inline] |
| 69 | + pub fn self_ty(&self) -> I::Ty { |
| 70 | + self.args.type_at(0) |
| 71 | + } |
| 72 | +} |
| 73 | + |
| 74 | +#[derive(derivative::Derivative)] |
| 75 | +#[derivative( |
| 76 | + Clone(bound = ""), |
| 77 | + Copy(bound = ""), |
| 78 | + Hash(bound = ""), |
| 79 | + PartialEq(bound = ""), |
| 80 | + Eq(bound = "") |
| 81 | +)] |
| 82 | +#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] |
| 83 | +#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] |
| 84 | +pub struct TraitPredicate<I: Interner> { |
| 85 | + pub trait_ref: TraitRef<I>, |
| 86 | + |
| 87 | + /// If polarity is Positive: we are proving that the trait is implemented. |
| 88 | + /// |
| 89 | + /// If polarity is Negative: we are proving that a negative impl of this trait |
| 90 | + /// exists. (Note that coherence also checks whether negative impls of supertraits |
| 91 | + /// exist via a series of predicates.) |
| 92 | + /// |
| 93 | + /// If polarity is Reserved: that's a bug. |
| 94 | + pub polarity: PredicatePolarity, |
| 95 | +} |
| 96 | + |
| 97 | +impl<I: Interner> TraitPredicate<I> { |
| 98 | + pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self { |
| 99 | + Self { trait_ref: self.trait_ref.with_self_ty(interner, self_ty), polarity: self.polarity } |
| 100 | + } |
| 101 | + |
| 102 | + pub fn def_id(self) -> I::DefId { |
| 103 | + self.trait_ref.def_id |
| 104 | + } |
| 105 | + |
| 106 | + pub fn self_ty(self) -> I::Ty { |
| 107 | + self.trait_ref.self_ty() |
| 108 | + } |
| 109 | +} |
| 110 | + |
| 111 | +impl<I: Interner> fmt::Debug for TraitPredicate<I> { |
| 112 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 113 | + // FIXME(effects) printing? |
| 114 | + write!(f, "TraitPredicate({:?}, polarity:{:?})", self.trait_ref, self.polarity) |
| 115 | + } |
| 116 | +} |
| 117 | + |
| 118 | +/// Polarity for a trait predicate. May either be negative or positive. |
| 119 | +/// Distinguished from [`ImplPolarity`] since we never compute goals with |
| 120 | +/// "reservation" level. |
| 121 | +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] |
| 122 | +#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] |
| 123 | +pub enum PredicatePolarity { |
| 124 | + /// `Type: Trait` |
| 125 | + Positive, |
| 126 | + /// `Type: !Trait` |
| 127 | + Negative, |
| 128 | +} |
| 129 | + |
| 130 | +impl PredicatePolarity { |
| 131 | + /// Flips polarity by turning `Positive` into `Negative` and `Negative` into `Positive`. |
| 132 | + pub fn flip(&self) -> PredicatePolarity { |
| 133 | + match self { |
| 134 | + PredicatePolarity::Positive => PredicatePolarity::Negative, |
| 135 | + PredicatePolarity::Negative => PredicatePolarity::Positive, |
| 136 | + } |
| 137 | + } |
| 138 | +} |
| 139 | + |
| 140 | +impl fmt::Display for PredicatePolarity { |
| 141 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 142 | + match self { |
| 143 | + Self::Positive => f.write_str("positive"), |
| 144 | + Self::Negative => f.write_str("negative"), |
| 145 | + } |
| 146 | + } |
| 147 | +} |
| 148 | + |
| 149 | +/// An existential reference to a trait, where `Self` is erased. |
| 150 | +/// For example, the trait object `Trait<'a, 'b, X, Y>` is: |
| 151 | +/// ```ignore (illustrative) |
| 152 | +/// exists T. T: Trait<'a, 'b, X, Y> |
| 153 | +/// ``` |
| 154 | +/// The generic parameters don't include the erased `Self`, only trait |
| 155 | +/// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above). |
| 156 | +#[derive(derivative::Derivative)] |
| 157 | +#[derivative( |
| 158 | + Clone(bound = ""), |
| 159 | + Copy(bound = ""), |
| 160 | + Hash(bound = ""), |
| 161 | + PartialEq(bound = ""), |
| 162 | + Eq(bound = "") |
| 163 | +)] |
| 164 | +#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] |
| 165 | +#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] |
| 166 | +pub struct ExistentialTraitRef<I: Interner> { |
| 167 | + pub def_id: I::DefId, |
| 168 | + pub args: I::GenericArgs, |
| 169 | +} |
| 170 | + |
| 171 | +impl<I: Interner> ExistentialTraitRef<I> { |
| 172 | + pub fn erase_self_ty(interner: I, trait_ref: TraitRef<I>) -> ExistentialTraitRef<I> { |
| 173 | + // Assert there is a Self. |
| 174 | + trait_ref.args.type_at(0); |
| 175 | + |
| 176 | + ExistentialTraitRef { |
| 177 | + def_id: trait_ref.def_id, |
| 178 | + args: interner.mk_args(&trait_ref.args[1..]), |
| 179 | + } |
| 180 | + } |
| 181 | + |
| 182 | + /// Object types don't have a self type specified. Therefore, when |
| 183 | + /// we convert the principal trait-ref into a normal trait-ref, |
| 184 | + /// you must give *some* self type. A common choice is `mk_err()` |
| 185 | + /// or some placeholder type. |
| 186 | + pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> TraitRef<I> { |
| 187 | + // otherwise the escaping vars would be captured by the binder |
| 188 | + // debug_assert!(!self_ty.has_escaping_bound_vars()); |
| 189 | + |
| 190 | + TraitRef::new(interner, self.def_id, [self_ty.into()].into_iter().chain(self.args.into_iter())) |
| 191 | + } |
| 192 | +} |
| 193 | + |
| 194 | +/// A `ProjectionPredicate` for an `ExistentialTraitRef`. |
| 195 | +#[derive(derivative::Derivative)] |
| 196 | +#[derivative( |
| 197 | + Clone(bound = ""), |
| 198 | + Copy(bound = ""), |
| 199 | + Hash(bound = ""), |
| 200 | + PartialEq(bound = ""), |
| 201 | + Eq(bound = "") |
| 202 | +)] |
| 203 | +#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] |
| 204 | +#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] |
| 205 | +pub struct ExistentialProjection<I: Interner> { |
| 206 | + pub def_id: I::DefId, |
| 207 | + pub args: I::GenericArgs, |
| 208 | + pub term: I::Term, |
| 209 | +} |
| 210 | + |
| 211 | +impl<I: Interner> ExistentialProjection<I> { |
| 212 | + /// Extracts the underlying existential trait reference from this projection. |
| 213 | + /// For example, if this is a projection of `exists T. <T as Iterator>::Item == X`, |
| 214 | + /// then this function would return an `exists T. T: Iterator` existential trait |
| 215 | + /// reference. |
| 216 | + pub fn trait_ref(&self, tcx: I) -> ExistentialTraitRef<I> { |
| 217 | + let def_id = tcx.parent(self.def_id); |
| 218 | + let args_count = tcx.generics_of(def_id).count() - 1; |
| 219 | + let args = tcx.mk_args(&self.args[..args_count]); |
| 220 | + ExistentialTraitRef { def_id, args } |
| 221 | + } |
| 222 | + |
| 223 | + pub fn with_self_ty(&self, tcx: I, self_ty: I::Ty) -> ProjectionPredicate<I> { |
| 224 | + // otherwise the escaping regions would be captured by the binders |
| 225 | + debug_assert!(!self_ty.has_escaping_bound_vars()); |
| 226 | + |
| 227 | + ProjectionPredicate { |
| 228 | + projection_ty: I::AliasTy::new( |
| 229 | + tcx, |
| 230 | + self.def_id, |
| 231 | + [self_ty.into()].into_iter().chain(self.args), |
| 232 | + ), |
| 233 | + term: self.term, |
| 234 | + } |
| 235 | + } |
| 236 | + |
| 237 | + pub fn erase_self_ty(tcx: I, projection_predicate: ProjectionPredicate<I>) -> Self { |
| 238 | + // Assert there is a Self. |
| 239 | + projection_predicate.projection_ty.args().type_at(0); |
| 240 | + |
| 241 | + Self { |
| 242 | + def_id: projection_predicate.projection_ty.def_id(), |
| 243 | + args: tcx.mk_args(&projection_predicate.projection_ty.args()[1..]), |
| 244 | + term: projection_predicate.term, |
| 245 | + } |
| 246 | + } |
| 247 | +} |
| 248 | + |
| 249 | +/// This kind of predicate has no *direct* correspondent in the |
| 250 | +/// syntax, but it roughly corresponds to the syntactic forms: |
| 251 | +/// |
| 252 | +/// 1. `T: TraitRef<..., Item = Type>` |
| 253 | +/// 2. `<T as TraitRef<...>>::Item == Type` (NYI) |
| 254 | +/// |
| 255 | +/// In particular, form #1 is "desugared" to the combination of a |
| 256 | +/// normal trait predicate (`T: TraitRef<...>`) and one of these |
| 257 | +/// predicates. Form #2 is a broader form in that it also permits |
| 258 | +/// equality between arbitrary types. Processing an instance of |
| 259 | +/// Form #2 eventually yields one of these `ProjectionPredicate` |
| 260 | +/// instances to normalize the LHS. |
| 261 | +#[derive(derivative::Derivative)] |
| 262 | +#[derivative( |
| 263 | + Clone(bound = ""), |
| 264 | + Copy(bound = ""), |
| 265 | + Hash(bound = ""), |
| 266 | + PartialEq(bound = ""), |
| 267 | + Eq(bound = "") |
| 268 | +)] |
| 269 | +#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] |
| 270 | +#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] |
| 271 | +pub struct ProjectionPredicate<I: Interner> { |
| 272 | + pub projection_ty: I::AliasTy, |
| 273 | + pub term: I::Term, |
| 274 | +} |
| 275 | + |
| 276 | +impl<I: Interner> ProjectionPredicate<I> { |
| 277 | + pub fn self_ty(self) -> I::Ty { |
| 278 | + self.projection_ty.self_ty() |
| 279 | + } |
| 280 | + |
| 281 | + pub fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> ProjectionPredicate<I> { |
| 282 | + Self { projection_ty: self.projection_ty.with_self_ty(tcx, self_ty), ..self } |
| 283 | + } |
| 284 | + |
| 285 | + pub fn trait_def_id(self, tcx: I) -> I::DefId { |
| 286 | + self.projection_ty.trait_def_id(tcx) |
| 287 | + } |
| 288 | + |
| 289 | + pub fn def_id(self) -> I::DefId { |
| 290 | + self.projection_ty.def_id() |
| 291 | + } |
| 292 | +} |
| 293 | + |
| 294 | +impl<I: Interner> fmt::Debug for ProjectionPredicate<I> { |
| 295 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 296 | + write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_ty, self.term) |
| 297 | + } |
| 298 | +} |
0 commit comments