Skip to content

Commit e3de992

Browse files
committed
Group ty::Predicate internals in one file
1 parent 413370b commit e3de992

File tree

9 files changed

+266
-296
lines changed

9 files changed

+266
-296
lines changed

compiler/rustc_middle/src/ty/bound_constness.rs

Lines changed: 0 additions & 34 deletions
This file was deleted.

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ pub mod walk;
5858
mod adt;
5959
mod alias_relation_direction;
6060
mod assoc;
61-
mod bound_constness;
6261
mod c_reader_cache_key;
6362
mod closure;
6463
mod closure_size_profile_data;
@@ -107,7 +106,6 @@ pub use self::alias_relation_direction::AliasRelationDirection;
107106
pub use self::assoc::*;
108107
pub use self::binding::BindingMode;
109108
pub use self::binding::BindingMode::*;
110-
pub use self::bound_constness::BoundConstness;
111109
pub use self::c_reader_cache_key::CReaderCacheKey;
112110
pub use self::closure::{
113111
is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo,
@@ -141,8 +139,8 @@ pub use self::param_env::{ParamEnv, ParamEnvAnd};
141139
pub use self::parameterized::ParameterizedOverTcx;
142140
pub use self::placeholder::{Placeholder, PlaceholderConst, PlaceholderRegion, PlaceholderType};
143141
pub use self::predicate::{
144-
Clause, CoercePredicate, CratePredicatesMap, InstantiatedPredicates, OutlivesPredicate,
145-
PolyCoercePredicate, PolyProjectionPredicate, PolyRegionOutlivesPredicate,
142+
BoundConstness, Clause, CoercePredicate, CratePredicatesMap, InstantiatedPredicates,
143+
OutlivesPredicate, PolyCoercePredicate, PolyProjectionPredicate, PolyRegionOutlivesPredicate,
146144
PolySubtypePredicate, PolyTraitPredicate, PolyTypeOutlivesPredicate, Predicate, PredicateKind,
147145
ProjectionPredicate, RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TraitPredicate,
148146
TypeOutlivesPredicate,

compiler/rustc_middle/src/ty/predicate.rs

Lines changed: 264 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,23 @@
1-
pub use crate::ty::context::{
2-
tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed,
3-
};
1+
use std::fmt;
2+
43
use rustc_data_structures::intern::Interned;
4+
use rustc_hir as hir;
55
use rustc_hir::def_id::DefId;
66
use rustc_type_ir::WithCachedTypeInfo;
77

88
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,
1112
};
1213

13-
mod clause;
14-
mod coerce_predicate;
1514
mod crate_predicates_map;
1615
mod instantiated_predicates;
17-
mod outlives_predicate;
18-
mod projection_predicate;
19-
mod subtype_predicate;
2016
mod to_predicate;
21-
mod trait_predicate;
2217

23-
pub use clause::Clause;
24-
pub use coerce_predicate::{CoercePredicate, PolyCoercePredicate};
2518
pub use crate_predicates_map::CratePredicatesMap;
2619
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};
3320
pub use to_predicate::ToPredicate;
34-
pub use trait_predicate::{PolyTraitPredicate, TraitPredicate};
3521

3622
/// Use this rather than `PredicateKind`, whenever possible.
3723
#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)]
@@ -96,6 +82,114 @@ pub enum PredicateKind<'tcx> {
9682
AliasRelate(Term<'tcx>, Term<'tcx>, AliasRelationDirection),
9783
}
9884

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+
99193
impl<'tcx> Predicate<'tcx> {
100194
/// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`.
101195
#[inline]
@@ -195,7 +289,7 @@ impl<'tcx> Predicate<'tcx> {
195289
pub fn subst_supertrait(
196290
self,
197291
tcx: TyCtxt<'tcx>,
198-
trait_ref: &ty::PolyTraitRef<'tcx>,
292+
trait_ref: &PolyTraitRef<'tcx>,
199293
) -> Predicate<'tcx> {
200294
// The interaction between HRTB and supertraits is not entirely
201295
// obvious. Let me walk you (and myself) through an example.
@@ -354,3 +448,152 @@ impl rustc_errors::IntoDiagnosticArg for Predicate<'_> {
354448
rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string()))
355449
}
356450
}
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

Comments
 (0)