1 use crate::ptr::P; 2 use crate::Expr; 3 use rustc_data_structures::fx::FxHashMap; 4 use rustc_span::symbol::{Ident, Symbol}; 5 use rustc_span::Span; 6 7 // Definitions: 8 // 9 // format_args!("hello {abc:.xyz$}!!", abc="world"); 10 // └──────────────────────────────────────────────┘ 11 // FormatArgs 12 // 13 // format_args!("hello {abc:.xyz$}!!", abc="world"); 14 // └─────────┘ 15 // argument 16 // 17 // format_args!("hello {abc:.xyz$}!!", abc="world"); 18 // └───────────────────┘ 19 // template 20 // 21 // format_args!("hello {abc:.xyz$}!!", abc="world"); 22 // └────┘└─────────┘└┘ 23 // pieces 24 // 25 // format_args!("hello {abc:.xyz$}!!", abc="world"); 26 // └────┘ └┘ 27 // literal pieces 28 // 29 // format_args!("hello {abc:.xyz$}!!", abc="world"); 30 // └─────────┘ 31 // placeholder 32 // 33 // format_args!("hello {abc:.xyz$}!!", abc="world"); 34 // └─┘ └─┘ 35 // positions (could be names, numbers, empty, or `*`) 36 37 /// (Parsed) format args. 38 /// 39 /// Basically the "AST" for a complete `format_args!()`. 40 /// 41 /// E.g., `format_args!("hello {name}");`. 42 #[derive(Clone, Encodable, Decodable, Debug)] 43 pub struct FormatArgs { 44 pub span: Span, 45 pub template: Vec<FormatArgsPiece>, 46 pub arguments: FormatArguments, 47 } 48 49 /// A piece of a format template string. 50 /// 51 /// E.g. "hello" or "{name}". 52 #[derive(Clone, Encodable, Decodable, Debug)] 53 pub enum FormatArgsPiece { 54 Literal(Symbol), 55 Placeholder(FormatPlaceholder), 56 } 57 58 /// The arguments to format_args!(). 59 /// 60 /// E.g. `1, 2, name="ferris", n=3`, 61 /// but also implicit captured arguments like `x` in `format_args!("{x}")`. 62 #[derive(Clone, Encodable, Decodable, Debug)] 63 pub struct FormatArguments { 64 arguments: Vec<FormatArgument>, 65 num_unnamed_args: usize, 66 num_explicit_args: usize, 67 names: FxHashMap<Symbol, usize>, 68 } 69 70 // FIXME: Rustdoc has trouble proving Send/Sync for this. See #106930. 71 #[cfg(parallel_compiler)] 72 unsafe impl Sync for FormatArguments {} 73 #[cfg(parallel_compiler)] 74 unsafe impl Send for FormatArguments {} 75 76 impl FormatArguments { new() -> Self77 pub fn new() -> Self { 78 Self { 79 arguments: Vec::new(), 80 names: FxHashMap::default(), 81 num_unnamed_args: 0, 82 num_explicit_args: 0, 83 } 84 } 85 add(&mut self, arg: FormatArgument) -> usize86 pub fn add(&mut self, arg: FormatArgument) -> usize { 87 let index = self.arguments.len(); 88 if let Some(name) = arg.kind.ident() { 89 self.names.insert(name.name, index); 90 } else if self.names.is_empty() { 91 // Only count the unnamed args before the first named arg. 92 // (Any later ones are errors.) 93 self.num_unnamed_args += 1; 94 } 95 if !matches!(arg.kind, FormatArgumentKind::Captured(..)) { 96 // This is an explicit argument. 97 // Make sure that all arguments so far are explicit. 98 assert_eq!( 99 self.num_explicit_args, 100 self.arguments.len(), 101 "captured arguments must be added last" 102 ); 103 self.num_explicit_args += 1; 104 } 105 self.arguments.push(arg); 106 index 107 } 108 by_name(&self, name: Symbol) -> Option<(usize, &FormatArgument)>109 pub fn by_name(&self, name: Symbol) -> Option<(usize, &FormatArgument)> { 110 let i = *self.names.get(&name)?; 111 Some((i, &self.arguments[i])) 112 } 113 by_index(&self, i: usize) -> Option<&FormatArgument>114 pub fn by_index(&self, i: usize) -> Option<&FormatArgument> { 115 (i < self.num_explicit_args).then(|| &self.arguments[i]) 116 } 117 unnamed_args(&self) -> &[FormatArgument]118 pub fn unnamed_args(&self) -> &[FormatArgument] { 119 &self.arguments[..self.num_unnamed_args] 120 } 121 named_args(&self) -> &[FormatArgument]122 pub fn named_args(&self) -> &[FormatArgument] { 123 &self.arguments[self.num_unnamed_args..self.num_explicit_args] 124 } 125 explicit_args(&self) -> &[FormatArgument]126 pub fn explicit_args(&self) -> &[FormatArgument] { 127 &self.arguments[..self.num_explicit_args] 128 } 129 all_args(&self) -> &[FormatArgument]130 pub fn all_args(&self) -> &[FormatArgument] { 131 &self.arguments[..] 132 } 133 all_args_mut(&mut self) -> &mut Vec<FormatArgument>134 pub fn all_args_mut(&mut self) -> &mut Vec<FormatArgument> { 135 &mut self.arguments 136 } 137 } 138 139 #[derive(Clone, Encodable, Decodable, Debug)] 140 pub struct FormatArgument { 141 pub kind: FormatArgumentKind, 142 pub expr: P<Expr>, 143 } 144 145 #[derive(Clone, Encodable, Decodable, Debug)] 146 pub enum FormatArgumentKind { 147 /// `format_args(…, arg)` 148 Normal, 149 /// `format_args(…, arg = 1)` 150 Named(Ident), 151 /// `format_args("… {arg} …")` 152 Captured(Ident), 153 } 154 155 impl FormatArgumentKind { ident(&self) -> Option<Ident>156 pub fn ident(&self) -> Option<Ident> { 157 match self { 158 &Self::Normal => None, 159 &Self::Named(id) => Some(id), 160 &Self::Captured(id) => Some(id), 161 } 162 } 163 } 164 165 #[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)] 166 pub struct FormatPlaceholder { 167 /// Index into [`FormatArgs::arguments`]. 168 pub argument: FormatArgPosition, 169 /// The span inside the format string for the full `{…}` placeholder. 170 pub span: Option<Span>, 171 /// `{}`, `{:?}`, or `{:x}`, etc. 172 pub format_trait: FormatTrait, 173 /// `{}` or `{:.5}` or `{:-^20}`, etc. 174 pub format_options: FormatOptions, 175 } 176 177 #[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)] 178 pub struct FormatArgPosition { 179 /// Which argument this position refers to (Ok), 180 /// or would've referred to if it existed (Err). 181 pub index: Result<usize, usize>, 182 /// What kind of position this is. See [`FormatArgPositionKind`]. 183 pub kind: FormatArgPositionKind, 184 /// The span of the name or number. 185 pub span: Option<Span>, 186 } 187 188 #[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq)] 189 pub enum FormatArgPositionKind { 190 /// `{}` or `{:.*}` 191 Implicit, 192 /// `{1}` or `{:1$}` or `{:.1$}` 193 Number, 194 /// `{a}` or `{:a$}` or `{:.a$}` 195 Named, 196 } 197 198 #[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq, Hash)] 199 pub enum FormatTrait { 200 /// `{}` 201 Display, 202 /// `{:?}` 203 Debug, 204 /// `{:e}` 205 LowerExp, 206 /// `{:E}` 207 UpperExp, 208 /// `{:o}` 209 Octal, 210 /// `{:p}` 211 Pointer, 212 /// `{:b}` 213 Binary, 214 /// `{:x}` 215 LowerHex, 216 /// `{:X}` 217 UpperHex, 218 } 219 220 #[derive(Clone, Encodable, Decodable, Default, Debug, PartialEq, Eq)] 221 pub struct FormatOptions { 222 /// The width. E.g. `{:5}` or `{:width$}`. 223 pub width: Option<FormatCount>, 224 /// The precision. E.g. `{:.5}` or `{:.precision$}`. 225 pub precision: Option<FormatCount>, 226 /// The alignment. E.g. `{:>}` or `{:<}` or `{:^}`. 227 pub alignment: Option<FormatAlignment>, 228 /// The fill character. E.g. the `.` in `{:.>10}`. 229 pub fill: Option<char>, 230 /// The `+` or `-` flag. 231 pub sign: Option<FormatSign>, 232 /// The `#` flag. 233 pub alternate: bool, 234 /// The `0` flag. E.g. the `0` in `{:02x}`. 235 pub zero_pad: bool, 236 /// The `x` or `X` flag (for `Debug` only). E.g. the `x` in `{:x?}`. 237 pub debug_hex: Option<FormatDebugHex>, 238 } 239 240 #[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq)] 241 pub enum FormatSign { 242 /// The `+` flag. 243 Plus, 244 /// The `-` flag. 245 Minus, 246 } 247 248 #[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq)] 249 pub enum FormatDebugHex { 250 /// The `x` flag in `{:x?}`. 251 Lower, 252 /// The `X` flag in `{:X?}`. 253 Upper, 254 } 255 256 #[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq)] 257 pub enum FormatAlignment { 258 /// `{:<}` 259 Left, 260 /// `{:>}` 261 Right, 262 /// `{:^}` 263 Center, 264 } 265 266 #[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)] 267 pub enum FormatCount { 268 /// `{:5}` or `{:.5}` 269 Literal(usize), 270 /// `{:.*}`, `{:.5$}`, or `{:a$}`, etc. 271 Argument(FormatArgPosition), 272 } 273