Only point at inside of string literals if they're actually string literals

This commit is contained in:
Esteban Küber
2018-07-23 15:33:36 -07:00
parent 6bcf8777fe
commit c55a698943
2 changed files with 26 additions and 8 deletions

View File

@@ -117,6 +117,8 @@ struct Context<'a, 'b: 'a> {
invalid_refs: Vec<(usize, usize)>, invalid_refs: Vec<(usize, usize)>,
/// Spans of all the formatting arguments, in order. /// Spans of all the formatting arguments, in order.
arg_spans: Vec<Span>, arg_spans: Vec<Span>,
/// Wether this formatting string is a literal or it comes from a macro.
is_literal: bool,
} }
/// Parses the arguments from the given list of tokens, returning None /// Parses the arguments from the given list of tokens, returning None
@@ -276,7 +278,11 @@ impl<'a, 'b> Context<'a, 'b> {
/// format string. /// format string.
fn report_invalid_references(&self, numbered_position_args: bool) { fn report_invalid_references(&self, numbered_position_args: bool) {
let mut e; let mut e;
let sp = MultiSpan::from_spans(self.arg_spans.clone()); let sp = if self.is_literal {
MultiSpan::from_spans(self.arg_spans.clone())
} else {
MultiSpan::from_span(self.fmtsp)
};
let mut refs: Vec<_> = self let mut refs: Vec<_> = self
.invalid_refs .invalid_refs
.iter() .iter()
@@ -294,7 +300,7 @@ impl<'a, 'b> Context<'a, 'b> {
), ),
); );
} else { } else {
let (arg_list, sp) = match refs.len() { let (arg_list, mut sp) = match refs.len() {
1 => { 1 => {
let (reg, pos) = refs.pop().unwrap(); let (reg, pos) = refs.pop().unwrap();
( (
@@ -317,11 +323,14 @@ impl<'a, 'b> Context<'a, 'b> {
) )
} }
}; };
if !self.is_literal {
sp = MultiSpan::from_span(self.fmtsp);
}
e = self.ecx.mut_span_err(sp, e = self.ecx.mut_span_err(sp,
&format!("invalid reference to positional {} ({})", &format!("invalid reference to positional {} ({})",
arg_list, arg_list,
self.describe_num_args())); self.describe_num_args()));
e.note("positional arguments are zero-based"); e.note("positional arguments are zero-based");
}; };
@@ -370,7 +379,11 @@ impl<'a, 'b> Context<'a, 'b> {
Some(e) => *e, Some(e) => *e,
None => { None => {
let msg = format!("there is no argument named `{}`", name); let msg = format!("there is no argument named `{}`", name);
let sp = *self.arg_spans.get(self.curpiece).unwrap_or(&self.fmtsp); let sp = if self.is_literal {
*self.arg_spans.get(self.curpiece).unwrap_or(&self.fmtsp)
} else {
self.fmtsp
};
let mut err = self.ecx.struct_span_err(sp, &msg[..]); let mut err = self.ecx.struct_span_err(sp, &msg[..]);
err.emit(); err.emit();
return; return;
@@ -721,7 +734,7 @@ pub fn expand_format_args<'cx>(ecx: &'cx mut ExtCtxt,
pub fn expand_format_args_nl<'cx>( pub fn expand_format_args_nl<'cx>(
ecx: &'cx mut ExtCtxt, ecx: &'cx mut ExtCtxt,
mut sp: Span, mut sp: Span,
tts: &[tokenstream::TokenTree], tts: &[tokenstream::TokenTree],
) -> Box<dyn base::MacResult + 'cx> { ) -> Box<dyn base::MacResult + 'cx> {
//if !ecx.ecfg.enable_allow_internal_unstable() { //if !ecx.ecfg.enable_allow_internal_unstable() {
@@ -784,6 +797,10 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
return DummyResult::raw_expr(sp); return DummyResult::raw_expr(sp);
} }
}; };
let is_literal = match ecx.codemap().span_to_snippet(fmt_sp) {
Ok(ref s) if s.starts_with("\"") || s.starts_with("r#") => true,
_ => false,
};
let mut cx = Context { let mut cx = Context {
ecx, ecx,
@@ -806,6 +823,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
fmtsp: fmt.span, fmtsp: fmt.span,
invalid_refs: Vec::new(), invalid_refs: Vec::new(),
arg_spans: Vec::new(), arg_spans: Vec::new(),
is_literal,
}; };
let fmt_str = &*fmt.node.0.as_str(); let fmt_str = &*fmt.node.0.as_str();

View File

@@ -1,8 +1,8 @@
error: 1 positional argument in format string, but no arguments were given error: 1 positional argument in format string, but no arguments were given
--> $DIR/macro-backtrace-println.rs:24:31 --> $DIR/macro-backtrace-println.rs:24:30
| |
LL | ($fmt:expr) => (myprint!(concat!($fmt, "/n"))); //~ ERROR no arguments were given LL | ($fmt:expr) => (myprint!(concat!($fmt, "/n"))); //~ ERROR no arguments were given
| ^^ | ^^^^^^^^^^^^^^^^^^^
... ...
LL | myprintln!("{}"); LL | myprintln!("{}");
| ----------------- in this macro invocation | ----------------- in this macro invocation