Skip to content

Commit

Permalink
Make rustc_parse_format compile on stable
Browse files Browse the repository at this point in the history
This allows it to be used by lightweight formatting systems and may
allow it to be used by rust-analyzer.
  • Loading branch information
bjorn3 committed May 3, 2022
1 parent 683c582 commit d33140d
Show file tree
Hide file tree
Showing 9 changed files with 231 additions and 191 deletions.
1 change: 0 additions & 1 deletion Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4171,7 +4171,6 @@ name = "rustc_parse_format"
version = "0.0.0"
dependencies = [
"rustc_lexer",
"rustc_span",
]

[[package]]
Expand Down
39 changes: 27 additions & 12 deletions compiler/rustc_builtin_macros/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -626,15 +626,15 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl

if !parser.errors.is_empty() {
let err = parser.errors.remove(0);
let err_sp = template_span.from_inner(err.span);
let err_sp = template_span.from_inner(InnerSpan::new(err.span.start, err.span.end));
let msg = &format!("invalid asm template string: {}", err.description);
let mut e = ecx.struct_span_err(err_sp, msg);
e.span_label(err_sp, err.label + " in asm template string");
if let Some(note) = err.note {
e.note(&note);
}
if let Some((label, span)) = err.secondary_label {
let err_sp = template_span.from_inner(span);
let err_sp = template_span.from_inner(InnerSpan::new(span.start, span.end));
e.span_label(err_sp, label);
}
e.emit();
Expand All @@ -643,7 +643,10 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl

curarg = parser.curarg;

let mut arg_spans = parser.arg_places.iter().map(|span| template_span.from_inner(*span));
let mut arg_spans = parser
.arg_places
.iter()
.map(|span| template_span.from_inner(InnerSpan::new(span.start, span.end)));
for piece in unverified_pieces {
match piece {
parse::Piece::String(s) => {
Expand Down Expand Up @@ -699,14 +702,21 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
Some(idx)
}
}
parse::ArgumentNamed(name, span) => match args.named_args.get(&name) {
Some(&idx) => Some(idx),
None => {
let msg = format!("there is no argument named `{}`", name);
ecx.struct_span_err(template_span.from_inner(span), &msg).emit();
None
parse::ArgumentNamed(name, span) => {
match args.named_args.get(&Symbol::intern(name)) {
Some(&idx) => Some(idx),
None => {
let msg = format!("there is no argument named `{}`", name);
ecx.struct_span_err(
template_span
.from_inner(InnerSpan::new(span.start, span.end)),
&msg,
)
.emit();
None
}
}
},
}
};

let mut chars = arg.format.ty.chars();
Expand All @@ -715,7 +725,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
let span = arg
.format
.ty_span
.map(|sp| template_sp.from_inner(sp))
.map(|sp| template_sp.from_inner(InnerSpan::new(sp.start, sp.end)))
.unwrap_or(template_sp);
ecx.struct_span_err(
span,
Expand All @@ -741,7 +751,12 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
let template_num_lines = 1 + template_str.matches('\n').count();
line_spans.extend(std::iter::repeat(template_sp).take(template_num_lines));
} else {
line_spans.extend(parser.line_spans.iter().map(|span| template_span.from_inner(*span)));
line_spans.extend(
parser
.line_spans
.iter()
.map(|span| template_span.from_inner(InnerSpan::new(span.start, span.end))),
);
};
}

Expand Down
34 changes: 23 additions & 11 deletions compiler/rustc_builtin_macros/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,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: Symbol| *self.names.get(&s).unwrap_or(&0);
let lookup = |s: &str| *self.names.get(&Symbol::intern(s)).unwrap_or(&0);

match *p {
parse::String(_) => {}
Expand Down Expand Up @@ -276,7 +276,9 @@ 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, span) => Named(s, span),
parse::ArgumentNamed(s, span) => {
Named(Symbol::intern(s), InnerSpan::new(span.start, span.end))
}
};

let ty = Placeholder(match arg.format.ty {
Expand All @@ -291,7 +293,10 @@ impl<'a, 'b> Context<'a, 'b> {
"X" => "UpperHex",
_ => {
let fmtsp = self.fmtsp;
let sp = arg.format.ty_span.map(|sp| fmtsp.from_inner(sp));
let sp = arg
.format
.ty_span
.map(|sp| fmtsp.from_inner(InnerSpan::new(sp.start, sp.end)));
let mut err = self.ecx.struct_span_err(
sp.unwrap_or(fmtsp),
&format!("unknown format trait `{}`", arg.format.ty),
Expand Down Expand Up @@ -340,14 +345,17 @@ 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(..) => {}
parse::CountIsParam(i) => {
self.verify_arg_type(Exact(i), Count);
}
parse::CountIsName(s, span) => {
self.verify_arg_type(Named(s, span), Count);
self.verify_arg_type(
Named(Symbol::intern(s), InnerSpan::new(span.start, span.end)),
Count,
);
}
}
}
Expand Down Expand Up @@ -425,7 +433,7 @@ impl<'a, 'b> Context<'a, 'b> {

for fmt in &self.arg_with_formatting {
if let Some(span) = fmt.precision_span {
let span = self.fmtsp.from_inner(span);
let span = self.fmtsp.from_inner(InnerSpan::new(span.start, span.end));
match fmt.precision {
parse::CountIsParam(pos) if pos > self.num_args() => {
e.span_label(
Expand Down Expand Up @@ -471,7 +479,7 @@ impl<'a, 'b> Context<'a, 'b> {
}
}
if let Some(span) = fmt.width_span {
let span = self.fmtsp.from_inner(span);
let span = self.fmtsp.from_inner(InnerSpan::new(span.start, span.end));
match fmt.width {
parse::CountIsParam(pos) if pos > self.num_args() => {
e.span_label(
Expand Down Expand Up @@ -610,7 +618,7 @@ impl<'a, 'b> Context<'a, 'b> {
ecx.std_path(&[sym::fmt, sym::rt, sym::v1, s])
}

fn build_count(&self, c: parse::Count) -> P<ast::Expr> {
fn build_count(&self, c: parse::Count<'_>) -> P<ast::Expr> {
let sp = self.macsp;
let count = |c, arg| {
let mut path = Context::rtpath(self.ecx, sym::Count);
Expand Down Expand Up @@ -1033,7 +1041,7 @@ pub fn expand_preparsed_format_args(
if !parser.errors.is_empty() {
let err = parser.errors.remove(0);
let sp = if efmt_kind_is_lit {
fmt_span.from_inner(err.span)
fmt_span.from_inner(InnerSpan::new(err.span.start, err.span.end))
} else {
// The format string could be another macro invocation, e.g.:
// format!(concat!("abc", "{}"), 4);
Expand All @@ -1052,14 +1060,18 @@ pub fn expand_preparsed_format_args(
}
if let Some((label, span)) = err.secondary_label {
if efmt_kind_is_lit {
e.span_label(fmt_span.from_inner(span), label);
e.span_label(fmt_span.from_inner(InnerSpan::new(span.start, span.end)), label);
}
}
e.emit();
return DummyResult::raw_expr(sp, true);
}

let arg_spans = parser.arg_places.iter().map(|span| fmt_span.from_inner(*span)).collect();
let arg_spans = parser
.arg_places
.iter()
.map(|span| fmt_span.from_inner(InnerSpan::new(span.start, span.end)))
.collect();

let named_pos: FxHashSet<usize> = names.values().cloned().collect();

Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_lint/src/non_fmt_panic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,10 @@ fn check_panic_str<'tcx>(
if n_arguments > 0 && fmt_parser.errors.is_empty() {
let arg_spans: Vec<_> = match &fmt_parser.arg_places[..] {
[] => vec![fmt_span],
v => v.iter().map(|span| fmt_span.from_inner(*span)).collect(),
v => v
.iter()
.map(|span| fmt_span.from_inner(InnerSpan::new(span.start, span.end)))
.collect(),
};
cx.struct_span_lint(NON_FMT_PANICS, arg_spans, |lint| {
let mut l = lint.build(match n_arguments {
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_parse_format/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@ version = "0.0.0"
edition = "2021"

[dependencies]
rustc_span = { path = "../rustc_span" }
rustc_lexer = { path = "../rustc_lexer" }
44 changes: 28 additions & 16 deletions compiler/rustc_parse_format/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
html_playground_url = "https://play.rust-lang.org/",
test(attr(deny(warnings)))
)]
#![feature(nll)]
#![feature(bool_to_option)]
// We want to be able to build this crate with a stable compiler, so no
// `#![feature]` attributes should be added.

pub use Alignment::*;
pub use Count::*;
Expand All @@ -22,7 +22,19 @@ use std::iter;
use std::str;
use std::string;

use rustc_span::{InnerSpan, Symbol};
// Note: copied from rustc_span
/// Range inside of a `Span` used for diagnostics when we only have access to relative positions.
#[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 }
}
}

/// The type of format string that we are parsing.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
Expand Down Expand Up @@ -57,7 +69,7 @@ pub enum Piece<'a> {
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Argument<'a> {
/// Where to find this argument
pub position: Position,
pub position: Position<'a>,
/// How to format the argument
pub format: FormatSpec<'a>,
}
Expand All @@ -72,11 +84,11 @@ pub struct FormatSpec<'a> {
/// Packed version of various flags provided.
pub flags: u32,
/// The integer precision to use.
pub precision: Count,
pub precision: Count<'a>,
/// The span of the precision formatting flag (for diagnostics).
pub precision_span: Option<InnerSpan>,
/// The string width requested for the resulting format.
pub width: Count,
pub width: Count<'a>,
/// The span of the width formatting flag (for diagnostics).
pub width_span: Option<InnerSpan>,
/// The descriptor string representing the name of the format desired for
Expand All @@ -89,16 +101,16 @@ pub struct FormatSpec<'a> {

/// Enum describing where an argument for a format can be located.
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Position {
pub enum Position<'a> {
/// 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(Symbol, InnerSpan),
ArgumentNamed(&'a str, InnerSpan),
}

impl Position {
impl Position<'_> {
pub fn index(&self) -> Option<usize> {
match self {
ArgumentIs(i) | ArgumentImplicitlyIs(i) => Some(*i),
Expand Down Expand Up @@ -143,11 +155,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, Debug, PartialEq)]
pub enum Count {
pub enum Count<'a> {
/// The count is specified explicitly.
CountIs(usize),
/// The count is specified by the argument with the given name.
CountIsName(Symbol, InnerSpan),
CountIsName(&'a str, InnerSpan),
/// The count is specified by the argument at the given index.
CountIsParam(usize),
/// The count is implied and cannot be explicitly specified.
Expand Down Expand Up @@ -489,7 +501,7 @@ 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<Position> {
fn position(&mut self) -> Option<Position<'a>> {
if let Some(i) = self.integer() {
Some(ArgumentIs(i))
} else {
Expand All @@ -498,7 +510,7 @@ impl<'a> Parser<'a> {
let word = self.word();
let end = start + word.len();
let span = self.to_span_index(start).to(self.to_span_index(end));
Some(ArgumentNamed(Symbol::intern(word), span))
Some(ArgumentNamed(word, span))
}

// This is an `ArgumentNext`.
Expand Down Expand Up @@ -651,7 +663,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, start: usize) -> (Count, Option<InnerSpan>) {
fn count(&mut self, start: usize) -> (Count<'a>, Option<InnerSpan>) {
if let Some(i) = self.integer() {
if let Some(end) = self.consume_pos('$') {
let span = self.to_span_index(start).to(self.to_span_index(end + 1));
Expand All @@ -667,7 +679,7 @@ impl<'a> Parser<'a> {
(CountImplied, None)
} else if let Some(end) = self.consume_pos('$') {
let span = self.to_span_index(start + 1).to(self.to_span_index(end));
(CountIsName(Symbol::intern(word), span), None)
(CountIsName(word, span), None)
} else {
self.cur = tmp;
(CountImplied, None)
Expand Down Expand Up @@ -723,7 +735,7 @@ impl<'a> Parser<'a> {
break;
}
}
found.then_some(cur)
if found { Some(cur) } else { None }
}
}

Expand Down
Loading

0 comments on commit d33140d

Please sign in to comment.