1use derive_where::derive_where;
4use indexmap::IndexSet;
5#[cfg(feature = "nightly")]
6use rustc_data_structures::stable_hash::{StableHash, StableHashCtxt, StableHasher};
7#[cfg(feature = "nightly")]
8use rustc_data_structures::transitive_relation::{TransitiveRelation, TransitiveRelationBuilder};
9use tracing::{debug, instrument};
10
11#[cfg(not(feature = "nightly"))]
13#[derive(Default, Clone, Debug)]
14pub struct TransitiveRelation<T>(T);
15#[cfg(not(feature = "nightly"))]
16impl<T> TransitiveRelation<T> {
17 pub fn reachable_from(&self, _data: T) -> Vec<T> {
18 unreachable!("-Zassumptions-on-binders is not supported for r-a")
19 }
20
21 pub fn base_edges(&self) -> impl Iterator<Item = (T, T)> {
22 unreachable!("-Zassumptions-on-binders is not supported for r-a");
23
24 #[allow(unreachable_code)]
25 [].into_iter()
26 }
27}
28#[derive(Clone, Debug)]
29#[cfg(not(feature = "nightly"))]
30pub struct TransitiveRelationBuilder<T>(T);
31#[cfg(not(feature = "nightly"))]
32impl<T> TransitiveRelationBuilder<T> {
33 pub fn freeze(self) -> TransitiveRelation<T> {
34 unreachable!("-Zassumptions-on-binders is not supported for r-a")
35 }
36
37 pub fn add(&mut self, _: T, _: T) {
38 unreachable!("-Zassumptions-on-binders is not supported for r-a")
39 }
40}
41#[cfg(not(feature = "nightly"))]
42impl<T> Default for TransitiveRelationBuilder<T> {
43 fn default() -> Self {
44 unreachable!("-Zassumptions-on-binders is not supported for r-a")
45 }
46}
47
48use crate::data_structures::IndexMap;
49use crate::fold::TypeSuperFoldable;
50use crate::inherent::*;
51use crate::relate::{Relate, RelateResult, TypeRelation, VarianceDiagInfo};
52use crate::{
53 AliasTy, Binder, BoundRegion, BoundVar, BoundVariableKind, DebruijnIndex, FallibleTypeFolder,
54 GenericTypeVisitable, InferCtxtLike, Interner, IsRigid, OutlivesClause, Region, RegionKind,
55 TyKind, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor, TypingMode, UniverseIndex,
56 Variance, VisitorResult, max_universe, set_aliases_to_non_rigid, try_visit,
57 walk_visitable_list,
58};
59
60#[automatically_derived]
impl<I: Interner> ::core::fmt::Debug for Assumptions<I> where I: Interner {
fn fmt(&self, __f: &mut ::core::fmt::Formatter<'_>)
-> ::core::fmt::Result {
match self {
Assumptions {
type_outlives: ref __field_type_outlives,
region_outlives: ref __field_region_outlives,
inverse_region_outlives: ref __field_inverse_region_outlives }
=> {
let mut __builder =
::core::fmt::Formatter::debug_struct(__f, "Assumptions");
::core::fmt::DebugStruct::field(&mut __builder,
"type_outlives", __field_type_outlives);
::core::fmt::DebugStruct::field(&mut __builder,
"region_outlives", __field_region_outlives);
::core::fmt::DebugStruct::field(&mut __builder,
"inverse_region_outlives", __field_inverse_region_outlives);
::core::fmt::DebugStruct::finish(&mut __builder)
}
}
}
}#[derive_where(Clone, Debug; I: Interner)]
61pub struct Assumptions<I: Interner> {
62 pub type_outlives: Vec<Binder<I, OutlivesClause<I, I::Ty>>>,
63 pub region_outlives: TransitiveRelation<Region<I>>,
64 pub inverse_region_outlives: TransitiveRelation<Region<I>>,
65}
66
67impl<I: Interner> Assumptions<I> {
68 pub fn empty() -> Self {
69 Self {
70 type_outlives: Vec::new(),
71 region_outlives: TransitiveRelationBuilder::default().freeze(),
72 inverse_region_outlives: TransitiveRelationBuilder::default().freeze(),
73 }
74 }
75
76 pub fn new(
77 type_outlives: Vec<Binder<I, OutlivesClause<I, I::Ty>>>,
78 region_outlives: TransitiveRelation<Region<I>>,
79 ) -> Self {
80 Self {
81 inverse_region_outlives: {
82 let mut builder = TransitiveRelationBuilder::default();
83 for (r1, r2) in region_outlives.base_edges() {
84 builder.add(r2, r1);
85 }
86 builder.freeze()
87 },
88 type_outlives,
89 region_outlives,
90 }
91 }
92}
93
94#[automatically_derived]
impl<I: Interner, S> ::core::fmt::Debug for RegionConstraint<I, S> where
I: Interner, S: ::core::fmt::Debug {
fn fmt(&self, __f: &mut ::core::fmt::Formatter<'_>)
-> ::core::fmt::Result {
match self {
RegionConstraint::Ambiguity(ref __field_0) => {
let mut __builder =
::core::fmt::Formatter::debug_tuple(__f, "Ambiguity");
::core::fmt::DebugTuple::field(&mut __builder, __field_0);
::core::fmt::DebugTuple::finish(&mut __builder)
}
RegionConstraint::RegionOutlives(ref __field_0, ref __field_1,
ref __field_2) => {
let mut __builder =
::core::fmt::Formatter::debug_tuple(__f, "RegionOutlives");
::core::fmt::DebugTuple::field(&mut __builder, __field_0);
::core::fmt::DebugTuple::field(&mut __builder, __field_1);
::core::fmt::DebugTuple::field(&mut __builder, __field_2);
::core::fmt::DebugTuple::finish(&mut __builder)
}
RegionConstraint::AliasTyOutlivesViaEnv(ref __field_0,
ref __field_1) => {
let mut __builder =
::core::fmt::Formatter::debug_tuple(__f,
"AliasTyOutlivesViaEnv");
::core::fmt::DebugTuple::field(&mut __builder, __field_0);
::core::fmt::DebugTuple::field(&mut __builder, __field_1);
::core::fmt::DebugTuple::finish(&mut __builder)
}
RegionConstraint::PlaceholderTyOutlives(ref __field_0,
ref __field_1, ref __field_2) => {
let mut __builder =
::core::fmt::Formatter::debug_tuple(__f,
"PlaceholderTyOutlives");
::core::fmt::DebugTuple::field(&mut __builder, __field_0);
::core::fmt::DebugTuple::field(&mut __builder, __field_1);
::core::fmt::DebugTuple::field(&mut __builder, __field_2);
::core::fmt::DebugTuple::finish(&mut __builder)
}
RegionConstraint::And(ref __field_0) => {
let mut __builder =
::core::fmt::Formatter::debug_tuple(__f, "And");
::core::fmt::DebugTuple::field(&mut __builder, __field_0);
::core::fmt::DebugTuple::finish(&mut __builder)
}
RegionConstraint::Or(ref __field_0) => {
let mut __builder =
::core::fmt::Formatter::debug_tuple(__f, "Or");
::core::fmt::DebugTuple::field(&mut __builder, __field_0);
::core::fmt::DebugTuple::finish(&mut __builder)
}
}
}
}#[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, S)]
95#[derive(GenericTypeVisitable)]
96pub enum RegionConstraint<I: Interner, S = ()> {
97 Ambiguity(S),
98 RegionOutlives(Region<I>, Region<I>, S),
99 AliasTyOutlivesViaEnv(Binder<I, (AliasTy<I>, Region<I>)>, S),
109 PlaceholderTyOutlives(I::Ty, Region<I>, S),
119
120 And(Box<[RegionConstraint<I, S>]>),
121 Or(Box<[RegionConstraint<I, S>]>),
122}
123
124pub type SpannedRegionConstraint<I> = RegionConstraint<I, <I as Interner>::Span>;
130
131#[cfg(feature = "nightly")]
134impl<I: Interner> StableHash for RegionConstraint<I>
135where
136 Region<I>: StableHash,
137 I::Ty: StableHash,
138 I::GenericArgs: StableHash,
139 I::TraitAssocTyId: StableHash,
140 I::InherentAssocTyId: StableHash,
141 I::OpaqueTyId: StableHash,
142 I::FreeTyAliasId: StableHash,
143 I::BoundVarKinds: StableHash,
144{
145 #[inline]
146 fn stable_hash<CTX: StableHashCtxt>(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
147 use RegionConstraint::*;
148
149 std::mem::discriminant(self).stable_hash(hcx, hasher);
150 match self {
151 Ambiguity(_) => (),
152 RegionOutlives(a, b, _) => {
153 a.stable_hash(hcx, hasher);
154 b.stable_hash(hcx, hasher);
155 }
156 AliasTyOutlivesViaEnv(outlives, _) => {
157 outlives.stable_hash(hcx, hasher);
158 }
159 PlaceholderTyOutlives(a, b, _) => {
160 a.stable_hash(hcx, hasher);
161 b.stable_hash(hcx, hasher);
162 }
163 And(and) => {
164 for a in and.iter() {
165 a.stable_hash(hcx, hasher);
166 }
167 }
168 Or(or) => {
169 for a in or.iter() {
170 a.stable_hash(hcx, hasher);
171 }
172 }
173 }
174 }
175}
176
177impl<I: Interner, S: Clone + std::fmt::Debug> TypeFoldable<I> for RegionConstraint<I, S> {
178 fn try_fold_with<F: FallibleTypeFolder<I>>(self, f: &mut F) -> Result<Self, F::Error> {
179 use RegionConstraint::*;
180 Ok(match self {
181 Ambiguity(_) => self,
182 RegionOutlives(a, b, span) => {
183 RegionOutlives(a.try_fold_with(f)?, b.try_fold_with(f)?, span)
184 }
185 AliasTyOutlivesViaEnv(outlives, span) => {
186 AliasTyOutlivesViaEnv(outlives.try_fold_with(f)?, span)
187 }
188 PlaceholderTyOutlives(a, b, span) => {
189 PlaceholderTyOutlives(a.try_fold_with(f)?, b.try_fold_with(f)?, span)
190 }
191 And(and) => {
192 let mut new_and = Vec::new();
193 for a in and {
194 new_and.push(a.try_fold_with(f)?);
195 }
196 And(new_and.into_boxed_slice())
197 }
198 Or(or) => {
199 let mut new_or = Vec::new();
200 for a in or {
201 new_or.push(a.try_fold_with(f)?);
202 }
203 Or(new_or.into_boxed_slice())
204 }
205 })
206 }
207
208 fn fold_with<F: TypeFolder<I>>(self, f: &mut F) -> Self {
209 use RegionConstraint::*;
210 match self {
211 Ambiguity(_) => self,
212 RegionOutlives(a, b, span) => RegionOutlives(a.fold_with(f), b.fold_with(f), span),
213 AliasTyOutlivesViaEnv(outlives, span) => {
214 AliasTyOutlivesViaEnv(outlives.fold_with(f), span)
215 }
216 PlaceholderTyOutlives(a, b, span) => {
217 PlaceholderTyOutlives(a.fold_with(f), b.fold_with(f), span)
218 }
219 And(and) => {
220 let mut new_and = Vec::new();
221 for a in and {
222 new_and.push(a.fold_with(f));
223 }
224 And(new_and.into_boxed_slice())
225 }
226 Or(or) => {
227 let mut new_or = Vec::new();
228 for a in or {
229 new_or.push(a.fold_with(f));
230 }
231 Or(new_or.into_boxed_slice())
232 }
233 }
234 }
235}
236
237impl<I: Interner, S: std::fmt::Debug> TypeVisitable<I> for RegionConstraint<I, S> {
238 fn visit_with<F: TypeVisitor<I>>(&self, f: &mut F) -> F::Result {
239 use RegionConstraint::*;
240
241 match self {
242 Ambiguity(_) => (),
243 RegionOutlives(a, b, _) => {
244 match ::rustc_ast_ir::visit::VisitorResult::branch(a.visit_with(f)) {
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};try_visit!(a.visit_with(f));
245 match ::rustc_ast_ir::visit::VisitorResult::branch(b.visit_with(f)) {
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};try_visit!(b.visit_with(f));
246 }
247 AliasTyOutlivesViaEnv(outlives, _) => {
248 match ::rustc_ast_ir::visit::VisitorResult::branch(outlives.visit_with(f)) {
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};try_visit!(outlives.visit_with(f));
249 }
250 PlaceholderTyOutlives(a, b, _) => {
251 match ::rustc_ast_ir::visit::VisitorResult::branch(a.visit_with(f)) {
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};try_visit!(a.visit_with(f));
252 match ::rustc_ast_ir::visit::VisitorResult::branch(b.visit_with(f)) {
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};try_visit!(b.visit_with(f));
253 }
254 And(and) => {
255 for elem in and {
match ::rustc_ast_ir::visit::VisitorResult::branch(::rustc_type_ir::TypeVisitable::visit_with(elem,
f)) {
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};
};walk_visitable_list!(f, and);
256 }
257 Or(or) => {
258 for elem in or {
match ::rustc_ast_ir::visit::VisitorResult::branch(::rustc_type_ir::TypeVisitable::visit_with(elem,
f)) {
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};
};walk_visitable_list!(f, or);
259 }
260 };
261
262 F::Result::output()
263 }
264}
265
266impl<I: Interner, S> RegionConstraint<I, S> {
267 fn map_spans<T>(self, f: &mut impl FnMut(S) -> T) -> RegionConstraint<I, T> {
268 use RegionConstraint::*;
269
270 match self {
271 Ambiguity(span) => Ambiguity(f(span)),
272 RegionOutlives(a, b, span) => RegionOutlives(a, b, f(span)),
273 AliasTyOutlivesViaEnv(outlives, span) => AliasTyOutlivesViaEnv(outlives, f(span)),
274 PlaceholderTyOutlives(ty, region, span) => PlaceholderTyOutlives(ty, region, f(span)),
275 And(constraints) => And(constraints.into_iter().map(|c| c.map_spans(f)).collect()),
276 Or(constraints) => Or(constraints.into_iter().map(|c| c.map_spans(f)).collect()),
277 }
278 }
279
280 pub fn without_spans(self) -> RegionConstraint<I> {
281 self.map_spans(&mut |_| ())
282 }
283}
284
285impl<I: Interner> RegionConstraint<I> {
286 pub fn with_span<S: Clone>(self, span: S) -> RegionConstraint<I, S> {
287 self.map_spans(&mut |_| span.clone())
288 }
289}
290
291impl<I: Interner, S: Clone + std::fmt::Debug> Default for RegionConstraint<I, S> {
292 fn default() -> Self {
293 Self::new_true()
294 }
295}
296
297impl<I: Interner, S: Clone + std::fmt::Debug> RegionConstraint<I, S> {
298 pub fn new_true() -> Self {
299 RegionConstraint::And(Box::new([]))
300 }
301
302 pub fn is_true(&self) -> bool {
303 match self {
304 Self::And(and) => and.is_empty(),
305 _ => false,
306 }
307 }
308
309 pub fn new_false() -> Self {
310 RegionConstraint::Or(Box::new([]))
311 }
312
313 pub fn is_false(&self) -> bool {
314 match self {
315 Self::Or(or) => or.is_empty(),
316 _ => false,
317 }
318 }
319
320 pub fn is_or(&self) -> bool {
321 #[allow(non_exhaustive_omitted_patterns)] match self {
Self::Or(_) => true,
_ => false,
}matches!(self, Self::Or(_))
322 }
323
324 pub fn unwrap_or(self) -> Box<[RegionConstraint<I, S>]> {
325 match self {
326 Self::Or(ors) => ors,
327 _ => {
::core::panicking::panic_fmt(format_args!("`unwrap_or` on non-Or: {0:?}",
self));
}panic!("`unwrap_or` on non-Or: {self:?}"),
328 }
329 }
330
331 pub fn unwrap_and(self) -> Box<[RegionConstraint<I, S>]> {
332 match self {
333 Self::And(ands) => ands,
334 _ => {
::core::panicking::panic_fmt(format_args!("`unwrap_and` on non-And: {0:?}",
self));
}panic!("`unwrap_and` on non-And: {self:?}"),
335 }
336 }
337
338 pub fn is_and(&self) -> bool {
339 #[allow(non_exhaustive_omitted_patterns)] match self {
Self::And(_) => true,
_ => false,
}matches!(self, Self::And(_))
340 }
341
342 pub fn is_ambig(&self) -> bool {
343 #[allow(non_exhaustive_omitted_patterns)] match self {
Self::Ambiguity(_) => true,
_ => false,
}matches!(self, Self::Ambiguity(_))
344 }
345
346 pub fn and(self, other: RegionConstraint<I, S>) -> RegionConstraint<I, S> {
347 use RegionConstraint::*;
348
349 match (self, other) {
350 (And(a_ands), And(b_ands)) => And(a_ands
351 .into_iter()
352 .chain(b_ands.into_iter())
353 .collect::<Vec<_>>()
354 .into_boxed_slice()),
355 (And(ands), other) | (other, And(ands)) => {
356 And(ands.into_iter().chain([other]).collect::<Vec<_>>().into_boxed_slice())
357 }
358 (this, other) => And(Box::new([this, other])),
359 }
360 }
361
362 x;#[instrument(level = "debug", ret)]
365 pub fn canonical_form(self) -> Self {
366 use RegionConstraint::*;
367
368 fn permutations<I: Interner, S: Clone>(
369 ors: &[Vec<RegionConstraint<I, S>>],
370 ) -> Vec<Vec<RegionConstraint<I, S>>> {
371 match ors {
372 [] => vec![vec![]],
373 [or1] => {
374 let mut choices = vec![];
375 for choice in or1 {
376 choices.push(vec![choice.clone()]);
377 }
378 choices
379 }
380 [or1, rest_ors @ ..] => {
381 let mut choices = vec![];
382 for choice in or1 {
383 choices.extend(
384 permutations(rest_ors)
385 .into_iter()
386 .map(|and| std::iter::once(choice.clone()).chain(and).collect()),
387 );
388 }
389 choices
390 }
391 }
392 }
393
394 let canonical = match self {
395 And(ands) => {
396 let ors = ands
405 .into_iter()
406 .map(|c| c.canonical_form().unwrap_or().to_vec())
407 .collect::<Vec<_>>();
408 debug!(?ors);
409 let or_permutations = permutations(&ors);
410 debug!(?or_permutations);
411
412 Or(or_permutations
413 .into_iter()
414 .map(|c| {
415 And(c
416 .into_iter()
417 .flat_map(|c2| c2.unwrap_and().into_iter())
418 .collect::<Vec<_>>()
419 .into_boxed_slice())
420 })
421 .collect::<Vec<_>>()
422 .into_boxed_slice())
423 }
424 Or(ors) => {
425 Or(ors
429 .into_iter()
430 .flat_map(|c| c.canonical_form().unwrap_or().into_iter())
431 .collect::<Vec<_>>()
432 .into_boxed_slice())
433 }
434 _ => Or(Box::new([And(Box::new([self]))])),
435 };
436
437 assert!(
438 canonical.is_canonical_form(),
439 "non canonical form region constraint: {:?}",
440 canonical
441 );
442 canonical
443 }
444
445 fn is_leaf_constraint(&self) -> bool {
446 use RegionConstraint::*;
447 match self {
448 Ambiguity(_)
449 | RegionOutlives(..)
450 | AliasTyOutlivesViaEnv(..)
451 | PlaceholderTyOutlives(..) => true,
452 And(..) | Or(..) => false,
453 }
454 }
455
456 fn is_canonical_and(&self) -> bool {
457 if let Self::And(ands) = self { ands.iter().all(|c| c.is_leaf_constraint()) } else { false }
458 }
459
460 pub fn is_canonical_form(&self) -> bool {
461 if let Self::Or(ors) = self { ors.iter().all(|c| c.is_canonical_and()) } else { false }
462 }
463}
464
465x;#[instrument(level = "debug", skip(infcx), ret)]
479pub fn eagerly_handle_placeholders_in_universe<Infcx: InferCtxtLike<Interner = I>, I: Interner>(
480 infcx: &Infcx,
481 constraint: RegionConstraint<I>,
482 u: UniverseIndex,
483) -> RegionConstraint<I> {
484 use RegionConstraint::*;
485
486 let assumptions = infcx.get_placeholder_assumptions(u);
487
488 let constraint = rewrite_type_outlives_constraints_in_universe_for_eager_placeholder_handling(
493 infcx,
494 constraint,
495 u,
496 &assumptions,
497 );
498
499 let constraint = constraint.canonical_form();
501
502 let constraint = Or(constraint
508 .unwrap_or()
509 .into_iter()
510 .map(|c| {
511 let and =
512 And(compute_new_region_constraints(infcx, &c.unwrap_and(), u).into_boxed_slice());
513
514 pull_region_outlives_constraints_out_of_universe(infcx, and, u, &assumptions)
516 })
517 .collect::<Vec<_>>()
518 .into_boxed_slice());
519
520 evaluate_solver_constraint(&constraint)
522}
523
524x;#[instrument(level = "debug", skip(infcx), ret)]
533fn compute_new_region_constraints<Infcx: InferCtxtLike<Interner = I>, I: Interner>(
534 infcx: &Infcx,
535 constraints: &[RegionConstraint<I>],
536 u: UniverseIndex,
537) -> Vec<RegionConstraint<I>> {
538 use RegionConstraint::*;
539
540 let mut new_constraints = vec![];
541
542 let mut region_flows_builder = TransitiveRelationBuilder::default();
543 let mut regions = IndexSet::new();
544 for c in constraints {
545 match c {
546 And(..) | Or(..) => unreachable!(),
547 Ambiguity(_) | PlaceholderTyOutlives(..) | AliasTyOutlivesViaEnv(..) => {
548 new_constraints.push(c.clone())
549 }
550 RegionOutlives(r1, r2, _) => {
551 regions.insert(r1);
552 regions.insert(r2);
553 region_flows_builder.add(r2, r1);
554 }
555 }
556 }
557
558 let region_flow = region_flows_builder.freeze();
559 for r in regions.into_iter() {
560 for ub in region_flow.reachable_from(r) {
561 let is_placeholder_like = |r: Region<I>| match r.kind() {
564 RegionKind::ReLateParam(..)
565 | RegionKind::ReEarlyParam(..)
566 | RegionKind::RePlaceholder(..)
567 | RegionKind::ReStatic => true,
568 RegionKind::ReVar(..) => max_universe(infcx, r) < u,
569 RegionKind::ReError(..) => false,
570 RegionKind::ReErased | RegionKind::ReBound(..) => unreachable!(),
571 };
572
573 if is_placeholder_like(*r) && is_placeholder_like(*ub) {
574 new_constraints.push(RegionOutlives(*ub, *r, ()));
575 }
576 }
577 }
578
579 new_constraints
580}
581
582x;#[instrument(level = "debug", ret)]
584pub fn evaluate_solver_constraint<I: Interner, S: Clone + std::fmt::Debug>(
585 constraint: &RegionConstraint<I, S>,
586) -> RegionConstraint<I, S> {
587 use RegionConstraint::*;
588 match constraint {
589 Ambiguity(_)
590 | RegionOutlives(..)
591 | AliasTyOutlivesViaEnv(..)
592 | PlaceholderTyOutlives(..) => constraint.clone(),
593 And(and) => {
594 let mut and_constraints = Vec::new();
595 let mut ambiguity = None;
596 for c in and.iter() {
597 let evaluated_constraint = evaluate_solver_constraint(c);
598 if evaluated_constraint.is_true() {
599 } else if evaluated_constraint.is_false() {
601 return RegionConstraint::new_false();
602 } else if let Ambiguity(span) = evaluated_constraint {
603 ambiguity.get_or_insert(span);
604 } else {
605 and_constraints.push(evaluated_constraint);
606 }
607 }
608
609 ambiguity.map_or_else(
610 || RegionConstraint::And(and_constraints.into_boxed_slice()),
611 RegionConstraint::Ambiguity,
612 )
613 }
614 Or(or) => {
615 let mut or_constraints = Vec::new();
616 let mut ambiguity = None;
617 for c in or.iter() {
618 let evaluated_constraint = evaluate_solver_constraint(c);
619 if evaluated_constraint.is_false() {
620 } else if evaluated_constraint.is_true() {
622 return RegionConstraint::new_true();
623 } else if let Ambiguity(span) = evaluated_constraint {
624 ambiguity.get_or_insert(span);
625 } else {
626 or_constraints.push(evaluated_constraint);
627 }
628 }
629
630 ambiguity.map_or_else(
631 || RegionConstraint::Or(or_constraints.into_boxed_slice()),
632 RegionConstraint::Ambiguity,
633 )
634 }
635 }
636}
637
638x;#[instrument(level = "debug", skip(infcx), ret)]
659fn pull_region_outlives_constraints_out_of_universe<
660 Infcx: InferCtxtLike<Interner = I>,
661 I: Interner,
662>(
663 infcx: &Infcx,
664 constraint: RegionConstraint<I>,
665 u: UniverseIndex,
666 assumptions: &Option<Assumptions<I>>,
667) -> RegionConstraint<I> {
668 assert!(max_universe(infcx, constraint.clone()) <= u);
669
670 use RegionConstraint::*;
678 match constraint {
679 Ambiguity(_) | PlaceholderTyOutlives(..) | AliasTyOutlivesViaEnv(..) => {
680 assert!(max_universe(infcx, constraint.clone()) < u);
681 constraint
682 }
683 RegionOutlives(region_1, region_2, ()) => {
684 let region_1_u = max_universe(infcx, region_1);
685 let region_2_u = max_universe(infcx, region_2);
686
687 if region_1_u != u && region_2_u != u {
688 return constraint;
689 }
690
691 let assumptions = match assumptions {
692 Some(assumptions) => assumptions,
693 None => return RegionConstraint::Ambiguity(()),
694 };
695
696 let mut candidates = vec![];
697 for ub in
698 regions_outlived_by(region_1, assumptions).filter(|r| max_universe(infcx, *r) < u)
699 {
700 for lb in regions_outliving(region_2, assumptions, infcx.cx())
704 .filter(|r| max_universe(infcx, *r) < u)
705 {
706 candidates.push(RegionOutlives(ub, lb, ()));
710 }
711 }
712
713 RegionConstraint::Or(candidates.into_boxed_slice())
714 }
715 And(constraints) => And(constraints
716 .into_iter()
717 .map(|constraint| {
718 pull_region_outlives_constraints_out_of_universe(infcx, constraint, u, assumptions)
719 })
720 .collect()),
721 Or(_) => unreachable!(),
722 }
723}
724
725pub fn destructure_type_outlives_constraints_in_root<
730 Infcx: InferCtxtLike<Interner = I>,
731 I: Interner,
732 S: Clone + std::fmt::Debug,
733>(
734 infcx: &Infcx,
735 constraint: RegionConstraint<I, S>,
736 assumptions: &Assumptions<I>,
737) -> RegionConstraint<I, S> {
738 use RegionConstraint::*;
739
740 match constraint {
741 Ambiguity(_) | RegionOutlives(..) => constraint,
742 PlaceholderTyOutlives(ty, r, span) => {
743 Or(regions_outlived_by_placeholder(ty, assumptions, infcx.cx())
744 .map(move |assumption_r| RegionOutlives(assumption_r, r, span.clone()))
745 .collect::<Vec<_>>()
746 .into_boxed_slice())
747 }
748 AliasTyOutlivesViaEnv(bound_outlives, span) => {
749 alias_outlives_candidates_from_assumptions(infcx, bound_outlives, assumptions)
750 .with_span(span)
751 }
752 And(constraints) => And(constraints
753 .into_iter()
754 .map(|constraint| {
755 destructure_type_outlives_constraints_in_root(infcx, constraint, assumptions)
756 })
757 .collect()),
758 Or(constraints) => Or(constraints
759 .into_iter()
760 .map(|constraint| {
761 destructure_type_outlives_constraints_in_root(infcx, constraint, assumptions)
762 })
763 .collect()),
764 }
765}
766
767x;#[instrument(level = "debug", skip(infcx), ret)]
778fn rewrite_type_outlives_constraints_in_universe_for_eager_placeholder_handling<
779 Infcx: InferCtxtLike<Interner = I>,
780 I: Interner,
781>(
782 infcx: &Infcx,
783 constraint: RegionConstraint<I>,
784 u: UniverseIndex,
785 assumptions: &Option<Assumptions<I>>,
786) -> RegionConstraint<I> {
787 assert!(
788 max_universe(infcx, constraint.clone()) <= u,
789 "constraint {:?} contains terms from a larger universe than {:?}",
790 constraint.clone(),
791 u
792 );
793
794 use RegionConstraint::*;
795 match constraint {
796 Ambiguity(_) | RegionOutlives(..) => constraint,
797 PlaceholderTyOutlives(ty, region, ()) => {
798 let ty_u = max_universe(infcx, ty);
799 let region_u = max_universe(infcx, region);
800
801 if region_u != u && ty_u != u {
802 return constraint;
803 }
804
805 let assumptions = match assumptions {
806 Some(assumptions) => assumptions,
807 None => return Ambiguity(()),
808 };
809
810 let mut candidates = vec![];
811
812 candidates.extend(
815 regions_outlived_by_placeholder(ty, assumptions, infcx.cx())
816 .map(move |assumption_r| RegionOutlives(assumption_r, region, ())),
817 );
818
819 if region_u == u && ty_u < u {
823 candidates.extend(
824 regions_outliving::<I>(region, assumptions, infcx.cx())
825 .filter(|r| max_universe(infcx, *r) < u)
826 .map(|r| PlaceholderTyOutlives(ty, r, ())),
827 );
828 }
829
830 Or(candidates.into_boxed_slice())
831 }
832 AliasTyOutlivesViaEnv(bound_outlives, ()) => {
833 let mut candidates = Vec::new();
834
835 if max_universe(infcx, bound_outlives) == u {
851 let mut replacer = PlaceholderReplacer {
852 cx: infcx.cx(),
853 existing_var_count: bound_outlives.bound_vars().len(),
854 bound_vars: IndexMap::default(),
855 universe: u,
856 current_index: DebruijnIndex::ZERO,
857 };
858 let escaping_outlives = bound_outlives.skip_binder().fold_with(&mut replacer);
859 let bound_vars = bound_outlives.bound_vars().iter().chain(
860 core::mem::take(&mut replacer.bound_vars)
861 .into_iter()
862 .map(|(_, bound_region)| BoundVariableKind::Region(bound_region.kind)),
863 );
864 let bound_outlives = Binder::bind_with_vars(
865 escaping_outlives,
866 I::BoundVarKinds::from_vars(infcx.cx(), bound_vars),
867 );
868 let candidate = RegionConstraint::AliasTyOutlivesViaEnv(bound_outlives, ());
869 if max_universe(infcx, candidate.clone()) < u {
870 candidates.push(candidate);
871 } else {
872 candidates.push(Ambiguity(()));
876 }
877 }
878
879 let assumptions = match assumptions {
880 Some(assumptions) => assumptions,
881 None => {
882 candidates.push(Ambiguity(()));
883 return Or(candidates.into_boxed_slice());
884 }
885 };
886
887 candidates.push(alias_outlives_candidates_from_assumptions(
890 infcx,
891 bound_outlives,
892 assumptions,
893 ));
894
895 let (escaping_alias, escaping_r) = bound_outlives.skip_binder();
900 if max_universe(infcx, escaping_r) == u {
901 let mut replacer = PlaceholderReplacer {
902 cx: infcx.cx(),
903 existing_var_count: bound_outlives.bound_vars().len(),
904 bound_vars: IndexMap::default(),
905 universe: u,
906 current_index: DebruijnIndex::ZERO,
907 };
908 let escaping_alias = escaping_alias.fold_with(&mut replacer);
909 let bound_vars = bound_outlives.bound_vars().iter().chain(
910 core::mem::take(&mut replacer.bound_vars)
911 .into_iter()
912 .map(|(_, bound_region)| BoundVariableKind::Region(bound_region.kind)),
913 );
914 let bound_alias = Binder::bind_with_vars(
915 escaping_alias,
916 I::BoundVarKinds::from_vars(infcx.cx(), bound_vars),
917 );
918
919 for r2 in regions_outliving(escaping_r, assumptions, infcx.cx())
922 .filter(|r2| max_universe(infcx, *r2) < u)
923 {
924 let candidate =
925 AliasTyOutlivesViaEnv(bound_alias.map_bound(|alias| (alias, r2)), ());
926 if max_universe(infcx, candidate.clone()) < u {
927 candidates.push(candidate);
928 } else {
929 candidates.push(Ambiguity(()));
930 }
931 }
932 }
933
934 match infcx.typing_mode_raw() {
938 TypingMode::Coherence => candidates.push(RegionConstraint::Ambiguity(())),
939 TypingMode::Typeck { .. }
940 | TypingMode::ErasedNotCoherence { .. }
941 | TypingMode::PostTypeckUntilBorrowck { .. }
942 | TypingMode::PostBorrowck { .. }
943 | TypingMode::Reflection
944 | TypingMode::PostAnalysis
945 | TypingMode::Codegen => (),
946 };
947
948 RegionConstraint::Or(candidates.into_boxed_slice())
949 }
950 And(constraints) => And(constraints
951 .into_iter()
952 .map(|constraint| {
953 rewrite_type_outlives_constraints_in_universe_for_eager_placeholder_handling(
954 infcx,
955 constraint,
956 u,
957 assumptions,
958 )
959 })
960 .collect()),
961 Or(constraints) => Or(constraints
962 .into_iter()
963 .map(|constraint| {
964 rewrite_type_outlives_constraints_in_universe_for_eager_placeholder_handling(
965 infcx,
966 constraint,
967 u,
968 assumptions,
969 )
970 })
971 .collect()),
972 }
973}
974
975pub fn regions_outlived_by<I: Interner>(
978 r: Region<I>,
979 assumptions: &Assumptions<I>,
980) -> impl Iterator<Item = Region<I>> {
981 assumptions.region_outlives.reachable_from(r).into_iter().chain([r])
983}
984
985pub fn regions_outliving<I: Interner>(
988 r: Region<I>,
989 assumptions: &Assumptions<I>,
990 cx: I,
991) -> impl Iterator<Item = Region<I>> {
992 assumptions
993 .inverse_region_outlives
994 .reachable_from(r)
995 .into_iter()
996 .chain([r, Region::new_static(cx)])
999}
1000
1001pub fn regions_outlived_by_placeholder<I: Interner>(
1004 t: I::Ty,
1005 assumptions: &Assumptions<I>,
1006 cx: I,
1007) -> impl Iterator<Item = Region<I>> {
1008 match t.kind() {
1009 TyKind::Placeholder(..) | TyKind::Param(..) => (),
1010 _ => {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("non-placeholder in `regions_outlived_by_placeholder`: {0:?}",
t)));
}unreachable!("non-placeholder in `regions_outlived_by_placeholder`: {t:?}"),
1011 }
1012
1013 assumptions.type_outlives.iter().flat_map(move |binder| match binder.no_bound_vars() {
1014 Some(OutlivesClause(ty, r)) => (ty == t).then_some(r),
1015 None => Some(Region::new_static(cx)),
1016 })
1017}
1018
1019pub struct PlaceholderReplacer<I: Interner> {
1020 cx: I,
1021 existing_var_count: usize,
1022 bound_vars: IndexMap<BoundVar, BoundRegion<I>>,
1023 universe: UniverseIndex,
1024 current_index: DebruijnIndex,
1025}
1026
1027impl<I: Interner> TypeFolder<I> for PlaceholderReplacer<I> {
1028 fn cx(&self) -> I {
1029 self.cx
1030 }
1031
1032 fn fold_region(&mut self, r: Region<I>) -> Region<I> {
1033 match r.kind() {
1034 RegionKind::RePlaceholder(p) if p.universe == self.universe => {
1035 let bound_vars_len = self.bound_vars.len();
1036 let mapped_var = self.bound_vars.entry(p.bound.var).or_insert(BoundRegion {
1037 var: BoundVar::from_usize(self.existing_var_count + bound_vars_len),
1038 kind: p.bound.kind,
1039 });
1040 Region::new_bound(self.cx, self.current_index, *mapped_var)
1041 }
1042 _ => r,
1044 }
1045 }
1046
1047 fn fold_binder<T: TypeFoldable<I>>(&mut self, b: Binder<I, T>) -> Binder<I, T> {
1048 self.current_index.shift_in(1);
1049 let b = b.super_fold_with(self);
1050 self.current_index.shift_out(1);
1051 b
1052 }
1053}
1054
1055x;#[instrument(level = "debug", skip(infcx), ret)]
1060fn alias_outlives_candidates_from_assumptions<Infcx: InferCtxtLike<Interner = I>, I: Interner>(
1061 infcx: &Infcx,
1062 bound_outlives: Binder<I, (AliasTy<I>, Region<I>)>,
1063 assumptions: &Assumptions<I>,
1064) -> RegionConstraint<I> {
1065 let mut candidates = Vec::new();
1066
1067 let prev_universe = infcx.universe();
1068
1069 infcx.enter_forall_with_empty_assumptions(bound_outlives, |(alias, r)| {
1070 for bound_type_outlives in assumptions.type_outlives.iter() {
1071 let OutlivesClause(alias2, r2) =
1072 infcx.instantiate_binder_with_infer(*bound_type_outlives);
1073
1074 let mut relation = HigherRankedAliasMatcher {
1075 infcx,
1076 region_constraints: vec![RegionConstraint::RegionOutlives(r2, r, ())],
1077 };
1078
1079 if let Ok(_) = relation.relate(
1082 alias.to_ty(infcx.cx(), IsRigid::No),
1083 set_aliases_to_non_rigid(infcx.cx(), alias2).skip_norm_wip(),
1084 ) {
1085 candidates
1086 .push(RegionConstraint::And(relation.region_constraints.into_boxed_slice()));
1087 }
1088 }
1089 });
1090
1091 let constraint = RegionConstraint::Or(candidates.into_boxed_slice());
1092
1093 let largest_universe = infcx.universe();
1094 debug!(?prev_universe, ?largest_universe);
1095
1096 ((prev_universe.index() + 1)..=largest_universe.index())
1097 .map(|u| UniverseIndex::from_usize(u))
1098 .rev()
1099 .fold(constraint, |constraint, u| {
1100 eagerly_handle_placeholders_in_universe(infcx, constraint, u)
1101 })
1102}
1103
1104struct HigherRankedAliasMatcher<'a, Infcx: InferCtxtLike<Interner = I>, I: Interner> {
1105 infcx: &'a Infcx,
1106 region_constraints: Vec<RegionConstraint<I>>,
1107}
1108
1109impl<'a, Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeRelation<I>
1110 for HigherRankedAliasMatcher<'a, Infcx, I>
1111{
1112 fn cx(&self) -> I {
1113 self.infcx.cx()
1114 }
1115
1116 fn relate_ty_args(
1117 &mut self,
1118 a_ty: I::Ty,
1119 _b_ty: I::Ty,
1120 _ty_def_id: I::DefId,
1121 a_args: I::GenericArgs,
1122 b_args: I::GenericArgs,
1123 _mk: impl FnOnce(I::GenericArgs) -> I::Ty,
1124 ) -> RelateResult<I, I::Ty> {
1125 rustc_type_ir::relate::relate_args_invariantly(self, a_args, b_args)?;
1126 Ok(a_ty)
1127 }
1128
1129 fn relate_with_variance<T: Relate<I>>(
1130 &mut self,
1131 _variance: Variance,
1132 _info: VarianceDiagInfo<I>,
1133 a: T,
1134 b: T,
1135 ) -> RelateResult<I, T> {
1136 self.relate(a, b)
1139 }
1140
1141 fn tys(&mut self, a: I::Ty, b: I::Ty) -> RelateResult<I, I::Ty> {
1142 rustc_type_ir::relate::structurally_relate_tys(self, a, b)
1143 }
1144
1145 fn regions(&mut self, a: Region<I>, b: Region<I>) -> RelateResult<I, Region<I>> {
1146 if a != b {
1147 self.region_constraints.push(RegionConstraint::RegionOutlives(a, b, ()));
1148 self.region_constraints.push(RegionConstraint::RegionOutlives(b, a, ()));
1149 }
1150 Ok(a)
1151 }
1152
1153 fn consts(&mut self, a: I::Const, b: I::Const) -> RelateResult<I, I::Const> {
1154 rustc_type_ir::relate::structurally_relate_consts(self, a, b)
1155 }
1156
1157 fn binders<T>(&mut self, a: Binder<I, T>, b: Binder<I, T>) -> RelateResult<I, Binder<I, T>>
1158 where
1159 T: Relate<I>,
1160 {
1161 self.infcx.enter_forall_with_empty_assumptions(a, |a| {
1162 let u = self.infcx.universe();
1163 self.infcx.insert_placeholder_assumptions(u, Some(Assumptions::empty()));
1164 let b = self.infcx.instantiate_binder_with_infer(b);
1165 self.relate(a, b)
1166 })?;
1167
1168 self.infcx.enter_forall_with_empty_assumptions(b, |b| {
1169 let u = self.infcx.universe();
1170 self.infcx.insert_placeholder_assumptions(u, Some(Assumptions::empty()));
1171 let a = self.infcx.instantiate_binder_with_infer(a);
1172 self.relate(a, b)
1173 })?;
1174
1175 Ok(a)
1176 }
1177}