Rollup merge of #139485 - petrochenkov:errkind-light, r=oli-obk,jieyouxu
compiletest: Stricter parsing for diagnostic kinds Non-controversial parts of https://github.com/rust-lang/rust/pull/139427 not requiring many changes in the test suite. r? ``@jieyouxu``
This commit is contained in:
commit
df57bdf741
30 changed files with 166 additions and 151 deletions
|
|
@ -3,7 +3,6 @@ use std::fs::File;
|
|||
use std::io::BufReader;
|
||||
use std::io::prelude::*;
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use regex::Regex;
|
||||
|
|
@ -18,30 +17,39 @@ pub enum ErrorKind {
|
|||
Warning,
|
||||
}
|
||||
|
||||
impl FromStr for ErrorKind {
|
||||
type Err = ();
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let s = s.to_uppercase();
|
||||
let part0: &str = s.split(':').next().unwrap();
|
||||
match part0 {
|
||||
"HELP" => Ok(ErrorKind::Help),
|
||||
"ERROR" => Ok(ErrorKind::Error),
|
||||
"NOTE" => Ok(ErrorKind::Note),
|
||||
"SUGGESTION" => Ok(ErrorKind::Suggestion),
|
||||
"WARN" | "WARNING" => Ok(ErrorKind::Warning),
|
||||
_ => Err(()),
|
||||
impl ErrorKind {
|
||||
pub fn from_compiler_str(s: &str) -> ErrorKind {
|
||||
match s {
|
||||
"help" => ErrorKind::Help,
|
||||
"error" | "error: internal compiler error" => ErrorKind::Error,
|
||||
"note" | "failure-note" => ErrorKind::Note,
|
||||
"warning" => ErrorKind::Warning,
|
||||
_ => panic!("unexpected compiler diagnostic kind `{s}`"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Either the canonical uppercase string, or some additional versions for compatibility.
|
||||
/// FIXME: consider keeping only the canonical versions here.
|
||||
fn from_user_str(s: &str) -> Option<ErrorKind> {
|
||||
Some(match s {
|
||||
"HELP" | "help" => ErrorKind::Help,
|
||||
"ERROR" | "error" => ErrorKind::Error,
|
||||
"NOTE" | "note" => ErrorKind::Note,
|
||||
"SUGGESTION" => ErrorKind::Suggestion,
|
||||
"WARN" | "WARNING" | "warn" | "warning" => ErrorKind::Warning,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ErrorKind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
ErrorKind::Help => write!(f, "help message"),
|
||||
ErrorKind::Error => write!(f, "error"),
|
||||
ErrorKind::Note => write!(f, "note"),
|
||||
ErrorKind::Suggestion => write!(f, "suggestion"),
|
||||
ErrorKind::Warning => write!(f, "warning"),
|
||||
ErrorKind::Help => write!(f, "HELP"),
|
||||
ErrorKind::Error => write!(f, "ERROR"),
|
||||
ErrorKind::Note => write!(f, "NOTE"),
|
||||
ErrorKind::Suggestion => write!(f, "SUGGESTION"),
|
||||
ErrorKind::Warning => write!(f, "WARN"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -53,6 +61,10 @@ pub struct Error {
|
|||
/// `None` if not specified or unknown message kind.
|
||||
pub kind: Option<ErrorKind>,
|
||||
pub msg: String,
|
||||
/// For some `Error`s, like secondary lines of multi-line diagnostics, line annotations
|
||||
/// are not mandatory, even if they would otherwise be mandatory for primary errors.
|
||||
/// Only makes sense for "actual" errors, not for "expected" errors.
|
||||
pub require_annotation: bool,
|
||||
}
|
||||
|
||||
impl Error {
|
||||
|
|
@ -60,7 +72,7 @@ impl Error {
|
|||
use colored::Colorize;
|
||||
format!(
|
||||
"{: <10}line {: >3}: {}",
|
||||
self.kind.map(|kind| kind.to_string()).unwrap_or_default().to_uppercase(),
|
||||
self.kind.map(|kind| kind.to_string()).unwrap_or_default(),
|
||||
self.line_num_str(),
|
||||
self.msg.cyan(),
|
||||
)
|
||||
|
|
@ -150,18 +162,12 @@ fn parse_expected(
|
|||
}
|
||||
|
||||
// Get the part of the comment after the sigil (e.g. `~^^` or ~|).
|
||||
let whole_match = captures.get(0).unwrap();
|
||||
let (_, mut msg) = line.split_at(whole_match.end());
|
||||
|
||||
let first_word = msg.split_whitespace().next().expect("Encountered unexpected empty comment");
|
||||
|
||||
// If we find `//~ ERROR foo` or something like that, skip the first word.
|
||||
let kind = first_word.parse::<ErrorKind>().ok();
|
||||
if kind.is_some() {
|
||||
msg = &msg.trim_start().split_at(first_word.len()).1;
|
||||
}
|
||||
|
||||
let msg = msg.trim().to_owned();
|
||||
let tag = captures.get(0).unwrap();
|
||||
let rest = line[tag.end()..].trim_start();
|
||||
let (kind_str, _) = rest.split_once(|c: char| !c.is_ascii_alphabetic()).unwrap_or((rest, ""));
|
||||
let kind = ErrorKind::from_user_str(kind_str);
|
||||
let untrimmed_msg = if kind.is_some() { &rest[kind_str.len()..] } else { rest };
|
||||
let msg = untrimmed_msg.strip_prefix(':').unwrap_or(untrimmed_msg).trim().to_owned();
|
||||
|
||||
let line_num_adjust = &captures["adjust"];
|
||||
let (follow_prev, line_num) = if line_num_adjust == "|" {
|
||||
|
|
@ -177,12 +183,12 @@ fn parse_expected(
|
|||
debug!(
|
||||
"line={:?} tag={:?} follow_prev={:?} kind={:?} msg={:?}",
|
||||
line_num,
|
||||
whole_match.as_str(),
|
||||
tag.as_str(),
|
||||
follow_prev,
|
||||
kind,
|
||||
msg
|
||||
);
|
||||
Some((follow_prev, Error { line_num, kind, msg }))
|
||||
Some((follow_prev, Error { line_num, kind, msg, require_annotation: true }))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
//! These structs are a subset of the ones found in `rustc_errors::json`.
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str::FromStr;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use regex::Regex;
|
||||
|
|
@ -142,43 +141,34 @@ pub fn extract_rendered(output: &str) -> String {
|
|||
}
|
||||
|
||||
pub fn parse_output(file_name: &str, output: &str, proc_res: &ProcRes) -> Vec<Error> {
|
||||
output.lines().flat_map(|line| parse_line(file_name, line, output, proc_res)).collect()
|
||||
}
|
||||
|
||||
fn parse_line(file_name: &str, line: &str, output: &str, proc_res: &ProcRes) -> Vec<Error> {
|
||||
// The compiler sometimes intermingles non-JSON stuff into the
|
||||
// output. This hack just skips over such lines. Yuck.
|
||||
if line.starts_with('{') {
|
||||
match serde_json::from_str::<Diagnostic>(line) {
|
||||
Ok(diagnostic) => {
|
||||
let mut expected_errors = vec![];
|
||||
push_expected_errors(&mut expected_errors, &diagnostic, &[], file_name);
|
||||
expected_errors
|
||||
}
|
||||
Err(error) => {
|
||||
// Ignore the future compat report message - this is handled
|
||||
// by `extract_rendered`
|
||||
if serde_json::from_str::<FutureIncompatReport>(line).is_ok() {
|
||||
vec![]
|
||||
} else {
|
||||
proc_res.fatal(
|
||||
let mut errors = Vec::new();
|
||||
for line in output.lines() {
|
||||
// The compiler sometimes intermingles non-JSON stuff into the
|
||||
// output. This hack just skips over such lines. Yuck.
|
||||
if line.starts_with('{') {
|
||||
match serde_json::from_str::<Diagnostic>(line) {
|
||||
Ok(diagnostic) => push_actual_errors(&mut errors, &diagnostic, &[], file_name),
|
||||
Err(error) => {
|
||||
// Ignore the future compat report message - this is handled
|
||||
// by `extract_rendered`
|
||||
if serde_json::from_str::<FutureIncompatReport>(line).is_err() {
|
||||
proc_res.fatal(
|
||||
Some(&format!(
|
||||
"failed to decode compiler output as json: \
|
||||
`{}`\nline: {}\noutput: {}",
|
||||
"failed to decode compiler output as json: `{}`\nline: {}\noutput: {}",
|
||||
error, line, output
|
||||
)),
|
||||
|| (),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vec![]
|
||||
}
|
||||
errors
|
||||
}
|
||||
|
||||
fn push_expected_errors(
|
||||
expected_errors: &mut Vec<Error>,
|
||||
fn push_actual_errors(
|
||||
errors: &mut Vec<Error>,
|
||||
diagnostic: &Diagnostic,
|
||||
default_spans: &[&DiagnosticSpan],
|
||||
file_name: &str,
|
||||
|
|
@ -236,44 +226,47 @@ fn push_expected_errors(
|
|||
}
|
||||
};
|
||||
|
||||
// Convert multi-line messages into multiple expected
|
||||
// errors. We expect to replace these with something
|
||||
// more structured shortly anyhow.
|
||||
// Convert multi-line messages into multiple errors.
|
||||
// We expect to replace these with something more structured anyhow.
|
||||
let mut message_lines = diagnostic.message.lines();
|
||||
if let Some(first_line) = message_lines.next() {
|
||||
let ignore = |s| {
|
||||
static RE: OnceLock<Regex> = OnceLock::new();
|
||||
RE.get_or_init(|| {
|
||||
Regex::new(r"aborting due to \d+ previous errors?|\d+ warnings? emitted").unwrap()
|
||||
})
|
||||
.is_match(s)
|
||||
};
|
||||
|
||||
if primary_spans.is_empty() && !ignore(first_line) {
|
||||
let msg = with_code(None, first_line);
|
||||
let kind = ErrorKind::from_str(&diagnostic.level).ok();
|
||||
expected_errors.push(Error { line_num: None, kind, msg });
|
||||
} else {
|
||||
for span in primary_spans {
|
||||
let msg = with_code(Some(span), first_line);
|
||||
let kind = ErrorKind::from_str(&diagnostic.level).ok();
|
||||
expected_errors.push(Error { line_num: Some(span.line_start), kind, msg });
|
||||
}
|
||||
let kind = Some(ErrorKind::from_compiler_str(&diagnostic.level));
|
||||
let first_line = message_lines.next().unwrap_or(&diagnostic.message);
|
||||
if primary_spans.is_empty() {
|
||||
static RE: OnceLock<Regex> = OnceLock::new();
|
||||
let re_init =
|
||||
|| Regex::new(r"aborting due to \d+ previous errors?|\d+ warnings? emitted").unwrap();
|
||||
errors.push(Error {
|
||||
line_num: None,
|
||||
kind,
|
||||
msg: with_code(None, first_line),
|
||||
require_annotation: diagnostic.level != "failure-note"
|
||||
&& !RE.get_or_init(re_init).is_match(first_line),
|
||||
});
|
||||
} else {
|
||||
for span in primary_spans {
|
||||
errors.push(Error {
|
||||
line_num: Some(span.line_start),
|
||||
kind,
|
||||
msg: with_code(Some(span), first_line),
|
||||
require_annotation: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
for next_line in message_lines {
|
||||
if primary_spans.is_empty() {
|
||||
expected_errors.push(Error {
|
||||
errors.push(Error {
|
||||
line_num: None,
|
||||
kind: None,
|
||||
kind,
|
||||
msg: with_code(None, next_line),
|
||||
require_annotation: false,
|
||||
});
|
||||
} else {
|
||||
for span in primary_spans {
|
||||
expected_errors.push(Error {
|
||||
errors.push(Error {
|
||||
line_num: Some(span.line_start),
|
||||
kind: None,
|
||||
kind,
|
||||
msg: with_code(Some(span), next_line),
|
||||
require_annotation: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -283,10 +276,11 @@ fn push_expected_errors(
|
|||
for span in primary_spans {
|
||||
if let Some(ref suggested_replacement) = span.suggested_replacement {
|
||||
for (index, line) in suggested_replacement.lines().enumerate() {
|
||||
expected_errors.push(Error {
|
||||
errors.push(Error {
|
||||
line_num: Some(span.line_start + index),
|
||||
kind: Some(ErrorKind::Suggestion),
|
||||
msg: line.to_string(),
|
||||
require_annotation: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -295,39 +289,41 @@ fn push_expected_errors(
|
|||
// Add notes for the backtrace
|
||||
for span in primary_spans {
|
||||
if let Some(frame) = &span.expansion {
|
||||
push_backtrace(expected_errors, frame, file_name);
|
||||
push_backtrace(errors, frame, file_name);
|
||||
}
|
||||
}
|
||||
|
||||
// Add notes for any labels that appear in the message.
|
||||
for span in spans_in_this_file.iter().filter(|span| span.label.is_some()) {
|
||||
expected_errors.push(Error {
|
||||
errors.push(Error {
|
||||
line_num: Some(span.line_start),
|
||||
kind: Some(ErrorKind::Note),
|
||||
msg: span.label.clone().unwrap(),
|
||||
require_annotation: true,
|
||||
});
|
||||
}
|
||||
|
||||
// Flatten out the children.
|
||||
for child in &diagnostic.children {
|
||||
push_expected_errors(expected_errors, child, primary_spans, file_name);
|
||||
push_actual_errors(errors, child, primary_spans, file_name);
|
||||
}
|
||||
}
|
||||
|
||||
fn push_backtrace(
|
||||
expected_errors: &mut Vec<Error>,
|
||||
errors: &mut Vec<Error>,
|
||||
expansion: &DiagnosticSpanMacroExpansion,
|
||||
file_name: &str,
|
||||
) {
|
||||
if Path::new(&expansion.span.file_name) == Path::new(&file_name) {
|
||||
expected_errors.push(Error {
|
||||
errors.push(Error {
|
||||
line_num: Some(expansion.span.line_start),
|
||||
kind: Some(ErrorKind::Note),
|
||||
msg: format!("in this expansion of {}", expansion.macro_decl_name),
|
||||
require_annotation: true,
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(previous_expansion) = &expansion.span.expansion {
|
||||
push_backtrace(expected_errors, previous_expansion, file_name);
|
||||
push_backtrace(errors, previous_expansion, file_name);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -810,7 +810,7 @@ impl<'test> TestCx<'test> {
|
|||
expect_help: bool,
|
||||
expect_note: bool,
|
||||
) -> bool {
|
||||
!actual_error.msg.is_empty()
|
||||
actual_error.require_annotation
|
||||
&& match actual_error.kind {
|
||||
Some(ErrorKind::Help) => expect_help,
|
||||
Some(ErrorKind::Note) => expect_note,
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ pub struct Foo;
|
|||
|
||||
pub fn consume_foo(_: Foo) {}
|
||||
//[cfail2]~^ NOTE function defined here
|
||||
//[cfail2]~| NOTE
|
||||
|
||||
pub fn produce_foo() -> Foo {
|
||||
Foo
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use std::future::Future;
|
||||
fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
|
||||
//~^ Error future cannot be sent between threads safely
|
||||
//~^ ERROR future cannot be sent between threads safely
|
||||
async { (ty, ty1) }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,5 +19,5 @@ async fn wrong_mutex() {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
fake_spawn(wrong_mutex()); //~ Error future cannot be sent between threads safely
|
||||
fake_spawn(wrong_mutex()); //~ ERROR future cannot be sent between threads safely
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,18 +5,18 @@ pub struct Example4<const N: usize = 13, const M: usize = 4>;
|
|||
|
||||
fn main() {
|
||||
let e: Example<13> = ();
|
||||
//~^ Error: mismatched types
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected struct `Example`
|
||||
let e: Example2<u32, 13> = ();
|
||||
//~^ Error: mismatched types
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected struct `Example2`
|
||||
let e: Example3<13, u32> = ();
|
||||
//~^ Error: mismatched types
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected struct `Example3`
|
||||
let e: Example3<7> = ();
|
||||
//~^ Error: mismatched types
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected struct `Example3<7>`
|
||||
let e: Example4<7> = ();
|
||||
//~^ Error: mismatched types
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected struct `Example4<7>`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ trait Foo {
|
|||
[Adt; std::mem::size_of::<Self::Assoc>()]: ,
|
||||
{
|
||||
<[Adt; std::mem::size_of::<Self::Assoc>()] as Foo>::bar()
|
||||
//~^ Error: the trait bound
|
||||
//~^ ERROR the trait bound
|
||||
}
|
||||
|
||||
fn bar() {}
|
||||
|
|
|
|||
|
|
@ -15,15 +15,15 @@ where
|
|||
|
||||
// errors are bad but seems to be pre-existing issue #86198
|
||||
assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
|
||||
//~^ Error: mismatched types
|
||||
//~^^ Error: unconstrained generic constant
|
||||
//~^ ERROR mismatched types
|
||||
//~^^ ERROR unconstrained generic constant
|
||||
assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
|
||||
//~^ Error: mismatched types
|
||||
//~^^ Error: unconstrained generic constant
|
||||
//~^ ERROR mismatched types
|
||||
//~^^ ERROR unconstrained generic constant
|
||||
assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>();
|
||||
//~^ Error: mismatched types
|
||||
//~^ ERROR mismatched types
|
||||
assert_impl::<HasCastInTraitImpl<14, 13>>();
|
||||
//~^ Error: mismatched types
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
pub fn use_trait_impl_2<const N: usize>()
|
||||
where
|
||||
|
|
@ -33,15 +33,15 @@ where
|
|||
|
||||
// errors are bad but seems to be pre-existing issue #86198
|
||||
assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
|
||||
//~^ Error: mismatched types
|
||||
//~^^ Error: unconstrained generic constant
|
||||
//~^ ERROR mismatched types
|
||||
//~^^ ERROR unconstrained generic constant
|
||||
assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
|
||||
//~^ Error: mismatched types
|
||||
//~^^ Error: unconstrained generic constant
|
||||
//~^ ERROR mismatched types
|
||||
//~^^ ERROR unconstrained generic constant
|
||||
assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>();
|
||||
//~^ Error: mismatched types
|
||||
//~^ ERROR mismatched types
|
||||
assert_impl::<HasCastInTraitImpl<14, 13>>();
|
||||
//~^ Error: mismatched types
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ pub trait True {}
|
|||
|
||||
impl<const LHS: u32, const RHS: u32> True for IsLessOrEqual<LHS, RHS> where
|
||||
Condition<{ LHS <= RHS }>: True
|
||||
//[min]~^ Error generic parameters may not be used in const operations
|
||||
//[min]~| Error generic parameters may not be used in const operations
|
||||
//[min]~^ ERROR generic parameters may not be used in const operations
|
||||
//[min]~| ERROR generic parameters may not be used in const operations
|
||||
{
|
||||
}
|
||||
impl True for Condition<true> {}
|
||||
|
|
@ -21,8 +21,8 @@ where
|
|||
IsLessOrEqual<I, 8>: True,
|
||||
IsLessOrEqual<J, 8>: True,
|
||||
IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
|
||||
//[min]~^ Error generic parameters may not be used in const operations
|
||||
//[min]~| Error generic parameters may not be used in const operations
|
||||
//[min]~^ ERROR generic parameters may not be used in const operations
|
||||
//[min]~| ERROR generic parameters may not be used in const operations
|
||||
// Condition<{ 8 - I <= 8 - J }>: True,
|
||||
{
|
||||
fn print() {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ trait Foo {
|
|||
[(); std::mem::size_of::<Self::Assoc>()]: ,
|
||||
{
|
||||
Self::AssocInstance == [(); std::mem::size_of::<Self::Assoc>()];
|
||||
//~^ Error: mismatched types
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ fn main() {
|
|||
//~| NOTE constant of non-structural type
|
||||
|
||||
trait Trait: Sized { const ASSOC: Option<Self>; } //~ NOTE constant defined here
|
||||
//~^ NOTE
|
||||
impl Trait for NoDerive { const ASSOC: Option<NoDerive> = Some(NoDerive); }
|
||||
match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), };
|
||||
//~^ ERROR constant of non-structural type `NoDerive` in a pattern
|
||||
|
|
|
|||
|
|
@ -118,14 +118,14 @@ LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: constant of non-structural type `NoDerive` in a pattern
|
||||
--> $DIR/reject_non_structural.rs:97:28
|
||||
--> $DIR/reject_non_structural.rs:98:28
|
||||
|
|
||||
LL | struct NoDerive;
|
||||
| --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
|
||||
...
|
||||
LL | trait Trait: Sized { const ASSOC: Option<Self>; }
|
||||
| ------------------ ------------------------- constant defined here
|
||||
LL | impl Trait for NoDerive { const ASSOC: Option<NoDerive> = Some(NoDerive); }
|
||||
...
|
||||
LL | match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), };
|
||||
| ^^^^^^^^^^^^^^^ constant of non-structural type
|
||||
|
|
||||
|
|
@ -136,7 +136,7 @@ LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: constant of non-structural type `NoDerive` in a pattern
|
||||
--> $DIR/reject_non_structural.rs:102:28
|
||||
--> $DIR/reject_non_structural.rs:103:28
|
||||
|
|
||||
LL | struct NoDerive;
|
||||
| --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
|
||||
|
|
@ -153,7 +153,7 @@ LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: constant of non-structural type `NoDerive` in a pattern
|
||||
--> $DIR/reject_non_structural.rs:107:29
|
||||
--> $DIR/reject_non_structural.rs:108:29
|
||||
|
|
||||
LL | struct NoDerive;
|
||||
| --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
extern "C" {
|
||||
fn foo(x: i32, y: u32, z: i32);
|
||||
//~^ NOTE function defined here
|
||||
//~| NOTE
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0061]: this function takes 3 arguments but 2 arguments were supplied
|
||||
--> $DIR/param-mismatch-foreign.rs:7:5
|
||||
--> $DIR/param-mismatch-foreign.rs:8:5
|
||||
|
|
||||
LL | foo(1i32, 2i32);
|
||||
| ^^^ ---- argument #2 of type `u32` is missing
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ trait Foo {
|
|||
|
||||
impl Foo for () {
|
||||
fn foo<U: Debug>(&self, _: &U) { }
|
||||
//~^ Error method `foo` has incompatible signature for trait
|
||||
//~^ ERROR method `foo` has incompatible signature for trait
|
||||
}
|
||||
|
||||
trait Bar {
|
||||
|
|
@ -15,7 +15,7 @@ trait Bar {
|
|||
|
||||
impl Bar for () {
|
||||
fn bar(&self, _: &impl Debug) { }
|
||||
//~^ Error method `bar` has incompatible signature for trait
|
||||
//~^ ERROR method `bar` has incompatible signature for trait
|
||||
}
|
||||
|
||||
trait Baz {
|
||||
|
|
@ -24,7 +24,7 @@ trait Baz {
|
|||
|
||||
impl Baz for () {
|
||||
fn baz<T: Debug>(&self, _: &impl Debug, _: &T) { }
|
||||
//~^ Error method `baz` has incompatible signature for trait
|
||||
//~^ ERROR method `baz` has incompatible signature for trait
|
||||
}
|
||||
|
||||
// With non-local trait (#49841):
|
||||
|
|
@ -35,7 +35,7 @@ struct X;
|
|||
|
||||
impl Hash for X {
|
||||
fn hash(&self, hasher: &mut impl Hasher) {}
|
||||
//~^ Error method `hash` has incompatible signature for trait
|
||||
//~^ ERROR method `hash` has incompatible signature for trait
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -3,5 +3,5 @@ struct Foo;
|
|||
fn main() {
|
||||
let mut a = Foo;
|
||||
let ref b = Foo;
|
||||
a += *b; //~ Error: binary assignment operation `+=` cannot be applied to type `Foo`
|
||||
a += *b; //~ ERROR binary assignment operation `+=` cannot be applied to type `Foo`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,9 @@ struct bool; //~ NOTE the other `bool` is defined in the current crate
|
|||
struct str; //~ NOTE the other `str` is defined in the current crate
|
||||
|
||||
fn foo(_: bool) {} //~ NOTE function defined here
|
||||
//~^ NOTE
|
||||
fn bar(_: &str) {} //~ NOTE function defined here
|
||||
|
||||
//~^ NOTE
|
||||
fn main() {
|
||||
foo(true);
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/similar_paths_primitive.rs:10:9
|
||||
--> $DIR/similar_paths_primitive.rs:11:9
|
||||
|
|
||||
LL | foo(true);
|
||||
| --- ^^^^ expected `bool`, found a different `bool`
|
||||
|
|
@ -20,7 +20,7 @@ LL | fn foo(_: bool) {}
|
|||
| ^^^ -------
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/similar_paths_primitive.rs:16:9
|
||||
--> $DIR/similar_paths_primitive.rs:17:9
|
||||
|
|
||||
LL | bar("hello");
|
||||
| --- ^^^^^^^ expected `str`, found a different `str`
|
||||
|
|
@ -35,7 +35,7 @@ note: the other `str` is defined in the current crate
|
|||
LL | struct str;
|
||||
| ^^^^^^^^^^
|
||||
note: function defined here
|
||||
--> $DIR/similar_paths_primitive.rs:7:4
|
||||
--> $DIR/similar_paths_primitive.rs:8:4
|
||||
|
|
||||
LL | fn bar(_: &str) {}
|
||||
| ^^^ -------
|
||||
|
|
|
|||
|
|
@ -102,5 +102,5 @@ fn main() {
|
|||
();
|
||||
();
|
||||
();
|
||||
dbg!(lib::Dummy); //~ Error: `Dummy` doesn't implement `Debug`
|
||||
dbg!(lib::Dummy); //~ ERROR `Dummy` doesn't implement `Debug`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ fn foo() {
|
|||
//~| NOTE inside of this loop
|
||||
//~| HELP consider moving the expression out of the loop
|
||||
//~| NOTE in this expansion of desugaring of `for` loop
|
||||
//~| NOTE
|
||||
//~| NOTE
|
||||
baz.push(foo);
|
||||
//~^ NOTE value moved here
|
||||
//~| HELP consider cloning the value
|
||||
|
|
@ -30,17 +32,19 @@ fn main() {
|
|||
for foo in foos {
|
||||
//~^ NOTE this reinitialization might get skipped
|
||||
//~| NOTE move occurs because `foo` has type `String`
|
||||
//~| NOTE
|
||||
for bar in &bars {
|
||||
//~^ NOTE inside of this loop
|
||||
//~| HELP consider moving the expression out of the loop
|
||||
//~| NOTE in this expansion of desugaring of `for` loop
|
||||
//~| NOTE
|
||||
if foo == *bar {
|
||||
baz.push(foo);
|
||||
//~^ NOTE value moved here
|
||||
//~| HELP consider cloning the value
|
||||
continue;
|
||||
//~^ NOTE verify that your loop breaking logic is correct
|
||||
//~| NOTE this `continue` advances the loop at line 33
|
||||
//~| NOTE this `continue` advances the loop at line 36
|
||||
}
|
||||
}
|
||||
qux.push(foo);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0382]: use of moved value: `foo`
|
||||
--> $DIR/nested-loop-moved-value-wrong-continue.rs:19:14
|
||||
--> $DIR/nested-loop-moved-value-wrong-continue.rs:21:14
|
||||
|
|
||||
LL | for foo in foos { for bar in &bars { if foo == *bar {
|
||||
| --- ---------------- inside of this loop
|
||||
|
|
@ -14,13 +14,13 @@ LL | qux.push(foo);
|
|||
| ^^^ value used here after move
|
||||
|
|
||||
note: verify that your loop breaking logic is correct
|
||||
--> $DIR/nested-loop-moved-value-wrong-continue.rs:15:9
|
||||
--> $DIR/nested-loop-moved-value-wrong-continue.rs:17:9
|
||||
|
|
||||
LL | for foo in foos { for bar in &bars { if foo == *bar {
|
||||
| --------------- ----------------
|
||||
...
|
||||
LL | continue;
|
||||
| ^^^^^^^^ this `continue` advances the loop at $DIR/nested-loop-moved-value-wrong-continue.rs:6:23: 18:8
|
||||
| ^^^^^^^^ this `continue` advances the loop at $DIR/nested-loop-moved-value-wrong-continue.rs:6:23: 20:8
|
||||
help: consider moving the expression out of the loop so it is only moved once
|
||||
|
|
||||
LL ~ for foo in foos { let mut value = baz.push(foo);
|
||||
|
|
@ -36,7 +36,7 @@ LL | baz.push(foo.clone());
|
|||
| ++++++++
|
||||
|
||||
error[E0382]: use of moved value: `foo`
|
||||
--> $DIR/nested-loop-moved-value-wrong-continue.rs:46:18
|
||||
--> $DIR/nested-loop-moved-value-wrong-continue.rs:50:18
|
||||
|
|
||||
LL | for foo in foos {
|
||||
| ---
|
||||
|
|
@ -54,7 +54,7 @@ LL | qux.push(foo);
|
|||
| ^^^ value used here after move
|
||||
|
|
||||
note: verify that your loop breaking logic is correct
|
||||
--> $DIR/nested-loop-moved-value-wrong-continue.rs:41:17
|
||||
--> $DIR/nested-loop-moved-value-wrong-continue.rs:45:17
|
||||
|
|
||||
LL | for foo in foos {
|
||||
| ---------------
|
||||
|
|
@ -63,7 +63,7 @@ LL | for bar in &bars {
|
|||
| ----------------
|
||||
...
|
||||
LL | continue;
|
||||
| ^^^^^^^^ this `continue` advances the loop at line 33
|
||||
| ^^^^^^^^ this `continue` advances the loop at line 36
|
||||
help: consider moving the expression out of the loop so it is only moved once
|
||||
|
|
||||
LL ~ let mut value = baz.push(foo);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ pub fn a() {
|
|||
|
||||
#[export_name="fail"]
|
||||
pub fn b() {
|
||||
//~^ Error symbol `fail` is already defined
|
||||
//~^ ERROR symbol `fail` is already defined
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -10,5 +10,6 @@ const async const fn test() {}
|
|||
//~| ERROR functions cannot be both `const` and `async`
|
||||
//~| NOTE `const` because of this
|
||||
//~| NOTE `async` because of this
|
||||
//~| NOTE
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -15,5 +15,6 @@ async unsafe const fn test() {}
|
|||
//~| ERROR functions cannot be both `const` and `async`
|
||||
//~| NOTE `const` because of this
|
||||
//~| NOTE `async` because of this
|
||||
//~| NOTE
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -6,11 +6,14 @@ extern crate issue_91800_macro;
|
|||
#[derive(MyTrait)]
|
||||
//~^ ERROR macros that expand to items must be delimited with braces or followed by a semicolon
|
||||
//~| ERROR proc-macro derive produced unparsable tokens
|
||||
//~| ERROR
|
||||
#[attribute_macro]
|
||||
//~^ ERROR macros that expand to items must be delimited with braces or followed by a semicolon
|
||||
//~| ERROR
|
||||
struct MyStruct;
|
||||
|
||||
fn_macro! {}
|
||||
//~^ ERROR macros that expand to items must be delimited with braces or followed by a semicolon
|
||||
//~| ERROR
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ LL | #[derive(MyTrait)]
|
|||
= note: this error originates in the derive macro `MyTrait` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: macros that expand to items must be delimited with braces or followed by a semicolon
|
||||
--> $DIR/issue-91800.rs:9:1
|
||||
--> $DIR/issue-91800.rs:10:1
|
||||
|
|
||||
LL | #[attribute_macro]
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -29,7 +29,7 @@ LL | #[attribute_macro]
|
|||
= note: this error originates in the attribute macro `attribute_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error:
|
||||
--> $DIR/issue-91800.rs:9:1
|
||||
--> $DIR/issue-91800.rs:10:1
|
||||
|
|
||||
LL | #[attribute_macro]
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -37,7 +37,7 @@ LL | #[attribute_macro]
|
|||
= note: this error originates in the attribute macro `attribute_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: macros that expand to items must be delimited with braces or followed by a semicolon
|
||||
--> $DIR/issue-91800.rs:13:1
|
||||
--> $DIR/issue-91800.rs:15:1
|
||||
|
|
||||
LL | fn_macro! {}
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
@ -45,7 +45,7 @@ LL | fn_macro! {}
|
|||
= note: this error originates in the macro `fn_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error:
|
||||
--> $DIR/issue-91800.rs:13:1
|
||||
--> $DIR/issue-91800.rs:15:1
|
||||
|
|
||||
LL | fn_macro! {}
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
|
|||
|
|
@ -4,15 +4,15 @@ struct A {
|
|||
|
||||
impl A {
|
||||
fn new(cofig: String) -> Self {
|
||||
Self { config } //~ Error cannot find value `config` in this scope
|
||||
Self { config } //~ ERROR cannot find value `config` in this scope
|
||||
}
|
||||
|
||||
fn do_something(cofig: String) {
|
||||
println!("{config}"); //~ Error cannot find value `config` in this scope
|
||||
println!("{config}"); //~ ERROR cannot find value `config` in this scope
|
||||
}
|
||||
|
||||
fn self_is_available(self, cofig: String) {
|
||||
println!("{config}"); //~ Error cannot find value `config` in this scope
|
||||
println!("{config}"); //~ ERROR cannot find value `config` in this scope
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ trait Cat {
|
|||
fn uwu<T: Cat>(c: T) {
|
||||
c.nya();
|
||||
//~^ ERROR no method named `nya` found for type parameter `T` in the current scope
|
||||
//~| Suggestion T::nya()
|
||||
//~| SUGGESTION T::nya()
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ impl Foo for S2 {
|
|||
type Item = impl Debug;
|
||||
|
||||
fn foo<T: Debug>(_: T) -> Self::Item {
|
||||
//~^ Error type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
|
||||
//~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
|
||||
S::<T>(Default::default())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue