rustc_pattern_analysis/rustc/
print.rs1use std::fmt;
13
14use rustc_abi::{FieldIdx, VariantIdx};
15use rustc_middle::bug;
16use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
17use rustc_span::sym;
18
19#[derive(#[automatically_derived]
impl ::core::clone::Clone for FieldPat {
#[inline]
fn clone(&self) -> FieldPat {
FieldPat {
field: ::core::clone::Clone::clone(&self.field),
pattern: ::core::clone::Clone::clone(&self.pattern),
is_wildcard: ::core::clone::Clone::clone(&self.is_wildcard),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for FieldPat {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f, "FieldPat",
"field", &self.field, "pattern", &self.pattern, "is_wildcard",
&&self.is_wildcard)
}
}Debug)]
20pub(crate) struct FieldPat {
21 pub(crate) field: FieldIdx,
22 pub(crate) pattern: String,
23 pub(crate) is_wildcard: bool,
24}
25
26fn start_or_comma() -> impl FnMut() -> &'static str {
30 let mut first = true;
31 move || {
32 if first {
33 first = false;
34 ""
35 } else {
36 ", "
37 }
38 }
39}
40
41#[derive(#[automatically_derived]
impl<'tcx> ::core::clone::Clone for EnumInfo<'tcx> {
#[inline]
fn clone(&self) -> EnumInfo<'tcx> {
match self {
EnumInfo::Enum { adt_def: __self_0, variant_index: __self_1 } =>
EnumInfo::Enum {
adt_def: ::core::clone::Clone::clone(__self_0),
variant_index: ::core::clone::Clone::clone(__self_1),
},
EnumInfo::NotEnum => EnumInfo::NotEnum,
}
}
}Clone, #[automatically_derived]
impl<'tcx> ::core::fmt::Debug for EnumInfo<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
EnumInfo::Enum { adt_def: __self_0, variant_index: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f, "Enum",
"adt_def", __self_0, "variant_index", &__self_1),
EnumInfo::NotEnum =>
::core::fmt::Formatter::write_str(f, "NotEnum"),
}
}
}Debug)]
42pub(crate) enum EnumInfo<'tcx> {
43 Enum { adt_def: AdtDef<'tcx>, variant_index: VariantIdx },
44 NotEnum,
45}
46
47pub(crate) fn write_struct_like<'tcx>(
48 f: &mut impl fmt::Write,
49 tcx: TyCtxt<'_>,
50 ty: Ty<'tcx>,
51 enum_info: &EnumInfo<'tcx>,
52 subpatterns: &[FieldPat],
53) -> fmt::Result {
54 let variant_and_name = match *enum_info {
55 EnumInfo::Enum { adt_def, variant_index } => {
56 let variant = adt_def.variant(variant_index);
57 let adt_did = adt_def.did();
58 let name = if tcx.is_diagnostic_item(sym::Option, adt_did)
59 || tcx.is_diagnostic_item(sym::Result, adt_did)
60 {
61 variant.name.to_string()
62 } else {
63 {
let _guard =
::rustc_middle::ty::print::pretty::RtnModeHelper::with(RtnMode::ForSuggestion);
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}::{1}",
tcx.def_path_str(adt_def.did()), variant.name))
})
}ty::print::with_types_for_suggestion!(format!(
64 "{}::{}",
65 tcx.def_path_str(adt_def.did()),
66 variant.name
67 ))
68 };
69 Some((variant, name))
70 }
71 EnumInfo::NotEnum => ty.ty_adt_def().and_then(|adt_def| {
72 Some((adt_def.non_enum_variant(), tcx.def_path_str(adt_def.did())))
73 }),
74 };
75
76 let mut start_or_comma = start_or_comma();
77
78 if let Some((variant, name)) = &variant_and_name {
79 f.write_fmt(format_args!("{0}", name))write!(f, "{name}")?;
80
81 if variant.ctor.is_none() {
84 f.write_fmt(format_args!(" {{ "))write!(f, " {{ ")?;
85
86 let mut printed = 0;
87 for &FieldPat { field, ref pattern, is_wildcard } in subpatterns {
88 if is_wildcard {
89 continue;
90 }
91 let field_name = variant.fields[field].name;
92 f.write_fmt(format_args!("{0}{1}: {2}", start_or_comma(), field_name,
pattern))write!(f, "{}{field_name}: {pattern}", start_or_comma())?;
93 printed += 1;
94 }
95
96 let is_union = ty.ty_adt_def().is_some_and(|adt| adt.is_union());
97 if printed < variant.fields.len() && (!is_union || printed == 0) {
98 f.write_fmt(format_args!("{0}..", start_or_comma()))write!(f, "{}..", start_or_comma())?;
99 }
100
101 return f.write_fmt(format_args!(" }}"))write!(f, " }}");
102 }
103 }
104
105 let num_fields = variant_and_name.as_ref().map_or(subpatterns.len(), |(v, _)| v.fields.len());
106 if num_fields != 0 || variant_and_name.is_none() {
107 f.write_fmt(format_args!("("))write!(f, "(")?;
108 for FieldPat { pattern, .. } in subpatterns {
109 f.write_fmt(format_args!("{0}{1}", start_or_comma(), pattern))write!(f, "{}{pattern}", start_or_comma())?;
110 }
111 if #[allow(non_exhaustive_omitted_patterns)] match ty.kind() {
ty::Tuple(..) => true,
_ => false,
}matches!(ty.kind(), ty::Tuple(..)) && num_fields == 1 {
112 f.write_fmt(format_args!(","))write!(f, ",")?;
113 }
114 f.write_fmt(format_args!(")"))write!(f, ")")?;
115 }
116
117 Ok(())
118}
119
120pub(crate) fn write_ref_like<'tcx>(
121 f: &mut impl fmt::Write,
122 ty: Ty<'tcx>,
123 subpattern: &str,
124) -> fmt::Result {
125 match ty.kind() {
126 ty::Ref(_, _, mutbl) => {
127 f.write_fmt(format_args!("&{0}", mutbl.prefix_str()))write!(f, "&{}", mutbl.prefix_str())?;
128 }
129 _ => ::rustc_middle::util::bug::bug_fmt(format_args!("{0} is a bad ref pattern type",
ty))bug!("{ty} is a bad ref pattern type"),
130 }
131 f.write_fmt(format_args!("{0}", subpattern))write!(f, "{subpattern}")
132}
133
134pub(crate) fn write_slice_like(
135 f: &mut impl fmt::Write,
136 prefix: &[String],
137 has_dot_dot: bool,
138 suffix: &[String],
139) -> fmt::Result {
140 let mut start_or_comma = start_or_comma();
141 f.write_fmt(format_args!("["))write!(f, "[")?;
142 for p in prefix.iter() {
143 f.write_fmt(format_args!("{0}{1}", start_or_comma(), p))write!(f, "{}{}", start_or_comma(), p)?;
144 }
145 if has_dot_dot {
146 f.write_fmt(format_args!("{0}..", start_or_comma()))write!(f, "{}..", start_or_comma())?;
147 }
148 for p in suffix.iter() {
149 f.write_fmt(format_args!("{0}{1}", start_or_comma(), p))write!(f, "{}{}", start_or_comma(), p)?;
150 }
151 f.write_fmt(format_args!("]"))write!(f, "]")
152}