diff --git a/Cargo.lock b/Cargo.lock index 7f35b7344dfed..73605af7936f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -910,6 +910,9 @@ dependencies = [ [[package]] name = "fmt_macros" version = "0.0.0" +dependencies = [ + "syntax_pos 0.0.0", +] [[package]] name = "fnv" diff --git a/src/libfmt_macros/Cargo.toml b/src/libfmt_macros/Cargo.toml index 50779a2d9ad08..fc32f21ec4e0a 100644 --- a/src/libfmt_macros/Cargo.toml +++ b/src/libfmt_macros/Cargo.toml @@ -8,3 +8,6 @@ edition = "2018" name = "fmt_macros" path = "lib.rs" crate-type = ["dylib"] + +[dependencies] +syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 6fed83021609d..b851183debfc5 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -24,6 +24,17 @@ use std::str; use std::string; use std::iter; +use syntax_pos::{InnerSpan, Symbol}; + +#[derive(Copy, Clone)] +struct InnerOffset(usize); + +impl InnerOffset { + fn to(self, end: InnerOffset) -> InnerSpan { + InnerSpan::new(self.0, end.0) + } +} + /// A piece is a portion of the format string which represents the next part /// to emit. These are emitted as a stream by the `Parser` class. #[derive(Copy, Clone, PartialEq)] @@ -39,7 +50,7 @@ pub enum Piece<'a> { #[derive(Copy, Clone, PartialEq)] pub struct Argument<'a> { /// Where to find this argument - pub position: Position<'a>, + pub position: Position, /// How to format the argument pub format: FormatSpec<'a>, } @@ -54,9 +65,9 @@ pub struct FormatSpec<'a> { /// Packed version of various flags provided pub flags: u32, /// The integer precision to use - pub precision: Count<'a>, + pub precision: Count, /// The string width requested for the resulting format - pub width: Count<'a>, + pub width: Count, /// The descriptor string representing the name of the format desired for /// this argument, this can be empty or any number of characters, although /// it is required to be one word. @@ -65,16 +76,16 @@ pub struct FormatSpec<'a> { /// Enum describing where an argument for a format can be located. #[derive(Copy, Clone, PartialEq)] -pub enum Position<'a> { +pub enum Position { /// The argument is implied to be located at an index ArgumentImplicitlyIs(usize), /// The argument is located at a specific index given in the format ArgumentIs(usize), /// The argument has a name. - ArgumentNamed(&'a str), + ArgumentNamed(Symbol), } -impl Position<'_> { +impl Position { pub fn index(&self) -> Option { match self { ArgumentIs(i) | ArgumentImplicitlyIs(i) => Some(*i), @@ -119,11 +130,11 @@ pub enum Flag { /// A count is used for the precision and width parameters of an integer, and /// can reference either an argument or a literal integer. #[derive(Copy, Clone, PartialEq)] -pub enum Count<'a> { +pub enum Count { /// The count is specified explicitly. CountIs(usize), /// The count is specified by the argument with the given name. - CountIsName(&'a str), + CountIsName(Symbol), /// The count is specified by the argument at the given index. CountIsParam(usize), /// The count is implied and cannot be explicitly specified. @@ -134,9 +145,8 @@ pub struct ParseError { pub description: string::String, pub note: Option, pub label: string::String, - pub start: SpanIndex, - pub end: SpanIndex, - pub secondary_label: Option<(string::String, SpanIndex, SpanIndex)>, + pub span: InnerSpan, + pub secondary_label: Option<(string::String, InnerSpan)>, } /// The parser structure for interpreting the input format string. This is @@ -155,24 +165,15 @@ pub struct Parser<'a> { /// `Some(raw count)` when the string is "raw", used to position spans correctly style: Option, /// Start and end byte offset of every successfully parsed argument - pub arg_places: Vec<(SpanIndex, SpanIndex)>, + pub arg_places: Vec, /// Characters that need to be shifted skips: Vec, - /// Span offset of the last opening brace seen, used for error reporting - last_opening_brace_pos: Option, + /// Span of the last opening brace seen, used for error reporting + last_opening_brace: Option, /// Wether the source string is comes from `println!` as opposed to `format!` or `print!` append_newline: bool, } -#[derive(Clone, Copy, Debug)] -pub struct SpanIndex(pub usize); - -impl SpanIndex { - pub fn unwrap(self) -> usize { - self.0 - } -} - impl<'a> Iterator for Parser<'a> { type Item = Piece<'a>; @@ -180,19 +181,20 @@ impl<'a> Iterator for Parser<'a> { if let Some(&(pos, c)) = self.cur.peek() { match c { '{' => { - let curr_last_brace = self.last_opening_brace_pos; - self.last_opening_brace_pos = Some(self.to_span_index(pos)); + let curr_last_brace = self.last_opening_brace; + let byte_pos = self.to_span_index(pos); + self.last_opening_brace = Some(byte_pos.to(InnerOffset(byte_pos.0 + 1))); self.cur.next(); if self.consume('{') { - self.last_opening_brace_pos = curr_last_brace; + self.last_opening_brace = curr_last_brace; Some(String(self.string(pos + 1))) } else { let arg = self.argument(); - if let Some(arg_pos) = self.must_consume('}').map(|end| { - (self.to_span_index(pos), self.to_span_index(end + 1)) - }) { - self.arg_places.push(arg_pos); + if let Some(end) = self.must_consume('}') { + let start = self.to_span_index(pos); + let end = self.to_span_index(end + 1); + self.arg_places.push(start.to(end)); } Some(NextArgument(arg)) } @@ -207,8 +209,7 @@ impl<'a> Iterator for Parser<'a> { "unmatched `}` found", "unmatched `}`", "if you intended to print `}`, you can escape it using `}}`", - err_pos, - err_pos, + err_pos.to(err_pos), ); None } @@ -240,7 +241,7 @@ impl<'a> Parser<'a> { style, arg_places: vec![], skips, - last_opening_brace_pos: None, + last_opening_brace: None, append_newline, } } @@ -252,15 +253,13 @@ impl<'a> Parser<'a> { &mut self, description: S1, label: S2, - start: SpanIndex, - end: SpanIndex, + span: InnerSpan, ) { self.errors.push(ParseError { description: description.into(), note: None, label: label.into(), - start, - end, + span, secondary_label: None, }); } @@ -273,15 +272,13 @@ impl<'a> Parser<'a> { description: S1, label: S2, note: S3, - start: SpanIndex, - end: SpanIndex, + span: InnerSpan, ) { self.errors.push(ParseError { description: description.into(), note: Some(note.into()), label: label.into(), - start, - end, + span, secondary_label: None, }); } @@ -302,22 +299,21 @@ impl<'a> Parser<'a> { } } - fn raw(&self) -> usize { - self.style.map(|raw| raw + 1).unwrap_or(0) - } - - fn to_span_index(&self, pos: usize) -> SpanIndex { + fn to_span_index(&self, pos: usize) -> InnerOffset { let mut pos = pos; + // This handles the raw string case, the raw argument is the number of # + // in r###"..."### (we need to add one because of the `r`). + let raw = self.style.map(|raw| raw + 1).unwrap_or(0); for skip in &self.skips { if pos > *skip { pos += 1; - } else if pos == *skip && self.raw() == 0 { + } else if pos == *skip && raw == 0 { pos += 1; } else { break; } } - SpanIndex(self.raw() + pos + 1) + InnerOffset(raw + pos + 1) } /// Forces consumption of the specified character. If the character is not @@ -335,8 +331,8 @@ impl<'a> Parser<'a> { let label = "expected `}`".to_owned(); let (note, secondary_label) = if c == '}' { (Some("if you intended to print `{`, you can escape it using `{{`".to_owned()), - self.last_opening_brace_pos.map(|pos| { - ("because of this opening brace".to_owned(), pos, pos) + self.last_opening_brace.map(|sp| { + ("because of this opening brace".to_owned(), sp) })) } else { (None, None) @@ -345,8 +341,7 @@ impl<'a> Parser<'a> { description, note, label, - start: pos, - end: pos, + span: pos.to(pos), secondary_label, }); None @@ -360,8 +355,8 @@ impl<'a> Parser<'a> { let label = format!("expected `{:?}`", c); let (note, secondary_label) = if c == '}' { (Some("if you intended to print `{`, you can escape it using `{{`".to_owned()), - self.last_opening_brace_pos.map(|pos| { - ("because of this opening brace".to_owned(), pos, pos) + self.last_opening_brace.map(|sp| { + ("because of this opening brace".to_owned(), sp) })) } else { (None, None) @@ -370,12 +365,11 @@ impl<'a> Parser<'a> { description, note, label, - start: pos, - end: pos, + span: pos.to(pos), secondary_label, }); } else { - self.err(description, format!("expected `{:?}`", c), pos, pos); + self.err(description, format!("expected `{:?}`", c), pos.to(pos)); } None } @@ -434,20 +428,24 @@ impl<'a> Parser<'a> { /// integer index of an argument, a named argument, or a blank string. /// Returns `Some(parsed_position)` if the position is not implicitly /// consuming a macro argument, `None` if it's the case. - fn position(&mut self) -> Option> { + fn position(&mut self) -> Option { if let Some(i) = self.integer() { Some(ArgumentIs(i)) } else { match self.cur.peek() { - Some(&(_, c)) if c.is_alphabetic() => Some(ArgumentNamed(self.word())), + Some(&(_, c)) if c.is_alphabetic() => { + Some(ArgumentNamed(Symbol::intern(self.word()))) + } Some(&(pos, c)) if c == '_' => { let invalid_name = self.string(pos); self.err_with_note(format!("invalid argument name `{}`", invalid_name), "invalid argument name", "argument names cannot start with an underscore", - self.to_span_index(pos), - self.to_span_index(pos + invalid_name.len())); - Some(ArgumentNamed(invalid_name)) + self.to_span_index(pos).to( + self.to_span_index(pos + invalid_name.len()) + ), + ); + Some(ArgumentNamed(Symbol::intern(invalid_name))) }, // This is an `ArgumentNext`. @@ -555,7 +553,7 @@ impl<'a> Parser<'a> { /// Parses a Count parameter at the current position. This does not check /// for 'CountIsNextParam' because that is only used in precision, not /// width. - fn count(&mut self) -> Count<'a> { + fn count(&mut self) -> Count { if let Some(i) = self.integer() { if self.consume('$') { CountIsParam(i) @@ -569,7 +567,7 @@ impl<'a> Parser<'a> { self.cur = tmp; CountImplied } else if self.consume('$') { - CountIsName(word) + CountIsName(Symbol::intern(word)) } else { self.cur = tmp; CountImplied @@ -759,6 +757,8 @@ mod tests { } #[test] fn format_counts() { + use syntax_pos::{GLOBALS, Globals, edition}; + GLOBALS.set(&Globals::new(edition::DEFAULT_EDITION), || { same("{:10s}", &[NextArgument(Argument { position: ArgumentImplicitlyIs(0), @@ -814,11 +814,12 @@ mod tests { fill: None, align: AlignUnknown, flags: 0, - precision: CountIsName("b"), - width: CountIsName("a"), + precision: CountIsName(Symbol::intern("b")), + width: CountIsName(Symbol::intern("a")), ty: "s", }, })]); + }); } #[test] fn format_flags() { diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 490501bde73e5..50d2eeef421c1 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -353,7 +353,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { _ => { // this is a "direct", user-specified, rather than derived, // obligation. - flags.push(("direct".to_owned(), None)); + flags.push((sym::direct, None)); } } @@ -365,27 +365,27 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // Currently I'm leaving it for what I need for `try`. if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) { let method = self.tcx.item_name(item); - flags.push(("from_method".to_owned(), None)); - flags.push(("from_method".to_owned(), Some(method.to_string()))); + flags.push((sym::from_method, None)); + flags.push((sym::from_method, Some(method.to_string()))); } } if let Some(t) = self.get_parent_trait_ref(&obligation.cause.code) { - flags.push(("parent_trait".to_owned(), Some(t))); + flags.push((sym::parent_trait, Some(t))); } if let Some(k) = obligation.cause.span.compiler_desugaring_kind() { - flags.push(("from_desugaring".to_owned(), None)); - flags.push(("from_desugaring".to_owned(), Some(k.name().to_string()))); + flags.push((sym::from_desugaring, None)); + flags.push((sym::from_desugaring, Some(k.name().to_string()))); } let generics = self.tcx.generics_of(def_id); let self_ty = trait_ref.self_ty(); // This is also included through the generics list as `Self`, // but the parser won't allow you to use it - flags.push(("_Self".to_owned(), Some(self_ty.to_string()))); + flags.push((sym::_Self, Some(self_ty.to_string()))); if let Some(def) = self_ty.ty_adt_def() { // We also want to be able to select self's original // signature with no type arguments resolved - flags.push(("_Self".to_owned(), Some(self.tcx.type_of(def.did).to_string()))); + flags.push((sym::_Self, Some(self.tcx.type_of(def.did).to_string()))); } for param in generics.params.iter() { @@ -396,38 +396,38 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { }, GenericParamDefKind::Lifetime => continue, }; - let name = param.name.to_string(); + let name = param.name.as_symbol(); flags.push((name, Some(value))); } if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) { - flags.push(("crate_local".to_owned(), None)); + flags.push((sym::crate_local, None)); } // Allow targeting all integers using `{integral}`, even if the exact type was resolved if self_ty.is_integral() { - flags.push(("_Self".to_owned(), Some("{integral}".to_owned()))); + flags.push((sym::_Self, Some("{integral}".to_owned()))); } if let ty::Array(aty, len) = self_ty.sty { - flags.push(("_Self".to_owned(), Some("[]".to_owned()))); - flags.push(("_Self".to_owned(), Some(format!("[{}]", aty)))); + flags.push((sym::_Self, Some("[]".to_owned()))); + flags.push((sym::_Self, Some(format!("[{}]", aty)))); if let Some(def) = aty.ty_adt_def() { // We also want to be able to select the array's type's original // signature with no type arguments resolved flags.push(( - "_Self".to_owned(), + sym::_Self, Some(format!("[{}]", self.tcx.type_of(def.did).to_string())), )); let tcx = self.tcx; if let Some(len) = len.assert_usize(tcx) { flags.push(( - "_Self".to_owned(), + sym::_Self, Some(format!("[{}; {}]", self.tcx.type_of(def.did).to_string(), len)), )); } else { flags.push(( - "_Self".to_owned(), + sym::_Self, Some(format!("[{}; _]", self.tcx.type_of(def.did).to_string())), )); } diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs index 1c17ace90c2fb..b78396c90dc65 100644 --- a/src/librustc/traits/on_unimplemented.rs +++ b/src/librustc/traits/on_unimplemented.rs @@ -7,7 +7,7 @@ use crate::util::nodemap::FxHashMap; use syntax::ast::{MetaItem, NestedMetaItem}; use syntax::attr; -use syntax::symbol::sym; +use syntax::symbol::{Symbol, kw, sym}; use syntax_pos::Span; use syntax_pos::symbol::LocalInternedString; @@ -52,7 +52,7 @@ fn parse_error(tcx: TyCtxt<'_, '_, '_>, span: Span, } impl<'a, 'gcx, 'tcx> OnUnimplementedDirective { - pub fn parse(tcx: TyCtxt<'a, 'gcx, 'tcx>, + fn parse(tcx: TyCtxt<'a, 'gcx, 'tcx>, trait_def_id: DefId, items: &[NestedMetaItem], span: Span, @@ -167,7 +167,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective { pub fn evaluate(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, trait_ref: ty::TraitRef<'tcx>, - options: &[(String, Option)]) + options: &[(Symbol, Option)]) -> OnUnimplementedNote { let mut message = None; @@ -180,7 +180,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective { if !attr::eval_condition(condition, &tcx.sess.parse_sess, &mut |c| { c.ident().map_or(false, |ident| { options.contains(&( - ident.to_string(), + ident.name, c.value_str().map(|s| s.as_str().to_string()) )) }) @@ -203,8 +203,8 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective { } } - let options: FxHashMap = options.into_iter() - .filter_map(|(k, v)| v.as_ref().map(|v| (k.to_owned(), v.to_owned()))) + let options: FxHashMap = options.into_iter() + .filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))) .collect(); OnUnimplementedNote { label: label.map(|l| l.format(tcx, trait_ref, &options)), @@ -215,7 +215,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective { } impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString { - pub fn try_parse(tcx: TyCtxt<'a, 'gcx, 'tcx>, + fn try_parse(tcx: TyCtxt<'a, 'gcx, 'tcx>, trait_def_id: DefId, from: LocalInternedString, err_sp: Span) @@ -241,16 +241,16 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString { Piece::String(_) => (), // Normal string, no need to check it Piece::NextArgument(a) => match a.position { // `{Self}` is allowed - Position::ArgumentNamed(s) if s == "Self" => (), + Position::ArgumentNamed(s) if s == kw::SelfUpper => (), // `{ThisTraitsName}` is allowed - Position::ArgumentNamed(s) if s == name.as_str() => (), + Position::ArgumentNamed(s) if s == name => (), // `{from_method}` is allowed - Position::ArgumentNamed(s) if s == "from_method" => (), + Position::ArgumentNamed(s) if s == sym::from_method => (), // `{from_desugaring}` is allowed - Position::ArgumentNamed(s) if s == "from_desugaring" => (), + Position::ArgumentNamed(s) if s == sym::from_desugaring => (), // So is `{A}` if A is a type parameter Position::ArgumentNamed(s) => match generics.params.iter().find(|param| { - param.name.as_str() == s + param.name.as_symbol() == s }) { Some(_) => (), None => { @@ -276,7 +276,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString { &self, tcx: TyCtxt<'a, 'gcx, 'tcx>, trait_ref: ty::TraitRef<'tcx>, - options: &FxHashMap, + options: &FxHashMap, ) -> String { let name = tcx.item_name(trait_ref.def_id); let trait_str = tcx.def_path_str(trait_ref.def_id); @@ -289,9 +289,9 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString { }, GenericParamDefKind::Lifetime => return None }; - let name = param.name.to_string(); + let name = param.name.as_symbol(); Some((name, value)) - }).collect::>(); + }).collect::>(); let empty_string = String::new(); let parser = Parser::new(&self.0, None, vec![], false); @@ -299,15 +299,15 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString { match p { Piece::String(s) => s, Piece::NextArgument(a) => match a.position { - Position::ArgumentNamed(s) => match generic_map.get(s) { + Position::ArgumentNamed(s) => match generic_map.get(&s) { Some(val) => val, - None if s == name.as_str() => { + None if s == name => { &trait_str } None => { - if let Some(val) = options.get(s) { + if let Some(val) = options.get(&s) { val - } else if s == "from_desugaring" || s == "from_method" { + } else if s == sym::from_desugaring || s == sym::from_method { // don't break messages using these two arguments incorrectly &empty_string } else { diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index 694843ad7f71e..6d51278b4e5e8 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs @@ -2,7 +2,7 @@ use errors::Applicability; use syntax::parse::lexer::{StringReader as Lexer}; use syntax::parse::{ParseSess, token}; use syntax::source_map::FilePathMapping; -use syntax_pos::FileName; +use syntax_pos::{InnerSpan, FileName}; use crate::clean; use crate::core::DocContext; @@ -63,7 +63,7 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { } if code_block.syntax.is_none() && code_block.is_fenced { - let sp = sp.from_inner_byte_pos(0, 3); + let sp = sp.from_inner(InnerSpan::new(0, 3)); diag.span_suggestion( sp, "mark blocks that do not contain Rust code as text", diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 018ab5dea6081..8fc6b9fdbe6b9 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -6,7 +6,7 @@ use rustc::lint as lint; use rustc::middle::privacy::AccessLevels; use rustc::util::nodemap::DefIdSet; use std::mem; -use syntax_pos::{DUMMY_SP, Span}; +use syntax_pos::{DUMMY_SP, InnerSpan, Span}; use std::ops::Range; use crate::clean::{self, GetDefId, Item}; @@ -440,10 +440,10 @@ crate fn source_span_for_markdown_range( } } - let sp = span_of_attrs(attrs).from_inner_byte_pos( + let sp = span_of_attrs(attrs).from_inner(InnerSpan::new( md_range.start + start_bytes, md_range.end + start_bytes + end_bytes, - ); + )); Some(sp) } diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 377164728f42a..85b524786b2f5 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -28,7 +28,7 @@ enum ArgumentType { enum Position { Exact(usize), - Named(String), + Named(Symbol), } struct Context<'a, 'b: 'a> { @@ -57,7 +57,7 @@ struct Context<'a, 'b: 'a> { /// Unique format specs seen for each argument. arg_unique_types: Vec>, /// Map from named arguments to their resolved indices. - names: FxHashMap, + names: FxHashMap, /// The latest consecutive literal strings, or empty if there weren't any. literal: String, @@ -127,9 +127,9 @@ fn parse_args<'a>( ecx: &mut ExtCtxt<'a>, sp: Span, tts: &[tokenstream::TokenTree] -) -> Result<(P, Vec>, FxHashMap), DiagnosticBuilder<'a>> { +) -> Result<(P, Vec>, FxHashMap), DiagnosticBuilder<'a>> { let mut args = Vec::>::new(); - let mut names = FxHashMap::::default(); + let mut names = FxHashMap::::default(); let mut p = ecx.new_parser_from_tts(tts); @@ -158,11 +158,10 @@ fn parse_args<'a>( "expected ident, positional arguments cannot follow named arguments", )); }; - let name: &str = &name.as_str(); p.expect(&token::Eq)?; let e = p.parse_expr()?; - if let Some(prev) = names.get(name) { + if let Some(prev) = names.get(&name) { ecx.struct_span_err(e.span, &format!("duplicate argument named `{}`", name)) .span_note(args[*prev].span, "previously here") .emit(); @@ -174,7 +173,7 @@ fn parse_args<'a>( // if the input is valid, we can simply append to the positional // args. And remember the names. let slot = args.len(); - names.insert(name.to_string(), slot); + names.insert(name, slot); args.push(e); } else { let e = p.parse_expr()?; @@ -188,7 +187,7 @@ impl<'a, 'b> Context<'a, 'b> { fn resolve_name_inplace(&self, p: &mut parse::Piece<'_>) { // NOTE: the `unwrap_or` branch is needed in case of invalid format // arguments, e.g., `format_args!("{foo}")`. - let lookup = |s| *self.names.get(s).unwrap_or(&0); + let lookup = |s: Symbol| *self.names.get(&s).unwrap_or(&0); match *p { parse::String(_) => {} @@ -222,7 +221,7 @@ impl<'a, 'b> Context<'a, 'b> { // it's written second, so it should come after width/precision. let pos = match arg.position { parse::ArgumentIs(i) | parse::ArgumentImplicitlyIs(i) => Exact(i), - parse::ArgumentNamed(s) => Named(s.to_string()), + parse::ArgumentNamed(s) => Named(s), }; let ty = Placeholder(arg.format.ty.to_string()); @@ -232,7 +231,7 @@ impl<'a, 'b> Context<'a, 'b> { } } - fn verify_count(&mut self, c: parse::Count<'_>) { + fn verify_count(&mut self, c: parse::Count) { match c { parse::CountImplied | parse::CountIs(..) => {} @@ -240,7 +239,7 @@ impl<'a, 'b> Context<'a, 'b> { self.verify_arg_type(Exact(i), Count); } parse::CountIsName(s) => { - self.verify_arg_type(Named(s.to_string()), Count); + self.verify_arg_type(Named(s), Count); } } } @@ -390,7 +389,7 @@ impl<'a, 'b> Context<'a, 'b> { ecx.std_path(&[sym::fmt, sym::rt, sym::v1, Symbol::intern(s)]) } - fn build_count(&self, c: parse::Count<'_>) -> P { + fn build_count(&self, c: parse::Count) -> P { let sp = self.macsp; let count = |c, arg| { let mut path = Context::rtpath(self.ecx, "Count"); @@ -739,7 +738,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt<'_>, sp: Span, efmt: P, args: Vec>, - names: FxHashMap, + names: FxHashMap, append_newline: bool) -> P { // NOTE: this verbose way of initializing `Vec>` is because @@ -901,15 +900,15 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt<'_>, if !parser.errors.is_empty() { let err = parser.errors.remove(0); - let sp = fmt.span.from_inner_byte_pos(err.start.unwrap(), err.end.unwrap()); + let sp = fmt.span.from_inner(err.span); let mut e = ecx.struct_span_err(sp, &format!("invalid format string: {}", err.description)); e.span_label(sp, err.label + " in format string"); if let Some(note) = err.note { e.note(¬e); } - if let Some((label, start, end)) = err.secondary_label { - let sp = fmt.span.from_inner_byte_pos(start.unwrap(), end.unwrap()); + if let Some((label, span)) = err.secondary_label { + let sp = fmt.span.from_inner(span); e.span_label(sp, label); } e.emit(); @@ -917,9 +916,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt<'_>, } let arg_spans = parser.arg_places.iter() - .map(|&(parse::SpanIndex(start), parse::SpanIndex(end))| { - fmt.span.from_inner_byte_pos(start, end) - }) + .map(|span| fmt.span.from_inner(*span)) .collect(); let mut cx = Context { @@ -1044,7 +1041,9 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt<'_>, let mut show_doc_note = false; let mut suggestions = vec![]; - for sub in foreign::$kind::iter_subs(fmt_str) { + // account for `"` and account for raw strings `r#` + let padding = str_style.map(|i| i + 2).unwrap_or(1); + for sub in foreign::$kind::iter_subs(fmt_str, padding) { let trn = match sub.translate() { Some(trn) => trn, @@ -1064,10 +1063,8 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt<'_>, show_doc_note = true; } - if let Some((start, end)) = pos { - // account for `"` and account for raw strings `r#` - let padding = str_style.map(|i| i + 2).unwrap_or(1); - let sp = fmt_sp.from_inner_byte_pos(start + padding, end + padding); + if let Some(inner_sp) = pos { + let sp = fmt_sp.from_inner(inner_sp); suggestions.push((sp, trn)); } else { diag.help(&format!("`{}` should be written as `{}`", sub, trn)); diff --git a/src/libsyntax_ext/format_foreign.rs b/src/libsyntax_ext/format_foreign.rs index 261b2f373cefd..7ad5997bf2c09 100644 --- a/src/libsyntax_ext/format_foreign.rs +++ b/src/libsyntax_ext/format_foreign.rs @@ -1,5 +1,6 @@ pub mod printf { use super::strcursor::StrCursor as Cur; + use syntax_pos::InnerSpan; /// Represents a single `printf`-style substitution. #[derive(Clone, PartialEq, Debug)] @@ -18,7 +19,7 @@ pub mod printf { } } - pub fn position(&self) -> Option<(usize, usize)> { + pub fn position(&self) -> Option { match *self { Substitution::Format(ref fmt) => Some(fmt.position), _ => None, @@ -28,7 +29,7 @@ pub mod printf { pub fn set_position(&mut self, start: usize, end: usize) { match self { Substitution::Format(ref mut fmt) => { - fmt.position = (start, end); + fmt.position = InnerSpan::new(start, end); } _ => {} } @@ -65,7 +66,7 @@ pub mod printf { /// Type of parameter being converted. pub type_: &'a str, /// Byte offset for the start and end of this formatting directive. - pub position: (usize, usize), + pub position: InnerSpan, } impl Format<'_> { @@ -263,10 +264,10 @@ pub mod printf { } /// Returns an iterator over all substitutions in a given string. - pub fn iter_subs(s: &str) -> Substitutions<'_> { + pub fn iter_subs(s: &str, start_pos: usize) -> Substitutions<'_> { Substitutions { s, - pos: 0, + pos: start_pos, } } @@ -282,9 +283,9 @@ pub mod printf { let (mut sub, tail) = parse_next_substitution(self.s)?; self.s = tail; match sub { - Substitution::Format(_) => if let Some((start, end)) = sub.position() { - sub.set_position(start + self.pos, end + self.pos); - self.pos += end; + Substitution::Format(_) => if let Some(inner_span) = sub.position() { + sub.set_position(inner_span.start + self.pos, inner_span.end + self.pos); + self.pos += inner_span.end; } Substitution::Escape => self.pos += 2, } @@ -373,7 +374,7 @@ pub mod printf { precision: None, length: None, type_: at.slice_between(next).unwrap(), - position: (start.at, next.at), + position: InnerSpan::new(start.at, next.at), }), next.slice_after() )); @@ -560,7 +561,7 @@ pub mod printf { drop(next); end = at; - let position = (start.at, end.at); + let position = InnerSpan::new(start.at, end.at); let f = Format { span: start.slice_between(end).unwrap(), @@ -650,7 +651,7 @@ pub mod printf { precision: $prec, length: $len, type_: $type_, - position: $pos, + position: syntax_pos::InnerSpan::new($pos.0, $pos.1), }), "!" )) @@ -711,7 +712,7 @@ pub mod printf { #[test] fn test_iter() { let s = "The %d'th word %% is: `%.*s` %!\n"; - let subs: Vec<_> = iter_subs(s).map(|sub| sub.translate()).collect(); + let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate()).collect(); assert_eq!( subs.iter().map(|ms| ms.as_ref().map(|s| &s[..])).collect::>(), vec![Some("{}"), None, Some("{:.*}"), None] @@ -761,6 +762,7 @@ pub mod printf { pub mod shell { use super::strcursor::StrCursor as Cur; + use syntax_pos::InnerSpan; #[derive(Clone, PartialEq, Debug)] pub enum Substitution<'a> { @@ -778,11 +780,11 @@ pub mod shell { } } - pub fn position(&self) -> Option<(usize, usize)> { + pub fn position(&self) -> Option { match self { Substitution::Ordinal(_, pos) | Substitution::Name(_, pos) | - Substitution::Escape(pos) => Some(*pos), + Substitution::Escape(pos) => Some(InnerSpan::new(pos.0, pos.1)), } } @@ -804,10 +806,10 @@ pub mod shell { } /// Returns an iterator over all substitutions in a given string. - pub fn iter_subs(s: &str) -> Substitutions<'_> { + pub fn iter_subs(s: &str, start_pos: usize) -> Substitutions<'_> { Substitutions { s, - pos: 0, + pos: start_pos, } } @@ -823,7 +825,7 @@ pub mod shell { match parse_next_substitution(self.s) { Some((mut sub, tail)) => { self.s = tail; - if let Some((start, end)) = sub.position() { + if let Some(InnerSpan { start, end }) = sub.position() { sub.set_position(start + self.pos, end + self.pos); self.pos += end; } @@ -940,7 +942,7 @@ pub mod shell { fn test_iter() { use super::iter_subs; let s = "The $0'th word $$ is: `$WORD` $!\n"; - let subs: Vec<_> = iter_subs(s).map(|sub| sub.translate()).collect(); + let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate()).collect(); assert_eq!( subs.iter().map(|ms| ms.as_ref().map(|s| &s[..])).collect::>(), vec![Some("{0}"), None, Some("{WORD}")] diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 8f5595968a738..bf0ab5fae4e87 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -504,10 +504,10 @@ impl Span { ) } - pub fn from_inner_byte_pos(self, start: usize, end: usize) -> Span { + pub fn from_inner(self, inner: InnerSpan) -> Span { let span = self.data(); - Span::new(span.lo + BytePos::from_usize(start), - span.lo + BytePos::from_usize(end), + Span::new(span.lo + BytePos::from_usize(inner.start), + span.lo + BytePos::from_usize(inner.end), span.ctxt) } @@ -1395,6 +1395,18 @@ pub struct MalformedSourceMapPositions { pub end_pos: BytePos } +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct InnerSpan { + pub start: usize, + pub end: usize, +} + +impl InnerSpan { + pub fn new(start: usize, end: usize) -> InnerSpan { + InnerSpan { start, end } + } +} + // Given a slice of line start positions and a position, returns the index of // the line the position is on. Returns -1 if the position is located before // the first line. diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 302b3c75263cf..95d74ce054ef9 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -203,6 +203,7 @@ symbols! { core_intrinsics, crate_id, crate_in_paths, + crate_local, crate_name, crate_type, crate_visibility_modifier, @@ -221,6 +222,7 @@ symbols! { deref, deref_mut, derive, + direct, doc, doc_alias, doc_cfg, @@ -278,8 +280,10 @@ symbols! { format_args_nl, from, From, + from_desugaring, from_error, from_generator, + from_method, from_ok, from_usize, fundamental, @@ -443,6 +447,7 @@ symbols! { panic_impl, panic_implementation, panic_runtime, + parent_trait, partial_cmp, PartialOrd, passes, @@ -569,6 +574,7 @@ symbols! { __rust_unstable_column, rvalue_static_promotion, sanitizer_runtime, + _Self, self_in_typedefs, self_struct_ctor, Send,