Skip to content

Commit a0e620a

Browse files
Rollup merge of rust-lang#153785 - amandasystems:debug-type-test, r=wesleywiser
Hand-written Debug implementation for `TypeTest` This adds a hand-written debug format for `TypeTest`s that at least was helpful for me when debugging because I always struggle to remember which component is which. It formats a type test using the Unicode turnstile symbol (for "computes") to illustrate that the test encodes a typing rule that, if it holds, produces a conclusion. The format is: `TypeTest from {originating span} {bound} ⊢ T: 'lower_bound`, where `T` is the generic type being tested and `lower_bound` is the lower bound. Bounds are formatted as you would expect, but where the region for `'lower_bound` is included in the outlives constraints for context. I resisted the urge to turn `ALL [A, ..., Z]` into `[A ∧ ... ∧ Z]` etc. ## What it looks like Here's an example of a simple type test from the test suite that says that some type `I/#0` will be lower-bounded (outlive) `?4` iff `'?1: '?4`: Before: ``` $ RUSTC_LOG="rustc_borrowck::region_infer=debug" rustc +stage1 tests/ui/associated-types/associated-types-eq-3.rs ... DEBUG rustc_borrowck::region_infer type tests: [ TypeTest { generic_kind: I/#0, lower_bound: '?4, span: tests/ui/associated-types/associated-types-eq-3.rs:21:18: 21:25 (#0), verify_bound: OutlivedBy( '?1, ), }, TypeTest { generic_kind: I/#0, lower_bound: '?4, span: tests/ui/associated-types/associated-types-eq-3.rs:21:18: 21:25 (#0), verify_bound: OutlivedBy( '?1, ), }, ] ... ``` After: ``` $ RUSTC_LOG="rustc_borrowck::region_infer=debug" rustc +stage1 tests/ui/associated-types/associated-types-eq-3.rs ... DEBUG rustc_borrowck::region_infer type tests: [ TypeTest from tests/ui/associated-types/associated-types-eq-3.rs:21:18: 21:25 (#0)['?1: '?4] ⊢ I/#0: '?4, TypeTest from tests/ui/associated-types/associated-types-eq-3.rs:21:18: 21:25 (#0)['?1: '?4] ⊢ I/#0: '?4, ] ... ```
2 parents 6f222b3 + 9bd3f51 commit a0e620a

1 file changed

Lines changed: 43 additions & 1 deletion

File tree

  • compiler/rustc_borrowck/src/region_infer

compiler/rustc_borrowck/src/region_infer/mod.rs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::collections::VecDeque;
2+
use std::fmt;
23
use std::rc::Rc;
34

45
use rustc_data_structures::frozen::Frozen;
@@ -182,7 +183,7 @@ pub(crate) enum Cause {
182183
/// For more information about this translation, see
183184
/// `InferCtxt::process_registered_region_obligations` and
184185
/// `InferCtxt::type_must_outlive` in `rustc_infer::infer::InferCtxt`.
185-
#[derive(Clone, Debug)]
186+
#[derive(Clone)]
186187
pub(crate) struct TypeTest<'tcx> {
187188
/// The type `T` that must outlive the region.
188189
pub generic_kind: GenericKind<'tcx>,
@@ -198,6 +199,47 @@ pub(crate) struct TypeTest<'tcx> {
198199
pub verify_bound: VerifyBound<'tcx>,
199200
}
200201

202+
impl fmt::Debug for TypeTest<'_> {
203+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204+
fn fmt_bound(
205+
f: &mut fmt::Formatter<'_>,
206+
generic_kind: GenericKind<'_>,
207+
lower: RegionVid,
208+
bound: &VerifyBound<'_>,
209+
) -> fmt::Result {
210+
let fmt_bounds =
211+
|f: &mut fmt::Formatter<'_>, bounds: &[VerifyBound<'_>]| -> fmt::Result {
212+
let mut it = bounds.iter().peekable();
213+
while let Some(bound) = it.next() {
214+
fmt_bound(f, generic_kind, lower, bound)?;
215+
if it.peek().is_some() {
216+
write!(f, ", ")?
217+
}
218+
}
219+
Ok(())
220+
};
221+
match bound {
222+
VerifyBound::IfEq(binder) => write!(f, "{:?} == {:?}", generic_kind, binder),
223+
VerifyBound::OutlivedBy(region) => write!(f, "{region:?}: {lower:?}"),
224+
VerifyBound::AnyBound(verify_bounds) => {
225+
write!(f, "Any[")?;
226+
fmt_bounds(f, verify_bounds)?;
227+
write!(f, "]")
228+
}
229+
VerifyBound::AllBounds(verify_bounds) => {
230+
write!(f, "All[")?;
231+
fmt_bounds(f, verify_bounds)?;
232+
write!(f, "]")
233+
}
234+
VerifyBound::IsEmpty => write!(f, "Empty({lower:?})"),
235+
}
236+
}
237+
write!(f, "TypeTest from {:?}[", self.span)?;
238+
fmt_bound(f, self.generic_kind, self.lower_bound, &self.verify_bound)?;
239+
write!(f, "] ⊢ {:?}: {:?}", self.generic_kind, self.lower_bound)
240+
}
241+
}
242+
201243
/// When we have an unmet lifetime constraint, we try to propagate it outward (e.g. to a closure
202244
/// environment). If we can't, it is an error.
203245
#[derive(Clone, Copy, Debug, Eq, PartialEq)]

0 commit comments

Comments
 (0)