Skip to content

Commit df13e1b

Browse files
committed
add new region constraint repr
1 parent b9daf6b commit df13e1b

1 file changed

Lines changed: 160 additions & 0 deletions

File tree

compiler/rustc_type_ir/src/region_constraint.rs

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,166 @@ impl<I: Interner> Assumptions<I> {
5151
}
5252
}
5353

54+
#[derive_where(Clone, Hash, PartialEq, Debug; I: Interner)]
55+
pub enum RegionConstraint<I: Interner> {
56+
Ambiguity,
57+
RegionOutlives(I::Region, I::Region),
58+
AliasTyOutlivesFromEnv(Binder<I, (AliasTy<I>, I::Region)>),
59+
/// This is an `I::Ty` for two reasons:
60+
/// 1. We need the type visitable impl to be able to `visit_ty` on this so canonicalization
61+
/// knows about the placeholder
62+
/// 2. When exiting the trait solver there may be placeholder outlives corresponding to params
63+
/// from the root universe. These need to be changed from a `Placeholder` to the original
64+
/// `Param`.
65+
PlaceholderTyOutlives(I::Ty, I::Region),
66+
67+
And(Box<[RegionConstraint<I>]>),
68+
Or(Box<[RegionConstraint<I>]>),
69+
}
70+
71+
#[cfg(feature = "nightly")]
72+
// This is not a derived impl because a perfect derive leads to cycle errors which
73+
// means the trait is never actually implemented but the compiler doesn't tell you
74+
// that so if you get a *WEIRD* error where its just telling you random types don't
75+
// implement HashStable.... it's because of that
76+
impl<CTX, I: Interner> HashStable<CTX> for RegionConstraint<I>
77+
where
78+
I::Region: HashStable<CTX>,
79+
AliasTy<I>: HashStable<CTX>,
80+
I::Ty: HashStable<CTX>,
81+
I::BoundVarKinds: HashStable<CTX>,
82+
{
83+
#[inline]
84+
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
85+
use RegionConstraint::*;
86+
87+
std::mem::discriminant(self).hash_stable(hcx, hasher);
88+
match self {
89+
Ambiguity => (),
90+
RegionOutlives(a, b) => {
91+
a.hash_stable(hcx, hasher);
92+
b.hash_stable(hcx, hasher);
93+
}
94+
AliasTyOutlivesFromEnv(outlives) => {
95+
outlives.hash_stable(hcx, hasher);
96+
}
97+
PlaceholderTyOutlives(a, b) => {
98+
a.hash_stable(hcx, hasher);
99+
b.hash_stable(hcx, hasher);
100+
}
101+
And(and) => {
102+
for a in and.iter() {
103+
a.hash_stable(hcx, hasher);
104+
}
105+
}
106+
Or(or) => {
107+
for a in or.iter() {
108+
a.hash_stable(hcx, hasher);
109+
}
110+
}
111+
}
112+
}
113+
}
114+
115+
impl<I: Interner> TypeFoldable<I> for RegionConstraint<I> {
116+
fn try_fold_with<F: FallibleTypeFolder<I>>(self, f: &mut F) -> Result<Self, F::Error> {
117+
use RegionConstraint::*;
118+
Ok(match self {
119+
Ambiguity => self,
120+
RegionOutlives(a, b) => RegionOutlives(a.try_fold_with(f)?, b.try_fold_with(f)?),
121+
AliasTyOutlivesFromEnv(outlives) => AliasTyOutlivesFromEnv(outlives.try_fold_with(f)?),
122+
PlaceholderTyOutlives(a, b) => {
123+
PlaceholderTyOutlives(a.try_fold_with(f)?, b.try_fold_with(f)?)
124+
}
125+
And(and) => {
126+
let mut new_and = Vec::new();
127+
for a in and {
128+
new_and.push(a.try_fold_with(f)?);
129+
}
130+
And(new_and.into_boxed_slice())
131+
}
132+
Or(or) => {
133+
let mut new_or = Vec::new();
134+
for a in or {
135+
new_or.push(a.try_fold_with(f)?);
136+
}
137+
Or(new_or.into_boxed_slice())
138+
}
139+
})
140+
}
141+
142+
fn fold_with<F: TypeFolder<I>>(self, f: &mut F) -> Self {
143+
use RegionConstraint::*;
144+
match self {
145+
Ambiguity => self,
146+
RegionOutlives(a, b) => RegionOutlives(a.fold_with(f), b.fold_with(f)),
147+
AliasTyOutlivesFromEnv(outlives) => AliasTyOutlivesFromEnv(outlives.fold_with(f)),
148+
PlaceholderTyOutlives(a, b) => PlaceholderTyOutlives(a.fold_with(f), b.fold_with(f)),
149+
And(and) => {
150+
let mut new_and = Vec::new();
151+
for a in and {
152+
new_and.push(a.fold_with(f));
153+
}
154+
And(new_and.into_boxed_slice())
155+
}
156+
Or(or) => {
157+
let mut new_or = Vec::new();
158+
for a in or {
159+
new_or.push(a.fold_with(f));
160+
}
161+
Or(new_or.into_boxed_slice())
162+
}
163+
}
164+
}
165+
}
166+
167+
impl<I: Interner> TypeVisitable<I> for RegionConstraint<I> {
168+
fn visit_with<F: TypeVisitor<I>>(&self, f: &mut F) -> F::Result {
169+
use core::ops::ControlFlow::*;
170+
171+
use RegionConstraint::*;
172+
173+
match self {
174+
Ambiguity => (),
175+
RegionOutlives(a, b) => {
176+
if let b @ Break(_) = a.visit_with(f).branch() {
177+
return F::Result::from_branch(b);
178+
};
179+
if let b @ Break(_) = b.visit_with(f).branch() {
180+
return F::Result::from_branch(b);
181+
};
182+
}
183+
AliasTyOutlivesFromEnv(outlives) => {
184+
return outlives.visit_with(f);
185+
}
186+
PlaceholderTyOutlives(a, b) => {
187+
if let b @ Break(_) = a.visit_with(f).branch() {
188+
return F::Result::from_branch(b);
189+
};
190+
if let b @ Break(_) = b.visit_with(f).branch() {
191+
return F::Result::from_branch(b);
192+
};
193+
}
194+
And(and) => {
195+
for a in and {
196+
if let b @ Break(_) = a.visit_with(f).branch() {
197+
return F::Result::from_branch(b);
198+
};
199+
}
200+
}
201+
Or(or) => {
202+
for a in or {
203+
if let b @ Break(_) = a.visit_with(f).branch() {
204+
return F::Result::from_branch(b);
205+
};
206+
}
207+
}
208+
};
209+
210+
F::Result::output()
211+
}
212+
}
213+
54214
pub fn max_universe<Infcx: InferCtxtLike<Interner = I>, I: Interner, T: TypeVisitable<I>>(
55215
infcx: &Infcx,
56216
t: T,

0 commit comments

Comments
 (0)