Skip to content

Commit

Permalink
Unrolled build for rust-lang#120318
Browse files Browse the repository at this point in the history
Rollup merge of rust-lang#120318 - Nadrieril:share-debug-impl, r=compiler-errors

pattern_analysis: Reuse most of the `DeconstructedPat` `Debug` impl

The `DeconstructedPat: Debug` is best-effort because we'd need `tcx` to get things like field names etc. Since rust-analyzer has a similar constraint, this PR moves most the impl to be shared between the two. While I was at it I also fixed a nit in the `IntRange: Debug` impl.

r? `@compiler-errors`
  • Loading branch information
rust-timer committed Jan 25, 2024
2 parents d93fecc + 354b45f commit edc7e62
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 107 deletions.
16 changes: 11 additions & 5 deletions compiler/rustc_pattern_analysis/src/constructor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,12 +391,18 @@ impl IntRange {
/// first.
impl fmt::Debug for IntRange {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Finite(lo) = self.lo {
if self.is_singleton() {
// Only finite ranges can be singletons.
let Finite(lo) = self.lo else { unreachable!() };
write!(f, "{lo}")?;
}
write!(f, "{}", RangeEnd::Excluded)?;
if let Finite(hi) = self.hi {
write!(f, "{hi}")?;
} else {
if let Finite(lo) = self.lo {
write!(f, "{lo}")?;
}
write!(f, "{}", RangeEnd::Excluded)?;
if let Finite(hi) = self.hi {
write!(f, "{hi}")?;
}
}
Ok(())
}
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_pattern_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,12 @@ pub trait TypeCx: Sized + fmt::Debug {
/// This must follow the invariants of `ConstructorSet`
fn ctors_for_ty(&self, ty: &Self::Ty) -> Result<ConstructorSet<Self>, Self::Error>;

/// Best-effort `Debug` implementation.
fn debug_pat(f: &mut fmt::Formatter<'_>, pat: &DeconstructedPat<'_, Self>) -> fmt::Result;
/// Write the name of the variant represented by `pat`. Used for the best-effort `Debug` impl of
/// `DeconstructedPat`. Only invoqued when `pat.ctor()` is `Struct | Variant(_) | UnionField`.
fn write_variant_name(
f: &mut fmt::Formatter<'_>,
pat: &crate::pat::DeconstructedPat<'_, Self>,
) -> fmt::Result;

/// Raise a bug.
fn bug(&self, fmt: fmt::Arguments<'_>) -> !;
Expand Down
70 changes: 69 additions & 1 deletion compiler/rustc_pattern_analysis/src/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,75 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> {
/// This is best effort and not good enough for a `Display` impl.
impl<'p, Cx: TypeCx> fmt::Debug for DeconstructedPat<'p, Cx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Cx::debug_pat(f, self)
let pat = self;
let mut first = true;
let mut start_or_continue = |s| {
if first {
first = false;
""
} else {
s
}
};
let mut start_or_comma = || start_or_continue(", ");

match pat.ctor() {
Struct | Variant(_) | UnionField => {
Cx::write_variant_name(f, pat)?;
// Without `cx`, we can't know which field corresponds to which, so we can't
// get the names of the fields. Instead we just display everything as a tuple
// struct, which should be good enough.
write!(f, "(")?;
for p in pat.iter_fields() {
write!(f, "{}", start_or_comma())?;
write!(f, "{p:?}")?;
}
write!(f, ")")
}
// Note: given the expansion of `&str` patterns done in `expand_pattern`, we should
// be careful to detect strings here. However a string literal pattern will never
// be reported as a non-exhaustiveness witness, so we can ignore this issue.
Ref => {
let subpattern = pat.iter_fields().next().unwrap();
write!(f, "&{:?}", subpattern)
}
Slice(slice) => {
let mut subpatterns = pat.iter_fields();
write!(f, "[")?;
match slice.kind {
SliceKind::FixedLen(_) => {
for p in subpatterns {
write!(f, "{}{:?}", start_or_comma(), p)?;
}
}
SliceKind::VarLen(prefix_len, _) => {
for p in subpatterns.by_ref().take(prefix_len) {
write!(f, "{}{:?}", start_or_comma(), p)?;
}
write!(f, "{}", start_or_comma())?;
write!(f, "..")?;
for p in subpatterns {
write!(f, "{}{:?}", start_or_comma(), p)?;
}
}
}
write!(f, "]")
}
Bool(b) => write!(f, "{b}"),
// Best-effort, will render signed ranges incorrectly
IntRange(range) => write!(f, "{range:?}"),
F32Range(lo, hi, end) => write!(f, "{lo}{end}{hi}"),
F64Range(lo, hi, end) => write!(f, "{lo}{end}{hi}"),
Str(value) => write!(f, "{value:?}"),
Opaque(..) => write!(f, "<constant pattern>"),
Or => {
for pat in pat.iter_fields() {
write!(f, "{}{:?}", start_or_continue(" | "), pat)?;
}
Ok(())
}
Wildcard | Missing { .. } | NonExhaustive | Hidden => write!(f, "_ : {:?}", pat.ty()),
}
}
}

Expand Down
110 changes: 11 additions & 99 deletions compiler/rustc_pattern_analysis/src/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -850,103 +850,6 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {

Pat { ty: pat.ty().inner(), span: DUMMY_SP, kind }
}

/// Best-effort `Debug` implementation.
pub(crate) fn debug_pat(
f: &mut fmt::Formatter<'_>,
pat: &crate::pat::DeconstructedPat<'_, Self>,
) -> fmt::Result {
let mut first = true;
let mut start_or_continue = |s| {
if first {
first = false;
""
} else {
s
}
};
let mut start_or_comma = || start_or_continue(", ");

match pat.ctor() {
Struct | Variant(_) | UnionField => match pat.ty().kind() {
ty::Adt(def, _) if def.is_box() => {
// Without `box_patterns`, the only legal pattern of type `Box` is `_` (outside
// of `std`). So this branch is only reachable when the feature is enabled and
// the pattern is a box pattern.
let subpattern = pat.iter_fields().next().unwrap();
write!(f, "box {subpattern:?}")
}
ty::Adt(..) | ty::Tuple(..) => {
let variant =
match pat.ty().kind() {
ty::Adt(adt, _) => Some(adt.variant(
RustcMatchCheckCtxt::variant_index_for_adt(pat.ctor(), *adt),
)),
ty::Tuple(_) => None,
_ => unreachable!(),
};

if let Some(variant) = variant {
write!(f, "{}", variant.name)?;
}

// Without `cx`, we can't know which field corresponds to which, so we can't
// get the names of the fields. Instead we just display everything as a tuple
// struct, which should be good enough.
write!(f, "(")?;
for p in pat.iter_fields() {
write!(f, "{}", start_or_comma())?;
write!(f, "{p:?}")?;
}
write!(f, ")")
}
_ => write!(f, "_"),
},
// Note: given the expansion of `&str` patterns done in `expand_pattern`, we should
// be careful to detect strings here. However a string literal pattern will never
// be reported as a non-exhaustiveness witness, so we can ignore this issue.
Ref => {
let subpattern = pat.iter_fields().next().unwrap();
write!(f, "&{:?}", subpattern)
}
Slice(slice) => {
let mut subpatterns = pat.iter_fields();
write!(f, "[")?;
match slice.kind {
SliceKind::FixedLen(_) => {
for p in subpatterns {
write!(f, "{}{:?}", start_or_comma(), p)?;
}
}
SliceKind::VarLen(prefix_len, _) => {
for p in subpatterns.by_ref().take(prefix_len) {
write!(f, "{}{:?}", start_or_comma(), p)?;
}
write!(f, "{}", start_or_comma())?;
write!(f, "..")?;
for p in subpatterns {
write!(f, "{}{:?}", start_or_comma(), p)?;
}
}
}
write!(f, "]")
}
Bool(b) => write!(f, "{b}"),
// Best-effort, will render signed ranges incorrectly
IntRange(range) => write!(f, "{range:?}"),
F32Range(lo, hi, end) => write!(f, "{lo}{end}{hi}"),
F64Range(lo, hi, end) => write!(f, "{lo}{end}{hi}"),
Str(value) => write!(f, "{value}"),
Opaque(..) => write!(f, "<constant pattern>"),
Or => {
for pat in pat.iter_fields() {
write!(f, "{}{:?}", start_or_continue(" | "), pat)?;
}
Ok(())
}
Wildcard | Missing { .. } | NonExhaustive | Hidden => write!(f, "_ : {:?}", pat.ty()),
}
}
}

impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> {
Expand Down Expand Up @@ -978,12 +881,21 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> {
self.ctors_for_ty(*ty)
}

fn debug_pat(
fn write_variant_name(
f: &mut fmt::Formatter<'_>,
pat: &crate::pat::DeconstructedPat<'_, Self>,
) -> fmt::Result {
Self::debug_pat(f, pat)
if let ty::Adt(adt, _) = pat.ty().kind() {
if adt.is_box() {
write!(f, "Box")?
} else {
let variant = adt.variant(Self::variant_index_for_adt(pat.ctor(), *adt));
write!(f, "{}", variant.name)?;
}
}
Ok(())
}

fn bug(&self, fmt: fmt::Arguments<'_>) -> ! {
span_bug!(self.scrut_span, "{}", fmt)
}
Expand Down

0 comments on commit edc7e62

Please sign in to comment.