Skip to content

Commit dc13072

Browse files
Use Symbol for named arguments in fmt_macros
1 parent 7795b15 commit dc13072

File tree

7 files changed

+79
-61
lines changed

7 files changed

+79
-61
lines changed

Cargo.lock

+3
Original file line numberDiff line numberDiff line change
@@ -910,6 +910,9 @@ dependencies = [
910910
[[package]]
911911
name = "fmt_macros"
912912
version = "0.0.0"
913+
dependencies = [
914+
"syntax_pos 0.0.0",
915+
]
913916

914917
[[package]]
915918
name = "fnv"

src/libfmt_macros/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,6 @@ edition = "2018"
88
name = "fmt_macros"
99
path = "lib.rs"
1010
crate-type = ["dylib"]
11+
12+
[dependencies]
13+
syntax_pos = { path = "../libsyntax_pos" }

src/libfmt_macros/lib.rs

+22-15
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ use std::str;
2424
use std::string;
2525
use std::iter;
2626

27+
use syntax_pos::Symbol;
28+
2729
/// A piece is a portion of the format string which represents the next part
2830
/// to emit. These are emitted as a stream by the `Parser` class.
2931
#[derive(Copy, Clone, PartialEq)]
@@ -39,7 +41,7 @@ pub enum Piece<'a> {
3941
#[derive(Copy, Clone, PartialEq)]
4042
pub struct Argument<'a> {
4143
/// Where to find this argument
42-
pub position: Position<'a>,
44+
pub position: Position,
4345
/// How to format the argument
4446
pub format: FormatSpec<'a>,
4547
}
@@ -54,9 +56,9 @@ pub struct FormatSpec<'a> {
5456
/// Packed version of various flags provided
5557
pub flags: u32,
5658
/// The integer precision to use
57-
pub precision: Count<'a>,
59+
pub precision: Count,
5860
/// The string width requested for the resulting format
59-
pub width: Count<'a>,
61+
pub width: Count,
6062
/// The descriptor string representing the name of the format desired for
6163
/// this argument, this can be empty or any number of characters, although
6264
/// it is required to be one word.
@@ -65,16 +67,16 @@ pub struct FormatSpec<'a> {
6567

6668
/// Enum describing where an argument for a format can be located.
6769
#[derive(Copy, Clone, PartialEq)]
68-
pub enum Position<'a> {
70+
pub enum Position {
6971
/// The argument is implied to be located at an index
7072
ArgumentImplicitlyIs(usize),
7173
/// The argument is located at a specific index given in the format
7274
ArgumentIs(usize),
7375
/// The argument has a name.
74-
ArgumentNamed(&'a str),
76+
ArgumentNamed(Symbol),
7577
}
7678

77-
impl Position<'_> {
79+
impl Position {
7880
pub fn index(&self) -> Option<usize> {
7981
match self {
8082
ArgumentIs(i) | ArgumentImplicitlyIs(i) => Some(*i),
@@ -119,11 +121,11 @@ pub enum Flag {
119121
/// A count is used for the precision and width parameters of an integer, and
120122
/// can reference either an argument or a literal integer.
121123
#[derive(Copy, Clone, PartialEq)]
122-
pub enum Count<'a> {
124+
pub enum Count {
123125
/// The count is specified explicitly.
124126
CountIs(usize),
125127
/// The count is specified by the argument with the given name.
126-
CountIsName(&'a str),
128+
CountIsName(Symbol),
127129
/// The count is specified by the argument at the given index.
128130
CountIsParam(usize),
129131
/// The count is implied and cannot be explicitly specified.
@@ -431,20 +433,22 @@ impl<'a> Parser<'a> {
431433
/// integer index of an argument, a named argument, or a blank string.
432434
/// Returns `Some(parsed_position)` if the position is not implicitly
433435
/// consuming a macro argument, `None` if it's the case.
434-
fn position(&mut self) -> Option<Position<'a>> {
436+
fn position(&mut self) -> Option<Position> {
435437
if let Some(i) = self.integer() {
436438
Some(ArgumentIs(i))
437439
} else {
438440
match self.cur.peek() {
439-
Some(&(_, c)) if c.is_alphabetic() => Some(ArgumentNamed(self.word())),
441+
Some(&(_, c)) if c.is_alphabetic() => {
442+
Some(ArgumentNamed(Symbol::intern(self.word())))
443+
}
440444
Some(&(pos, c)) if c == '_' => {
441445
let invalid_name = self.string(pos);
442446
self.err_with_note(format!("invalid argument name `{}`", invalid_name),
443447
"invalid argument name",
444448
"argument names cannot start with an underscore",
445449
self.to_span_index(pos),
446450
self.to_span_index(pos + invalid_name.len()));
447-
Some(ArgumentNamed(invalid_name))
451+
Some(ArgumentNamed(Symbol::intern(invalid_name)))
448452
},
449453

450454
// This is an `ArgumentNext`.
@@ -552,7 +556,7 @@ impl<'a> Parser<'a> {
552556
/// Parses a Count parameter at the current position. This does not check
553557
/// for 'CountIsNextParam' because that is only used in precision, not
554558
/// width.
555-
fn count(&mut self) -> Count<'a> {
559+
fn count(&mut self) -> Count {
556560
if let Some(i) = self.integer() {
557561
if self.consume('$') {
558562
CountIsParam(i)
@@ -566,7 +570,7 @@ impl<'a> Parser<'a> {
566570
self.cur = tmp;
567571
CountImplied
568572
} else if self.consume('$') {
569-
CountIsName(word)
573+
CountIsName(Symbol::intern(word))
570574
} else {
571575
self.cur = tmp;
572576
CountImplied
@@ -756,6 +760,8 @@ mod tests {
756760
}
757761
#[test]
758762
fn format_counts() {
763+
use syntax_pos::{GLOBALS, Globals, edition};
764+
GLOBALS.set(&Globals::new(edition::DEFAULT_EDITION), || {
759765
same("{:10s}",
760766
&[NextArgument(Argument {
761767
position: ArgumentImplicitlyIs(0),
@@ -811,11 +817,12 @@ mod tests {
811817
fill: None,
812818
align: AlignUnknown,
813819
flags: 0,
814-
precision: CountIsName("b"),
815-
width: CountIsName("a"),
820+
precision: CountIsName(Symbol::intern("b")),
821+
width: CountIsName(Symbol::intern("a")),
816822
ty: "s",
817823
},
818824
})]);
825+
});
819826
}
820827
#[test]
821828
fn format_flags() {

src/librustc/traits/error_reporting.rs

+16-16
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
353353
_ => {
354354
// this is a "direct", user-specified, rather than derived,
355355
// obligation.
356-
flags.push(("direct".to_owned(), None));
356+
flags.push((sym::direct, None));
357357
}
358358
}
359359

@@ -365,27 +365,27 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
365365
// Currently I'm leaving it for what I need for `try`.
366366
if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) {
367367
let method = self.tcx.item_name(item);
368-
flags.push(("from_method".to_owned(), None));
369-
flags.push(("from_method".to_owned(), Some(method.to_string())));
368+
flags.push((sym::from_method, None));
369+
flags.push((sym::from_method, Some(method.to_string())));
370370
}
371371
}
372372
if let Some(t) = self.get_parent_trait_ref(&obligation.cause.code) {
373-
flags.push(("parent_trait".to_owned(), Some(t)));
373+
flags.push((sym::parent_trait, Some(t)));
374374
}
375375

376376
if let Some(k) = obligation.cause.span.compiler_desugaring_kind() {
377-
flags.push(("from_desugaring".to_owned(), None));
378-
flags.push(("from_desugaring".to_owned(), Some(k.name().to_string())));
377+
flags.push((sym::from_desugaring, None));
378+
flags.push((sym::from_desugaring, Some(k.name().to_string())));
379379
}
380380
let generics = self.tcx.generics_of(def_id);
381381
let self_ty = trait_ref.self_ty();
382382
// This is also included through the generics list as `Self`,
383383
// but the parser won't allow you to use it
384-
flags.push(("_Self".to_owned(), Some(self_ty.to_string())));
384+
flags.push((sym::_Self, Some(self_ty.to_string())));
385385
if let Some(def) = self_ty.ty_adt_def() {
386386
// We also want to be able to select self's original
387387
// signature with no type arguments resolved
388-
flags.push(("_Self".to_owned(), Some(self.tcx.type_of(def.did).to_string())));
388+
flags.push((sym::_Self, Some(self.tcx.type_of(def.did).to_string())));
389389
}
390390

391391
for param in generics.params.iter() {
@@ -396,38 +396,38 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
396396
},
397397
GenericParamDefKind::Lifetime => continue,
398398
};
399-
let name = param.name.to_string();
399+
let name = param.name.as_symbol();
400400
flags.push((name, Some(value)));
401401
}
402402

403403
if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) {
404-
flags.push(("crate_local".to_owned(), None));
404+
flags.push((sym::crate_local, None));
405405
}
406406

407407
// Allow targeting all integers using `{integral}`, even if the exact type was resolved
408408
if self_ty.is_integral() {
409-
flags.push(("_Self".to_owned(), Some("{integral}".to_owned())));
409+
flags.push((sym::_Self, Some("{integral}".to_owned())));
410410
}
411411

412412
if let ty::Array(aty, len) = self_ty.sty {
413-
flags.push(("_Self".to_owned(), Some("[]".to_owned())));
414-
flags.push(("_Self".to_owned(), Some(format!("[{}]", aty))));
413+
flags.push((sym::_Self, Some("[]".to_owned())));
414+
flags.push((sym::_Self, Some(format!("[{}]", aty))));
415415
if let Some(def) = aty.ty_adt_def() {
416416
// We also want to be able to select the array's type's original
417417
// signature with no type arguments resolved
418418
flags.push((
419-
"_Self".to_owned(),
419+
sym::_Self,
420420
Some(format!("[{}]", self.tcx.type_of(def.did).to_string())),
421421
));
422422
let tcx = self.tcx;
423423
if let Some(len) = len.assert_usize(tcx) {
424424
flags.push((
425-
"_Self".to_owned(),
425+
sym::_Self,
426426
Some(format!("[{}; {}]", self.tcx.type_of(def.did).to_string(), len)),
427427
));
428428
} else {
429429
flags.push((
430-
"_Self".to_owned(),
430+
sym::_Self,
431431
Some(format!("[{}; _]", self.tcx.type_of(def.did).to_string())),
432432
));
433433
}

src/librustc/traits/on_unimplemented.rs

+17-17
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::util::nodemap::FxHashMap;
77

88
use syntax::ast::{MetaItem, NestedMetaItem};
99
use syntax::attr;
10-
use syntax::symbol::sym;
10+
use syntax::symbol::{Symbol, kw, sym};
1111
use syntax_pos::Span;
1212
use syntax_pos::symbol::LocalInternedString;
1313

@@ -167,7 +167,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
167167
pub fn evaluate(&self,
168168
tcx: TyCtxt<'a, 'gcx, 'tcx>,
169169
trait_ref: ty::TraitRef<'tcx>,
170-
options: &[(String, Option<String>)])
170+
options: &[(Symbol, Option<String>)])
171171
-> OnUnimplementedNote
172172
{
173173
let mut message = None;
@@ -180,7 +180,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
180180
if !attr::eval_condition(condition, &tcx.sess.parse_sess, &mut |c| {
181181
c.ident().map_or(false, |ident| {
182182
options.contains(&(
183-
ident.to_string(),
183+
ident.name,
184184
c.value_str().map(|s| s.as_str().to_string())
185185
))
186186
})
@@ -203,8 +203,8 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
203203
}
204204
}
205205

206-
let options: FxHashMap<String, String> = options.into_iter()
207-
.filter_map(|(k, v)| v.as_ref().map(|v| (k.to_owned(), v.to_owned())))
206+
let options: FxHashMap<Symbol, String> = options.into_iter()
207+
.filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned())))
208208
.collect();
209209
OnUnimplementedNote {
210210
label: label.map(|l| l.format(tcx, trait_ref, &options)),
@@ -241,16 +241,16 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
241241
Piece::String(_) => (), // Normal string, no need to check it
242242
Piece::NextArgument(a) => match a.position {
243243
// `{Self}` is allowed
244-
Position::ArgumentNamed(s) if s == "Self" => (),
244+
Position::ArgumentNamed(s) if s == kw::SelfUpper => (),
245245
// `{ThisTraitsName}` is allowed
246-
Position::ArgumentNamed(s) if s == name.as_str() => (),
246+
Position::ArgumentNamed(s) if s == name => (),
247247
// `{from_method}` is allowed
248-
Position::ArgumentNamed(s) if s == "from_method" => (),
248+
Position::ArgumentNamed(s) if s == sym::from_method => (),
249249
// `{from_desugaring}` is allowed
250-
Position::ArgumentNamed(s) if s == "from_desugaring" => (),
250+
Position::ArgumentNamed(s) if s == sym::from_desugaring => (),
251251
// So is `{A}` if A is a type parameter
252252
Position::ArgumentNamed(s) => match generics.params.iter().find(|param| {
253-
param.name.as_str() == s
253+
param.name.as_symbol() == s
254254
}) {
255255
Some(_) => (),
256256
None => {
@@ -276,7 +276,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
276276
&self,
277277
tcx: TyCtxt<'a, 'gcx, 'tcx>,
278278
trait_ref: ty::TraitRef<'tcx>,
279-
options: &FxHashMap<String, String>,
279+
options: &FxHashMap<Symbol, String>,
280280
) -> String {
281281
let name = tcx.item_name(trait_ref.def_id);
282282
let trait_str = tcx.def_path_str(trait_ref.def_id);
@@ -289,25 +289,25 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
289289
},
290290
GenericParamDefKind::Lifetime => return None
291291
};
292-
let name = param.name.to_string();
292+
let name = param.name.as_symbol();
293293
Some((name, value))
294-
}).collect::<FxHashMap<String, String>>();
294+
}).collect::<FxHashMap<Symbol, String>>();
295295
let empty_string = String::new();
296296

297297
let parser = Parser::new(&self.0, None, vec![], false);
298298
parser.map(|p|
299299
match p {
300300
Piece::String(s) => s,
301301
Piece::NextArgument(a) => match a.position {
302-
Position::ArgumentNamed(s) => match generic_map.get(s) {
302+
Position::ArgumentNamed(s) => match generic_map.get(&s) {
303303
Some(val) => val,
304-
None if s == name.as_str() => {
304+
None if s == name => {
305305
&trait_str
306306
}
307307
None => {
308-
if let Some(val) = options.get(s) {
308+
if let Some(val) = options.get(&s) {
309309
val
310-
} else if s == "from_desugaring" || s == "from_method" {
310+
} else if s == sym::from_desugaring || s == sym::from_method {
311311
// don't break messages using these two arguments incorrectly
312312
&empty_string
313313
} else {

0 commit comments

Comments
 (0)