|
1 |
| -pub use crate::ty::context::{ |
2 |
| - tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, |
3 |
| -}; |
| 1 | +use std::fmt; |
| 2 | + |
4 | 3 | use rustc_data_structures::intern::Interned;
|
| 4 | +use rustc_hir as hir; |
5 | 5 | use rustc_hir::def_id::DefId;
|
6 | 6 | use rustc_type_ir::WithCachedTypeInfo;
|
7 | 7 |
|
8 | 8 | use crate::ty::{
|
9 |
| - self, AliasRelationDirection, Binder, BoundConstness, ClosureKind, Const, DebruijnIndex, |
10 |
| - EarlyBinder, GenericArg, SubstsRef, Term, Ty, TypeFlags, |
| 9 | + self, AliasRelationDirection, AliasTy, Binder, ClosureKind, Const, DebruijnIndex, EarlyBinder, |
| 10 | + GenericArg, ImplPolarity, ParamEnv, PolyTraitRef, SubstsRef, Term, TraitRef, Ty, TyCtxt, |
| 11 | + TypeFlags, |
11 | 12 | };
|
12 | 13 |
|
13 |
| -mod clause; |
14 |
| -mod coerce_predicate; |
15 | 14 | mod crate_predicates_map;
|
16 | 15 | mod instantiated_predicates;
|
17 |
| -mod outlives_predicate; |
18 |
| -mod projection_predicate; |
19 |
| -mod subtype_predicate; |
20 | 16 | mod to_predicate;
|
21 |
| -mod trait_predicate; |
22 | 17 |
|
23 |
| -pub use clause::Clause; |
24 |
| -pub use coerce_predicate::{CoercePredicate, PolyCoercePredicate}; |
25 | 18 | pub use crate_predicates_map::CratePredicatesMap;
|
26 | 19 | pub use instantiated_predicates::InstantiatedPredicates;
|
27 |
| -pub use outlives_predicate::{ |
28 |
| - OutlivesPredicate, PolyRegionOutlivesPredicate, PolyTypeOutlivesPredicate, |
29 |
| - RegionOutlivesPredicate, TypeOutlivesPredicate, |
30 |
| -}; |
31 |
| -pub use projection_predicate::{PolyProjectionPredicate, ProjectionPredicate}; |
32 |
| -pub use subtype_predicate::{PolySubtypePredicate, SubtypePredicate}; |
33 | 20 | pub use to_predicate::ToPredicate;
|
34 |
| -pub use trait_predicate::{PolyTraitPredicate, TraitPredicate}; |
35 | 21 |
|
36 | 22 | /// Use this rather than `PredicateKind`, whenever possible.
|
37 | 23 | #[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)]
|
@@ -96,6 +82,114 @@ pub enum PredicateKind<'tcx> {
|
96 | 82 | AliasRelate(Term<'tcx>, Term<'tcx>, AliasRelationDirection),
|
97 | 83 | }
|
98 | 84 |
|
| 85 | +/// A clause is something that can appear in where bounds or be inferred |
| 86 | +/// by implied bounds. |
| 87 | +#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] |
| 88 | +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] |
| 89 | +pub enum Clause<'tcx> { |
| 90 | + /// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be |
| 91 | + /// the `Self` type of the trait reference and `A`, `B`, and `C` |
| 92 | + /// would be the type parameters. |
| 93 | + Trait(TraitPredicate<'tcx>), |
| 94 | + |
| 95 | + /// `where 'a: 'b` |
| 96 | + RegionOutlives(RegionOutlivesPredicate<'tcx>), |
| 97 | + |
| 98 | + /// `where T: 'a` |
| 99 | + TypeOutlives(TypeOutlivesPredicate<'tcx>), |
| 100 | + |
| 101 | + /// `where <T as TraitRef>::Name == X`, approximately. |
| 102 | + /// See the `ProjectionPredicate` struct for details. |
| 103 | + Projection(ProjectionPredicate<'tcx>), |
| 104 | + |
| 105 | + /// Ensures that a const generic argument to a parameter `const N: u8` |
| 106 | + /// is of type `u8`. |
| 107 | + ConstArgHasType(Const<'tcx>, Ty<'tcx>), |
| 108 | +} |
| 109 | + |
| 110 | +pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>; |
| 111 | + |
| 112 | +/// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates |
| 113 | +/// whether the `a` type is the type that we should label as "expected" when |
| 114 | +/// presenting user diagnostics. |
| 115 | +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] |
| 116 | +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] |
| 117 | +pub struct SubtypePredicate<'tcx> { |
| 118 | + pub a_is_expected: bool, |
| 119 | + pub a: Ty<'tcx>, |
| 120 | + pub b: Ty<'tcx>, |
| 121 | +} |
| 122 | + |
| 123 | +pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>; |
| 124 | + |
| 125 | +/// Encodes that we have to coerce *from* the `a` type to the `b` type. |
| 126 | +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] |
| 127 | +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] |
| 128 | +pub struct CoercePredicate<'tcx> { |
| 129 | + pub a: Ty<'tcx>, |
| 130 | + pub b: Ty<'tcx>, |
| 131 | +} |
| 132 | + |
| 133 | +pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>; |
| 134 | + |
| 135 | +#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] |
| 136 | +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] |
| 137 | +pub struct TraitPredicate<'tcx> { |
| 138 | + pub trait_ref: TraitRef<'tcx>, |
| 139 | + |
| 140 | + pub constness: BoundConstness, |
| 141 | + |
| 142 | + /// If polarity is Positive: we are proving that the trait is implemented. |
| 143 | + /// |
| 144 | + /// If polarity is Negative: we are proving that a negative impl of this trait |
| 145 | + /// exists. (Note that coherence also checks whether negative impls of supertraits |
| 146 | + /// exist via a series of predicates.) |
| 147 | + /// |
| 148 | + /// If polarity is Reserved: that's a bug. |
| 149 | + pub polarity: ImplPolarity, |
| 150 | +} |
| 151 | + |
| 152 | +pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>; |
| 153 | +pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>; |
| 154 | +pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>; |
| 155 | +pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>; |
| 156 | + |
| 157 | +/// `A: B` |
| 158 | +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] |
| 159 | +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] |
| 160 | +pub struct OutlivesPredicate<A, B>(pub A, pub B); |
| 161 | + |
| 162 | +pub type PolyProjectionPredicate<'tcx> = ty::Binder<'tcx, ProjectionPredicate<'tcx>>; |
| 163 | + |
| 164 | +/// This kind of predicate has no *direct* correspondent in the |
| 165 | +/// syntax, but it roughly corresponds to the syntactic forms: |
| 166 | +/// |
| 167 | +/// 1. `T: TraitRef<..., Item = Type>` |
| 168 | +/// 2. `<T as TraitRef<...>>::Item == Type` (NYI) |
| 169 | +/// |
| 170 | +/// In particular, form #1 is "desugared" to the combination of a |
| 171 | +/// normal trait predicate (`T: TraitRef<...>`) and one of these |
| 172 | +/// predicates. Form #2 is a broader form in that it also permits |
| 173 | +/// equality between arbitrary types. Processing an instance of |
| 174 | +/// Form #2 eventually yields one of these `ProjectionPredicate` |
| 175 | +/// instances to normalize the LHS. |
| 176 | +#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] |
| 177 | +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] |
| 178 | +pub struct ProjectionPredicate<'tcx> { |
| 179 | + pub projection_ty: AliasTy<'tcx>, |
| 180 | + pub term: Term<'tcx>, |
| 181 | +} |
| 182 | + |
| 183 | +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)] |
| 184 | +pub enum BoundConstness { |
| 185 | + /// `T: Trait` |
| 186 | + NotConst, |
| 187 | + /// `T: ~const Trait` |
| 188 | + /// |
| 189 | + /// Requires resolving to const only when we are in a const context. |
| 190 | + ConstIfConst, |
| 191 | +} |
| 192 | + |
99 | 193 | impl<'tcx> Predicate<'tcx> {
|
100 | 194 | /// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`.
|
101 | 195 | #[inline]
|
@@ -195,7 +289,7 @@ impl<'tcx> Predicate<'tcx> {
|
195 | 289 | pub fn subst_supertrait(
|
196 | 290 | self,
|
197 | 291 | tcx: TyCtxt<'tcx>,
|
198 |
| - trait_ref: &ty::PolyTraitRef<'tcx>, |
| 292 | + trait_ref: &PolyTraitRef<'tcx>, |
199 | 293 | ) -> Predicate<'tcx> {
|
200 | 294 | // The interaction between HRTB and supertraits is not entirely
|
201 | 295 | // obvious. Let me walk you (and myself) through an example.
|
@@ -354,3 +448,152 @@ impl rustc_errors::IntoDiagnosticArg for Predicate<'_> {
|
354 | 448 | rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string()))
|
355 | 449 | }
|
356 | 450 | }
|
| 451 | + |
| 452 | +impl<'tcx> TraitPredicate<'tcx> { |
| 453 | + pub fn remap_constness(&mut self, param_env: &mut ParamEnv<'tcx>) { |
| 454 | + *param_env = param_env.with_constness(self.constness.and(param_env.constness())) |
| 455 | + } |
| 456 | + |
| 457 | + /// Remap the constness of this predicate before emitting it for diagnostics. |
| 458 | + pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) { |
| 459 | + // this is different to `remap_constness` that callees want to print this predicate |
| 460 | + // in case of selection errors. `T: ~const Drop` bounds cannot end up here when the |
| 461 | + // param_env is not const because it is always satisfied in non-const contexts. |
| 462 | + if let hir::Constness::NotConst = param_env.constness() { |
| 463 | + self.constness = ty::BoundConstness::NotConst; |
| 464 | + } |
| 465 | + } |
| 466 | + |
| 467 | + pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { |
| 468 | + Self { trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), ..self } |
| 469 | + } |
| 470 | + |
| 471 | + pub fn def_id(self) -> DefId { |
| 472 | + self.trait_ref.def_id |
| 473 | + } |
| 474 | + |
| 475 | + pub fn self_ty(self) -> Ty<'tcx> { |
| 476 | + self.trait_ref.self_ty() |
| 477 | + } |
| 478 | + |
| 479 | + #[inline] |
| 480 | + pub fn is_const_if_const(self) -> bool { |
| 481 | + self.constness == BoundConstness::ConstIfConst |
| 482 | + } |
| 483 | + |
| 484 | + pub fn is_constness_satisfied_by(self, constness: hir::Constness) -> bool { |
| 485 | + match (self.constness, constness) { |
| 486 | + (BoundConstness::NotConst, _) |
| 487 | + | (BoundConstness::ConstIfConst, hir::Constness::Const) => true, |
| 488 | + (BoundConstness::ConstIfConst, hir::Constness::NotConst) => false, |
| 489 | + } |
| 490 | + } |
| 491 | + |
| 492 | + pub fn without_const(mut self) -> Self { |
| 493 | + self.constness = BoundConstness::NotConst; |
| 494 | + self |
| 495 | + } |
| 496 | +} |
| 497 | + |
| 498 | +impl<'tcx> PolyTraitPredicate<'tcx> { |
| 499 | + pub fn def_id(self) -> DefId { |
| 500 | + // Ok to skip binder since trait `DefId` does not care about regions. |
| 501 | + self.skip_binder().def_id() |
| 502 | + } |
| 503 | + |
| 504 | + pub fn self_ty(self) -> ty::Binder<'tcx, Ty<'tcx>> { |
| 505 | + self.map_bound(|trait_ref| trait_ref.self_ty()) |
| 506 | + } |
| 507 | + |
| 508 | + /// Remap the constness of this predicate before emitting it for diagnostics. |
| 509 | + pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) { |
| 510 | + *self = self.map_bound(|mut p| { |
| 511 | + p.remap_constness_diag(param_env); |
| 512 | + p |
| 513 | + }); |
| 514 | + } |
| 515 | + |
| 516 | + #[inline] |
| 517 | + pub fn is_const_if_const(self) -> bool { |
| 518 | + self.skip_binder().is_const_if_const() |
| 519 | + } |
| 520 | + |
| 521 | + #[inline] |
| 522 | + pub fn polarity(self) -> ImplPolarity { |
| 523 | + self.skip_binder().polarity |
| 524 | + } |
| 525 | +} |
| 526 | + |
| 527 | +impl<'tcx> ProjectionPredicate<'tcx> { |
| 528 | + pub fn self_ty(self) -> Ty<'tcx> { |
| 529 | + self.projection_ty.self_ty() |
| 530 | + } |
| 531 | + |
| 532 | + pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ProjectionPredicate<'tcx> { |
| 533 | + Self { projection_ty: self.projection_ty.with_self_ty(tcx, self_ty), ..self } |
| 534 | + } |
| 535 | + |
| 536 | + pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { |
| 537 | + self.projection_ty.trait_def_id(tcx) |
| 538 | + } |
| 539 | + |
| 540 | + pub fn def_id(self) -> DefId { |
| 541 | + self.projection_ty.def_id |
| 542 | + } |
| 543 | +} |
| 544 | + |
| 545 | +impl<'tcx> PolyProjectionPredicate<'tcx> { |
| 546 | + /// Returns the `DefId` of the trait of the associated item being projected. |
| 547 | + #[inline] |
| 548 | + pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId { |
| 549 | + self.skip_binder().projection_ty.trait_def_id(tcx) |
| 550 | + } |
| 551 | + |
| 552 | + /// Get the [PolyTraitRef] required for this projection to be well formed. |
| 553 | + /// Note that for generic associated types the predicates of the associated |
| 554 | + /// type also need to be checked. |
| 555 | + #[inline] |
| 556 | + pub fn required_poly_trait_ref(&self, tcx: TyCtxt<'tcx>) -> PolyTraitRef<'tcx> { |
| 557 | + // Note: unlike with `TraitRef::to_poly_trait_ref()`, |
| 558 | + // `self.0.trait_ref` is permitted to have escaping regions. |
| 559 | + // This is because here `self` has a `Binder` and so does our |
| 560 | + // return value, so we are preserving the number of binding |
| 561 | + // levels. |
| 562 | + self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx)) |
| 563 | + } |
| 564 | + |
| 565 | + pub fn term(&self) -> ty::Binder<'tcx, Term<'tcx>> { |
| 566 | + self.map_bound(|predicate| predicate.term) |
| 567 | + } |
| 568 | + |
| 569 | + /// The `DefId` of the `TraitItem` for the associated type. |
| 570 | + /// |
| 571 | + /// Note that this is not the `DefId` of the `TraitRef` containing this |
| 572 | + /// associated type, which is in `tcx.associated_item(projection_def_id()).container`. |
| 573 | + pub fn projection_def_id(&self) -> DefId { |
| 574 | + // Ok to skip binder since trait `DefId` does not care about regions. |
| 575 | + self.skip_binder().projection_ty.def_id |
| 576 | + } |
| 577 | +} |
| 578 | + |
| 579 | +impl BoundConstness { |
| 580 | + /// Reduce `self` and `constness` to two possible combined states instead of four. |
| 581 | + pub fn and(&mut self, constness: hir::Constness) -> hir::Constness { |
| 582 | + match (constness, self) { |
| 583 | + (hir::Constness::Const, BoundConstness::ConstIfConst) => hir::Constness::Const, |
| 584 | + (_, this) => { |
| 585 | + *this = BoundConstness::NotConst; |
| 586 | + hir::Constness::NotConst |
| 587 | + } |
| 588 | + } |
| 589 | + } |
| 590 | +} |
| 591 | + |
| 592 | +impl fmt::Display for BoundConstness { |
| 593 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 594 | + match self { |
| 595 | + Self::NotConst => f.write_str("normal"), |
| 596 | + Self::ConstIfConst => f.write_str("`~const`"), |
| 597 | + } |
| 598 | + } |
| 599 | +} |
0 commit comments