Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Match errors using the callsite of macro expansions #52175

Merged
merged 1 commit into from
Jul 23, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/test/ui/codemap_tests/bad-format-args.rs
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@
// except according to those terms.

fn main() {
format!();
format!("" 1);
format!("", 1 1);
format!(); //~ ERROR requires at least a format string argument
format!("" 1); //~ ERROR expected token: `,`
format!("", 1 1); //~ ERROR expected token: `,`
}
6 changes: 3 additions & 3 deletions src/test/ui/codemap_tests/bad-format-args.stderr
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
error: requires at least a format string argument
--> $DIR/bad-format-args.rs:12:5
|
LL | format!();
LL | format!(); //~ ERROR requires at least a format string argument
| ^^^^^^^^^^
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: expected token: `,`
--> $DIR/bad-format-args.rs:13:5
|
LL | format!("" 1);
LL | format!("" 1); //~ ERROR expected token: `,`
| ^^^^^^^^^^^^^^
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: expected token: `,`
--> $DIR/bad-format-args.rs:14:5
|
LL | format!("", 1 1);
LL | format!("", 1 1); //~ ERROR expected token: `,`
| ^^^^^^^^^^^^^^^^^
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
3 changes: 1 addition & 2 deletions src/test/ui/cross-crate-macro-backtrace/main.rs
Original file line number Diff line number Diff line change
@@ -8,12 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// error-pattern: in format string

// aux-build:extern_macro_crate.rs
#[macro_use(myprintln, myprint)]
extern crate extern_macro_crate;

fn main() {
myprintln!("{}");
//~^ ERROR in format string
}
2 changes: 1 addition & 1 deletion src/test/ui/cross-crate-macro-backtrace/main.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: 1 positional argument in format string, but no arguments were given
--> $DIR/main.rs:18:5
--> $DIR/main.rs:16:5
|
LL | myprintln!("{}");
| ^^^^^^^^^^^^^^^^^
1 change: 1 addition & 0 deletions src/test/ui/cross-file-errors/main.rs
Original file line number Diff line number Diff line change
@@ -13,4 +13,5 @@ mod underscore;

fn main() {
underscore!();
//~^ ERROR expected expression, found reserved identifier `_`
}
2 changes: 1 addition & 1 deletion src/test/ui/edition-keywords-2015-2018-expansion.rs
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@
extern crate edition_kw_macro_2018;

mod one_async {
produces_async! {} // ERROR expected identifier, found reserved keyword
produces_async! {} //~ ERROR expected identifier, found reserved keyword
}
mod two_async {
produces_async_raw! {} // OK
2 changes: 1 addition & 1 deletion src/test/ui/edition-keywords-2015-2018-expansion.stderr
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
error: expected identifier, found reserved keyword `async`
--> $DIR/edition-keywords-2015-2018-expansion.rs:20:5
|
LL | produces_async! {} // ERROR expected identifier, found reserved keyword
LL | produces_async! {} //~ ERROR expected identifier, found reserved keyword
| ^^^^^^^^^^^^^^^^^^ expected identifier, found reserved keyword
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
2 changes: 1 addition & 1 deletion src/test/ui/edition-keywords-2018-2018-expansion.rs
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@
extern crate edition_kw_macro_2018;

mod one_async {
produces_async! {} // ERROR expected identifier, found reserved keyword `async`
produces_async! {} //~ ERROR expected identifier, found reserved keyword `async`
}
mod two_async {
produces_async_raw! {} // OK
2 changes: 1 addition & 1 deletion src/test/ui/edition-keywords-2018-2018-expansion.stderr
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
error: expected identifier, found reserved keyword `async`
--> $DIR/edition-keywords-2018-2018-expansion.rs:20:5
|
LL | produces_async! {} // ERROR expected identifier, found reserved keyword `async`
LL | produces_async! {} //~ ERROR expected identifier, found reserved keyword `async`
| ^^^^^^^^^^^^^^^^^^ expected identifier, found reserved keyword
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
3 changes: 1 addition & 2 deletions src/test/ui/hygiene/intercrate.rs
Original file line number Diff line number Diff line change
@@ -12,12 +12,11 @@

// aux-build:intercrate.rs

// error-pattern:type `fn() -> u32 {intercrate::foo::bar::f}` is private

#![feature(decl_macro)]

extern crate intercrate;

fn main() {
assert_eq!(intercrate::foo::m!(), 1);
//~^ ERROR type `fn() -> u32 {intercrate::foo::bar::f}` is private
}
2 changes: 1 addition & 1 deletion src/test/ui/hygiene/intercrate.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: type `fn() -> u32 {intercrate::foo::bar::f}` is private
--> $DIR/intercrate.rs:22:16
--> $DIR/intercrate.rs:20:16
|
LL | assert_eq!(intercrate::foo::m!(), 1);
| ^^^^^^^^^^^^^^^^^^^^^
3 changes: 1 addition & 2 deletions src/test/ui/hygiene/local_inner_macros_disabled.rs
Original file line number Diff line number Diff line change
@@ -11,11 +11,10 @@
// `local_inner_macros` has no effect if `feature(use_extern_macros)` is not enabled

// aux-build:local_inner_macros.rs
// error-pattern: cannot find macro `helper2!` in this scope

#[macro_use(public_macro)]
extern crate local_inner_macros;

public_macro!();
public_macro!(); //~ ERROR cannot find macro `helper2!` in this scope

fn main() {}
4 changes: 2 additions & 2 deletions src/test/ui/hygiene/local_inner_macros_disabled.stderr
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
error: cannot find macro `helper2!` in this scope
--> $DIR/local_inner_macros_disabled.rs:19:1
--> $DIR/local_inner_macros_disabled.rs:18:1
|
LL | public_macro!();
LL | public_macro!(); //~ ERROR cannot find macro `helper2!` in this scope
| ^^^^^^^^^^^^^^^^
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
3 changes: 1 addition & 2 deletions src/test/ui/issue-13446.rs
Original file line number Diff line number Diff line change
@@ -11,8 +11,7 @@

// Used to cause ICE

// error-pattern: mismatched types

static VEC: [u32; 256] = vec![];
//~^ ERROR mismatched types

fn main() {}
2 changes: 1 addition & 1 deletion src/test/ui/issue-13446.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0308]: mismatched types
--> $DIR/issue-13446.rs:16:26
--> $DIR/issue-13446.rs:14:26
|
LL | static VEC: [u32; 256] = vec![];
| ^^^^^^ expected array of 256 elements, found struct `std::vec::Vec`
6 changes: 2 additions & 4 deletions src/test/ui/issue-16966.rs
Original file line number Diff line number Diff line change
@@ -8,9 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// error-pattern:type annotations needed
fn main() {
panic!(
std::default::Default::default()
);
panic!(std::default::Default::default());
//~^ ERROR type annotations needed
}
8 changes: 3 additions & 5 deletions src/test/ui/issue-16966.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
error[E0282]: type annotations needed
--> $DIR/issue-16966.rs:13:5
--> $DIR/issue-16966.rs:12:5
|
LL | / panic!(
LL | | std::default::Default::default()
LL | | );
| |______^ cannot infer type for `M`
LL | panic!(std::default::Default::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for `M`
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

3 changes: 1 addition & 2 deletions src/test/ui/issue-32829.rs
Original file line number Diff line number Diff line change
@@ -8,9 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// error-pattern: calls in statics are limited

static S : u64 = { { panic!("foo"); 0 } };
//~^ ERROR calls in statics are limited

fn main() {
println!("{:?}", S);
2 changes: 1 addition & 1 deletion src/test/ui/issue-32829.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
--> $DIR/issue-32829.rs:13:22
--> $DIR/issue-32829.rs:11:22
|
LL | static S : u64 = { { panic!("foo"); 0 } };
| ^^^^^^^^^^^^^^
1 change: 1 addition & 0 deletions src/test/ui/issue-50577.rs
Original file line number Diff line number Diff line change
@@ -11,5 +11,6 @@
fn main() {
enum Foo {
Drop = assert_eq!(1, 1)
//~^ ERROR if may be missing an else clause
}
}
30 changes: 30 additions & 0 deletions src/test/ui/issue-51848.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// In case of macro expansion, the errors should be matched using the deepest callsite in the
// macro call stack whose span is in the current file

macro_rules! macro_with_error {
( ) => {
println!("{"); //~ ERROR invalid
};
}

fn foo() {

}

fn main() {
macro_with_error!();
//^ In case of a local macro we want the error to be matched in the macro definition, not here

println!("}"); //~ ERROR invalid
//^ In case of an external macro we want the error to be matched here
}
21 changes: 21 additions & 0 deletions src/test/ui/issue-51848.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error: invalid format string: expected `'}'` but string was terminated
--> $DIR/issue-51848.rs:16:20
|
LL | println!("{"); //~ ERROR invalid
| ^ expected `'}'` in format string
...
LL | macro_with_error!();
| -------------------- in this macro invocation
|
= note: if you intended to print `{`, you can escape it using `{{`

error: invalid format string: unmatched `}` found
--> $DIR/issue-51848.rs:28:15
|
LL | println!("}"); //~ ERROR invalid
| ^ unmatched `}` in format string
|
= note: if you intended to print `}`, you can escape it using `}}`

error: aborting due to 2 previous errors

1 change: 1 addition & 0 deletions src/test/ui/lifetimes/borrowck-let-suggestion.nll.stderr
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@ LL | let mut x = vec![1].iter();
| ^^^^^^^ - temporary value only lives until here
| |
| temporary value does not live long enough
LL | //~^ ERROR borrowed value does not live long enough
LL | x.use_mut();
| - borrow later used here
|
1 change: 1 addition & 0 deletions src/test/ui/lifetimes/borrowck-let-suggestion.rs
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@

fn f() {
let mut x = vec![1].iter();
//~^ ERROR borrowed value does not live long enough
x.use_mut();
}

2 changes: 1 addition & 1 deletion src/test/ui/lifetimes/borrowck-let-suggestion.stderr
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ LL | let mut x = vec![1].iter();
| ^^^^^^^ - temporary value dropped here while still borrowed
| |
| temporary value does not live long enough
LL | x.use_mut();
...
LL | }
| - temporary value needs to live until here
|
1 change: 1 addition & 0 deletions src/test/ui/reachable/expr_again.rs
Original file line number Diff line number Diff line change
@@ -16,5 +16,6 @@ fn main() {
let x = loop {
continue;
println!("hi");
//~^ ERROR unreachable statement
};
}
1 change: 1 addition & 0 deletions src/test/ui/reachable/expr_block.rs
Original file line number Diff line number Diff line change
@@ -33,6 +33,7 @@ fn c() {
let x = {
return;
println!("foo");
//~^ ERROR unreachable statement
22
};
}
1 change: 1 addition & 0 deletions src/test/ui/reachable/expr_if.rs
Original file line number Diff line number Diff line change
@@ -35,6 +35,7 @@ fn baz() {
// As the next action to be taken after the if arms, we should
// report the `println!` as unreachable:
println!("But I am.");
//~^ ERROR unreachable statement
}

fn main() { }
3 changes: 3 additions & 0 deletions src/test/ui/reachable/expr_loop.rs
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@
fn a() {
loop { return; }
println!("I am dead.");
//~^ ERROR unreachable statement
}

fn b() {
@@ -28,6 +29,7 @@ fn b() {
fn c() {
loop { return; }
println!("I am dead.");
//~^ ERROR unreachable statement
}

fn d() {
@@ -38,6 +40,7 @@ fn d() {
fn e() {
loop { 'middle: loop { loop { break 'middle; } } }
println!("I am dead.");
//~^ ERROR unreachable statement
}

fn main() { }
4 changes: 2 additions & 2 deletions src/test/ui/reachable/expr_loop.stderr
Original file line number Diff line number Diff line change
@@ -12,15 +12,15 @@ LL | #![deny(unreachable_code)]
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: unreachable statement
--> $DIR/expr_loop.rs:30:5
--> $DIR/expr_loop.rs:31:5
|
LL | println!("I am dead.");
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: unreachable statement
--> $DIR/expr_loop.rs:40:5
--> $DIR/expr_loop.rs:42:5
|
LL | println!("I am dead.");
| ^^^^^^^^^^^^^^^^^^^^^^^
2 changes: 2 additions & 0 deletions src/test/ui/reachable/expr_match.rs
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@ fn a() {
fn b() {
match () { () => return }
println!("I am dead");
//~^ ERROR unreachable statement
}

fn c() {
@@ -32,6 +33,7 @@ fn c() {
fn d() {
match () { () if false => return, () => return }
println!("I am dead");
//~^ ERROR unreachable statement
}

fn e() {
2 changes: 1 addition & 1 deletion src/test/ui/reachable/expr_match.stderr
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@ LL | println!("I am dead");
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: unreachable statement
--> $DIR/expr_match.rs:34:5
--> $DIR/expr_match.rs:35:5
|
LL | println!("I am dead");
| ^^^^^^^^^^^^^^^^^^^^^^
3 changes: 3 additions & 0 deletions src/test/ui/reachable/expr_while.rs
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@
fn foo() {
while {return} {
println!("Hello, world!");
//~^ ERROR unreachable
}
}

@@ -30,8 +31,10 @@ fn baz() {
// Here, we cite the `while` loop as dead.
while {return} {
println!("I am dead.");
//~^ ERROR unreachable
}
println!("I am, too.");
//~^ ERROR unreachable
}

fn main() { }
4 changes: 2 additions & 2 deletions src/test/ui/reachable/expr_while.stderr
Original file line number Diff line number Diff line change
@@ -12,15 +12,15 @@ LL | #![deny(unreachable_code)]
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: unreachable statement
--> $DIR/expr_while.rs:32:9
--> $DIR/expr_while.rs:33:9
|
LL | println!("I am dead.");
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: unreachable statement
--> $DIR/expr_while.rs:34:5
--> $DIR/expr_while.rs:36:5
|
LL | println!("I am, too.");
| ^^^^^^^^^^^^^^^^^^^^^^^
1 change: 1 addition & 0 deletions src/test/ui/span/coerce-suggestions.rs
Original file line number Diff line number Diff line change
@@ -29,4 +29,5 @@ fn main() {

let s = &mut String::new();
s = format!("foo");
//~^ ERROR E0308
}
1 change: 1 addition & 0 deletions src/test/ui/span/issue-33884.rs
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@ use std::io::{self, Read, Write};

fn handle_client(stream: TcpStream) -> io::Result<()> {
stream.write_fmt(format!("message received"))
//~^ ERROR mismatched types
}

fn main() {
2 changes: 1 addition & 1 deletion src/test/ui/span/slice-borrow.nll.stderr
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ error[E0597]: borrowed value does not live long enough
|
LL | let x: &[isize] = &vec![1, 2, 3, 4, 5];
| ^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
LL | y = &x[1..];
...
LL | }
| - temporary value only lives until here
LL | y.use_ref();
1 change: 1 addition & 0 deletions src/test/ui/span/slice-borrow.rs
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@ fn main() {
let y;
{
let x: &[isize] = &vec![1, 2, 3, 4, 5];
//~^ ERROR borrowed value does not live long enough
y = &x[1..];
}
y.use_ref();
2 changes: 1 addition & 1 deletion src/test/ui/span/slice-borrow.stderr
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ error[E0597]: borrowed value does not live long enough
|
LL | let x: &[isize] = &vec![1, 2, 3, 4, 5];
| ^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
LL | y = &x[1..];
...
LL | }
| - temporary value dropped here while still borrowed
LL | y.use_ref();
1 change: 1 addition & 0 deletions src/test/ui/type-check/cannot_infer_local_or_vec.rs
Original file line number Diff line number Diff line change
@@ -10,4 +10,5 @@

fn main() {
let x = vec![];
//~^ ERROR type annotations needed
}
Original file line number Diff line number Diff line change
@@ -10,4 +10,5 @@

fn main() {
let (x, ) = (vec![], );
//~^ ERROR type annotations needed
}
32 changes: 27 additions & 5 deletions src/tools/compiletest/src/json.rs
Original file line number Diff line number Diff line change
@@ -40,6 +40,21 @@ struct DiagnosticSpan {
expansion: Option<Box<DiagnosticSpanMacroExpansion>>,
}

impl DiagnosticSpan {
/// Returns the deepest source span in the macro call stack with a given file name.
/// This is either the supplied span, or the span for some macro callsite that expanded to it.
fn first_callsite_in_file(&self, file_name: &str) -> &DiagnosticSpan {
if self.file_name == file_name {
self
} else {
self.expansion
.as_ref()
.map(|origin| origin.span.first_callsite_in_file(file_name))
.unwrap_or(self)
}
}
}

#[derive(Deserialize, Clone)]
struct DiagnosticSpanMacroExpansion {
/// span where macro was applied to generate this code
@@ -115,16 +130,23 @@ fn push_expected_errors(
default_spans: &[&DiagnosticSpan],
file_name: &str,
) {
let spans_in_this_file: Vec<_> = diagnostic
// In case of macro expansions, we need to get the span of the callsite
let spans_info_in_this_file: Vec<_> = diagnostic
.spans
.iter()
.filter(|span| Path::new(&span.file_name) == Path::new(&file_name))
.map(|span| (span.is_primary, span.first_callsite_in_file(file_name)))
.filter(|(_, span)| Path::new(&span.file_name) == Path::new(&file_name))
.collect();

let primary_spans: Vec<_> = spans_in_this_file.iter()
.cloned()
.filter(|span| span.is_primary)
let spans_in_this_file: Vec<_> = spans_info_in_this_file.iter()
.map(|(_, span)| span)
.collect();

let primary_spans: Vec<_> = spans_info_in_this_file.iter()
.filter(|(is_primary, _)| *is_primary)
.map(|(_, span)| span)
.take(1) // sometimes we have more than one showing up in the json; pick first
.cloned()
.collect();
let primary_spans = if primary_spans.is_empty() {
// subdiagnostics often don't have a span of their own;
6 changes: 5 additions & 1 deletion src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
@@ -1194,6 +1194,10 @@ impl<'test> TestCx<'test> {
self.fatal_proc_rec("process did not return an error status", proc_res);
}

// On Windows, keep all '\' path separators to match the paths reported in the JSON output
// from the compiler
let os_file_name = self.testpaths.file.display().to_string();

// on windows, translate all '\' path separators to '/'
let file_name = format!("{}", self.testpaths.file.display()).replace(r"\", "/");

@@ -1209,7 +1213,7 @@ impl<'test> TestCx<'test> {
.any(|ee| ee.kind == Some(ErrorKind::Note));

// Parse the JSON output from the compiler and extract out the messages.
let actual_errors = json::parse_output(&file_name, &proc_res.stderr, proc_res);
let actual_errors = json::parse_output(&os_file_name, &proc_res.stderr, proc_res);
let mut unexpected = Vec::new();
let mut found = vec![false; expected_errors.len()];
for actual_error in &actual_errors {