|
1 | 1 | use crate::ty::{self, Binder, Ty, TyCtxt, TypeFlags};
|
2 |
| -use rustc_errors::ErrorGuaranteed; |
3 | 2 |
|
4 | 3 | use rustc_data_structures::fx::FxHashSet;
|
5 | 4 | use rustc_data_structures::sso::SsoHashSet;
|
6 | 5 | use std::ops::ControlFlow;
|
7 | 6 |
|
8 |
| -pub use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; |
9 |
| - |
10 |
| -pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> { |
11 |
| - /// Returns `true` if `self` has any late-bound regions that are either |
12 |
| - /// bound by `binder` or bound by some binder outside of `binder`. |
13 |
| - /// If `binder` is `ty::INNERMOST`, this indicates whether |
14 |
| - /// there are any late-bound regions that appear free. |
15 |
| - fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool { |
16 |
| - self.visit_with(&mut HasEscapingVarsVisitor { outer_index: binder }).is_break() |
17 |
| - } |
18 |
| - |
19 |
| - /// Returns `true` if this type has any regions that escape `binder` (and |
20 |
| - /// hence are not bound by it). |
21 |
| - fn has_vars_bound_above(&self, binder: ty::DebruijnIndex) -> bool { |
22 |
| - self.has_vars_bound_at_or_above(binder.shifted_in(1)) |
23 |
| - } |
24 |
| - |
25 |
| - /// Return `true` if this type has regions that are not a part of the type. |
26 |
| - /// For example, `for<'a> fn(&'a i32)` return `false`, while `fn(&'a i32)` |
27 |
| - /// would return `true`. The latter can occur when traversing through the |
28 |
| - /// former. |
29 |
| - /// |
30 |
| - /// See [`HasEscapingVarsVisitor`] for more information. |
31 |
| - fn has_escaping_bound_vars(&self) -> bool { |
32 |
| - self.has_vars_bound_at_or_above(ty::INNERMOST) |
33 |
| - } |
34 |
| - |
35 |
| - fn has_type_flags(&self, flags: TypeFlags) -> bool { |
36 |
| - let res = |
37 |
| - self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags); |
38 |
| - trace!(?self, ?flags, ?res, "has_type_flags"); |
39 |
| - res |
40 |
| - } |
41 |
| - fn has_projections(&self) -> bool { |
42 |
| - self.has_type_flags(TypeFlags::HAS_PROJECTION) |
43 |
| - } |
44 |
| - fn has_inherent_projections(&self) -> bool { |
45 |
| - self.has_type_flags(TypeFlags::HAS_TY_INHERENT) |
46 |
| - } |
47 |
| - fn has_opaque_types(&self) -> bool { |
48 |
| - self.has_type_flags(TypeFlags::HAS_TY_OPAQUE) |
49 |
| - } |
50 |
| - fn has_coroutines(&self) -> bool { |
51 |
| - self.has_type_flags(TypeFlags::HAS_TY_COROUTINE) |
52 |
| - } |
53 |
| - fn references_error(&self) -> bool { |
54 |
| - self.has_type_flags(TypeFlags::HAS_ERROR) |
55 |
| - } |
56 |
| - fn error_reported(&self) -> Result<(), ErrorGuaranteed> { |
57 |
| - if self.references_error() { |
58 |
| - // We must include lint errors and span delayed bugs here. |
59 |
| - if let Some(reported) = |
60 |
| - ty::tls::with(|tcx| tcx.dcx().has_errors_or_lint_errors_or_delayed_bugs()) |
61 |
| - { |
62 |
| - Err(reported) |
63 |
| - } else { |
64 |
| - bug!("expected some kind of error in `error_reported`"); |
65 |
| - } |
66 |
| - } else { |
67 |
| - Ok(()) |
68 |
| - } |
69 |
| - } |
70 |
| - fn has_non_region_param(&self) -> bool { |
71 |
| - self.has_type_flags(TypeFlags::HAS_PARAM - TypeFlags::HAS_RE_PARAM) |
72 |
| - } |
73 |
| - fn has_infer_regions(&self) -> bool { |
74 |
| - self.has_type_flags(TypeFlags::HAS_RE_INFER) |
75 |
| - } |
76 |
| - fn has_infer_types(&self) -> bool { |
77 |
| - self.has_type_flags(TypeFlags::HAS_TY_INFER) |
78 |
| - } |
79 |
| - fn has_non_region_infer(&self) -> bool { |
80 |
| - self.has_type_flags(TypeFlags::HAS_INFER - TypeFlags::HAS_RE_INFER) |
81 |
| - } |
82 |
| - fn has_infer(&self) -> bool { |
83 |
| - self.has_type_flags(TypeFlags::HAS_INFER) |
84 |
| - } |
85 |
| - fn has_placeholders(&self) -> bool { |
86 |
| - self.has_type_flags(TypeFlags::HAS_PLACEHOLDER) |
87 |
| - } |
88 |
| - fn has_non_region_placeholders(&self) -> bool { |
89 |
| - self.has_type_flags(TypeFlags::HAS_PLACEHOLDER - TypeFlags::HAS_RE_PLACEHOLDER) |
90 |
| - } |
91 |
| - fn has_param(&self) -> bool { |
92 |
| - self.has_type_flags(TypeFlags::HAS_PARAM) |
93 |
| - } |
94 |
| - /// "Free" regions in this context means that it has any region |
95 |
| - /// that is not (a) erased or (b) late-bound. |
96 |
| - fn has_free_regions(&self) -> bool { |
97 |
| - self.has_type_flags(TypeFlags::HAS_FREE_REGIONS) |
98 |
| - } |
99 |
| - |
100 |
| - fn has_erased_regions(&self) -> bool { |
101 |
| - self.has_type_flags(TypeFlags::HAS_RE_ERASED) |
102 |
| - } |
103 |
| - |
104 |
| - /// True if there are any un-erased free regions. |
105 |
| - fn has_erasable_regions(&self) -> bool { |
106 |
| - self.has_type_flags(TypeFlags::HAS_FREE_REGIONS) |
107 |
| - } |
108 |
| - |
109 |
| - /// Indicates whether this value references only 'global' |
110 |
| - /// generic parameters that are the same regardless of what fn we are |
111 |
| - /// in. This is used for caching. |
112 |
| - fn is_global(&self) -> bool { |
113 |
| - !self.has_type_flags(TypeFlags::HAS_FREE_LOCAL_NAMES) |
114 |
| - } |
115 |
| - |
116 |
| - /// True if there are any late-bound regions |
117 |
| - fn has_bound_regions(&self) -> bool { |
118 |
| - self.has_type_flags(TypeFlags::HAS_RE_BOUND) |
119 |
| - } |
120 |
| - /// True if there are any late-bound non-region variables |
121 |
| - fn has_non_region_bound_vars(&self) -> bool { |
122 |
| - self.has_type_flags(TypeFlags::HAS_BOUND_VARS - TypeFlags::HAS_RE_BOUND) |
123 |
| - } |
124 |
| - /// True if there are any bound variables |
125 |
| - fn has_bound_vars(&self) -> bool { |
126 |
| - self.has_type_flags(TypeFlags::HAS_BOUND_VARS) |
127 |
| - } |
128 |
| - |
129 |
| - /// Indicates whether this value still has parameters/placeholders/inference variables |
130 |
| - /// which could be replaced later, in a way that would change the results of `impl` |
131 |
| - /// specialization. |
132 |
| - fn still_further_specializable(&self) -> bool { |
133 |
| - self.has_type_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE) |
134 |
| - } |
135 |
| -} |
136 |
| - |
137 |
| -impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeVisitableExt<'tcx> for T {} |
| 7 | +pub use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; |
138 | 8 |
|
139 | 9 | ///////////////////////////////////////////////////////////////////////////
|
140 | 10 | // Region folder
|
@@ -370,185 +240,6 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ValidateBoundVars<'tcx> {
|
370 | 240 | }
|
371 | 241 | }
|
372 | 242 |
|
373 |
| -#[derive(Debug, PartialEq, Eq, Copy, Clone)] |
374 |
| -struct FoundEscapingVars; |
375 |
| - |
376 |
| -/// An "escaping var" is a bound var whose binder is not part of `t`. A bound var can be a |
377 |
| -/// bound region or a bound type. |
378 |
| -/// |
379 |
| -/// So, for example, consider a type like the following, which has two binders: |
380 |
| -/// |
381 |
| -/// for<'a> fn(x: for<'b> fn(&'a isize, &'b isize)) |
382 |
| -/// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ outer scope |
383 |
| -/// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ inner scope |
384 |
| -/// |
385 |
| -/// This type has *bound regions* (`'a`, `'b`), but it does not have escaping regions, because the |
386 |
| -/// binders of both `'a` and `'b` are part of the type itself. However, if we consider the *inner |
387 |
| -/// fn type*, that type has an escaping region: `'a`. |
388 |
| -/// |
389 |
| -/// Note that what I'm calling an "escaping var" is often just called a "free var". However, |
390 |
| -/// we already use the term "free var". It refers to the regions or types that we use to represent |
391 |
| -/// bound regions or type params on a fn definition while we are type checking its body. |
392 |
| -/// |
393 |
| -/// To clarify, conceptually there is no particular difference between |
394 |
| -/// an "escaping" var and a "free" var. However, there is a big |
395 |
| -/// difference in practice. Basically, when "entering" a binding |
396 |
| -/// level, one is generally required to do some sort of processing to |
397 |
| -/// a bound var, such as replacing it with a fresh/placeholder |
398 |
| -/// var, or making an entry in the environment to represent the |
399 |
| -/// scope to which it is attached, etc. An escaping var represents |
400 |
| -/// a bound var for which this processing has not yet been done. |
401 |
| -struct HasEscapingVarsVisitor { |
402 |
| - /// Anything bound by `outer_index` or "above" is escaping. |
403 |
| - outer_index: ty::DebruijnIndex, |
404 |
| -} |
405 |
| - |
406 |
| -impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasEscapingVarsVisitor { |
407 |
| - type BreakTy = FoundEscapingVars; |
408 |
| - |
409 |
| - fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>( |
410 |
| - &mut self, |
411 |
| - t: &Binder<'tcx, T>, |
412 |
| - ) -> ControlFlow<Self::BreakTy> { |
413 |
| - self.outer_index.shift_in(1); |
414 |
| - let result = t.super_visit_with(self); |
415 |
| - self.outer_index.shift_out(1); |
416 |
| - result |
417 |
| - } |
418 |
| - |
419 |
| - #[inline] |
420 |
| - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { |
421 |
| - // If the outer-exclusive-binder is *strictly greater* than |
422 |
| - // `outer_index`, that means that `t` contains some content |
423 |
| - // bound at `outer_index` or above (because |
424 |
| - // `outer_exclusive_binder` is always 1 higher than the |
425 |
| - // content in `t`). Therefore, `t` has some escaping vars. |
426 |
| - if t.outer_exclusive_binder() > self.outer_index { |
427 |
| - ControlFlow::Break(FoundEscapingVars) |
428 |
| - } else { |
429 |
| - ControlFlow::Continue(()) |
430 |
| - } |
431 |
| - } |
432 |
| - |
433 |
| - #[inline] |
434 |
| - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { |
435 |
| - // If the region is bound by `outer_index` or anything outside |
436 |
| - // of outer index, then it escapes the binders we have |
437 |
| - // visited. |
438 |
| - if r.bound_at_or_above_binder(self.outer_index) { |
439 |
| - ControlFlow::Break(FoundEscapingVars) |
440 |
| - } else { |
441 |
| - ControlFlow::Continue(()) |
442 |
| - } |
443 |
| - } |
444 |
| - |
445 |
| - fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { |
446 |
| - // If the outer-exclusive-binder is *strictly greater* than |
447 |
| - // `outer_index`, that means that `ct` contains some content |
448 |
| - // bound at `outer_index` or above (because |
449 |
| - // `outer_exclusive_binder` is always 1 higher than the |
450 |
| - // content in `t`). Therefore, `t` has some escaping vars. |
451 |
| - if ct.outer_exclusive_binder() > self.outer_index { |
452 |
| - ControlFlow::Break(FoundEscapingVars) |
453 |
| - } else { |
454 |
| - ControlFlow::Continue(()) |
455 |
| - } |
456 |
| - } |
457 |
| - |
458 |
| - #[inline] |
459 |
| - fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> { |
460 |
| - if predicate.outer_exclusive_binder() > self.outer_index { |
461 |
| - ControlFlow::Break(FoundEscapingVars) |
462 |
| - } else { |
463 |
| - ControlFlow::Continue(()) |
464 |
| - } |
465 |
| - } |
466 |
| -} |
467 |
| - |
468 |
| -#[derive(Debug, PartialEq, Eq, Copy, Clone)] |
469 |
| -struct FoundFlags; |
470 |
| - |
471 |
| -// FIXME: Optimize for checking for infer flags |
472 |
| -struct HasTypeFlagsVisitor { |
473 |
| - flags: ty::TypeFlags, |
474 |
| -} |
475 |
| - |
476 |
| -impl std::fmt::Debug for HasTypeFlagsVisitor { |
477 |
| - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
478 |
| - self.flags.fmt(fmt) |
479 |
| - } |
480 |
| -} |
481 |
| - |
482 |
| -// Note: this visitor traverses values down to the level of |
483 |
| -// `Ty`/`Const`/`Predicate`, but not within those types. This is because the |
484 |
| -// type flags at the outer layer are enough. So it's faster than it first |
485 |
| -// looks, particular for `Ty`/`Predicate` where it's just a field access. |
486 |
| -// |
487 |
| -// N.B. The only case where this isn't totally true is binders, which also |
488 |
| -// add `HAS_{RE,TY,CT}_LATE_BOUND` flag depending on the *bound variables* that |
489 |
| -// are present, regardless of whether those bound variables are used. This |
490 |
| -// is important for anonymization of binders in `TyCtxt::erase_regions`. We |
491 |
| -// specifically detect this case in `visit_binder`. |
492 |
| -impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasTypeFlagsVisitor { |
493 |
| - type BreakTy = FoundFlags; |
494 |
| - |
495 |
| - fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>( |
496 |
| - &mut self, |
497 |
| - t: &Binder<'tcx, T>, |
498 |
| - ) -> ControlFlow<Self::BreakTy> { |
499 |
| - // If we're looking for the HAS_BINDER_VARS flag, check if the |
500 |
| - // binder has vars. This won't be present in the binder's bound |
501 |
| - // value, so we need to check here too. |
502 |
| - if self.flags.intersects(TypeFlags::HAS_BINDER_VARS) && !t.bound_vars().is_empty() { |
503 |
| - return ControlFlow::Break(FoundFlags); |
504 |
| - } |
505 |
| - |
506 |
| - t.super_visit_with(self) |
507 |
| - } |
508 |
| - |
509 |
| - #[inline] |
510 |
| - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { |
511 |
| - // Note: no `super_visit_with` call. |
512 |
| - let flags = t.flags(); |
513 |
| - if flags.intersects(self.flags) { |
514 |
| - ControlFlow::Break(FoundFlags) |
515 |
| - } else { |
516 |
| - ControlFlow::Continue(()) |
517 |
| - } |
518 |
| - } |
519 |
| - |
520 |
| - #[inline] |
521 |
| - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { |
522 |
| - // Note: no `super_visit_with` call, as usual for `Region`. |
523 |
| - let flags = r.type_flags(); |
524 |
| - if flags.intersects(self.flags) { |
525 |
| - ControlFlow::Break(FoundFlags) |
526 |
| - } else { |
527 |
| - ControlFlow::Continue(()) |
528 |
| - } |
529 |
| - } |
530 |
| - |
531 |
| - #[inline] |
532 |
| - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { |
533 |
| - // Note: no `super_visit_with` call. |
534 |
| - if c.flags().intersects(self.flags) { |
535 |
| - ControlFlow::Break(FoundFlags) |
536 |
| - } else { |
537 |
| - ControlFlow::Continue(()) |
538 |
| - } |
539 |
| - } |
540 |
| - |
541 |
| - #[inline] |
542 |
| - fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> { |
543 |
| - // Note: no `super_visit_with` call. |
544 |
| - if predicate.flags().intersects(self.flags) { |
545 |
| - ControlFlow::Break(FoundFlags) |
546 |
| - } else { |
547 |
| - ControlFlow::Continue(()) |
548 |
| - } |
549 |
| - } |
550 |
| -} |
551 |
| - |
552 | 243 | /// Collects all the late-bound regions at the innermost binding level
|
553 | 244 | /// into a hash set.
|
554 | 245 | struct LateBoundRegionsCollector {
|
|
0 commit comments