diff --git a/compiler/rustc_expand/src/parse/tests.rs b/compiler/rustc_expand/src/parse/tests.rs
index 8b37728b60fea..e133501c5d0a8 100644
--- a/compiler/rustc_expand/src/parse/tests.rs
+++ b/compiler/rustc_expand/src/parse/tests.rs
@@ -1,4 +1,6 @@
-use crate::tests::{matches_codepattern, string_to_stream, with_error_checking_parse};
+use crate::tests::{
+ matches_codepattern, string_to_stream, with_error_checking_parse, with_expected_parse_error,
+};
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, Token};
@@ -51,11 +53,15 @@ fn string_to_item(source_str: String) -> Option
> {
with_error_checking_parse(source_str, &sess(), |p| p.parse_item(ForceCollect::No))
}
-#[should_panic]
#[test]
fn bad_path_expr_1() {
+ // This should trigger error: expected identifier, found keyword `return`
create_default_session_globals_then(|| {
- string_to_expr("::abc::def::return".to_string());
+ with_expected_parse_error(
+ "::abc::def::return",
+ "expected identifier, found keyword `return`",
+ |p| p.parse_expr(),
+ );
})
}
diff --git a/compiler/rustc_expand/src/tests.rs b/compiler/rustc_expand/src/tests.rs
index 6490e52955db8..67c268667c6bd 100644
--- a/compiler/rustc_expand/src/tests.rs
+++ b/compiler/rustc_expand/src/tests.rs
@@ -22,6 +22,33 @@ fn string_to_parser(ps: &ParseSess, source_str: String) -> Parser<'_> {
new_parser_from_source_str(ps, PathBuf::from("bogofile").into(), source_str)
}
+fn create_test_handler() -> (Handler, Lrc, Arc>>) {
+ let output = Arc::new(Mutex::new(Vec::new()));
+ let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty()));
+ let fallback_bundle = rustc_errors::fallback_fluent_bundle(
+ vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE],
+ false,
+ );
+ let emitter = EmitterWriter::new(
+ Box::new(Shared { data: output.clone() }),
+ Some(source_map.clone()),
+ None,
+ fallback_bundle,
+ false,
+ false,
+ false,
+ Some(140),
+ false,
+ false,
+ TerminalUrl::No,
+ );
+ let handler = Handler::with_emitter(true, None, Box::new(emitter), None);
+ (handler, source_map, output)
+}
+
+/// Returns the result of parsing the given string via the given callback.
+///
+/// If there are any errors, this will panic.
pub(crate) fn with_error_checking_parse<'a, T, F>(s: String, ps: &'a ParseSess, f: F) -> T
where
F: FnOnce(&mut Parser<'a>) -> PResult<'a, T>,
@@ -32,6 +59,26 @@ where
x
}
+/// Verifies that parsing the given string using the given callback will
+/// generate an error that contains the given text.
+pub(crate) fn with_expected_parse_error(source_str: &str, expected_output: &str, f: F)
+where
+ F: for<'a> FnOnce(&mut Parser<'a>) -> PResult<'a, T>,
+{
+ let (handler, source_map, output) = create_test_handler();
+ let ps = ParseSess::with_span_handler(handler, source_map);
+ let mut p = string_to_parser(&ps, source_str.to_string());
+ let result = f(&mut p);
+ assert!(result.is_ok());
+
+ let bytes = output.lock().unwrap();
+ let actual_output = str::from_utf8(&bytes).unwrap();
+ println!("expected output:\n------\n{}------", expected_output);
+ println!("actual output:\n------\n{}------", actual_output);
+
+ assert!(actual_output.contains(expected_output))
+}
+
/// Maps a string to tts, using a made-up filename.
pub(crate) fn string_to_stream(source_str: String) -> TokenStream {
let ps = ParseSess::new(
@@ -130,13 +177,7 @@ impl Write for Shared {
fn test_harness(file_text: &str, span_labels: Vec, expected_output: &str) {
create_default_session_if_not_set_then(|_| {
- let output = Arc::new(Mutex::new(Vec::new()));
-
- let fallback_bundle = rustc_errors::fallback_fluent_bundle(
- vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE],
- false,
- );
- let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty()));
+ let (handler, source_map, output) = create_test_handler();
source_map.new_source_file(Path::new("test.rs").to_owned().into(), file_text.to_owned());
let primary_span = make_span(&file_text, &span_labels[0].start, &span_labels[0].end);
@@ -148,20 +189,6 @@ fn test_harness(file_text: &str, span_labels: Vec, expected_output: &
println!("text: {:?}", source_map.span_to_snippet(span));
}
- let emitter = EmitterWriter::new(
- Box::new(Shared { data: output.clone() }),
- Some(source_map.clone()),
- None,
- fallback_bundle,
- false,
- false,
- false,
- None,
- false,
- false,
- TerminalUrl::No,
- );
- let handler = Handler::with_emitter(true, None, Box::new(emitter), None);
#[allow(rustc::untranslatable_diagnostic)]
handler.span_err(msp, "foo");