-
Notifications
You must be signed in to change notification settings - Fork 13.4k
fix: ensure bad #[test]
invocs retain correct AST
#110035
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -107,6 +107,36 @@ pub fn expand_test_or_bench( | |
return vec![]; | ||
} | ||
|
||
let not_testable_error = |item: Option<&ast::Item>| { | ||
let diag = &cx.sess.parse_sess.span_diagnostic; | ||
let msg = "the `#[test]` attribute may only be used on a non-associated function"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you make this translatable? See #100717. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, I'd prefer not to do this right now. The whole I'm happy to do this if you really want, just not sure it's currently worth the effort. |
||
let mut err = match item.map(|i| &i.kind) { | ||
// These were a warning before #92959 and need to continue being that to avoid breaking | ||
// stable user code (#94508). | ||
Some(ast::ItemKind::MacCall(_)) => diag.struct_span_warn(attr_sp, msg), | ||
// `.forget_guarantee()` needed to get these two arms to match types. Because of how | ||
// locally close the `.emit()` call is I'm comfortable with it, but if it can be | ||
// reworked in the future to not need it, it'd be nice. | ||
_ => diag.struct_span_err(attr_sp, msg).forget_guarantee(), | ||
}; | ||
if let Some(item) = item { | ||
err.span_label( | ||
item.span, | ||
format!( | ||
"expected a non-associated function, found {} {}", | ||
item.kind.article(), | ||
item.kind.descr() | ||
), | ||
); | ||
} | ||
err.span_label(attr_sp, "the `#[test]` macro causes a function to be run as a test and has no effect on non-functions") | ||
.span_suggestion(attr_sp, | ||
"replace with conditional compilation to make the item only exist when tests are being run", | ||
"#[cfg(test)]", | ||
Applicability::MaybeIncorrect) | ||
.emit(); | ||
}; | ||
|
||
let (item, is_stmt) = match item { | ||
Annotatable::Item(i) => (i, false), | ||
Annotatable::Stmt(stmt) if matches!(stmt.kind, ast::StmtKind::Item(_)) => { | ||
|
@@ -118,34 +148,22 @@ pub fn expand_test_or_bench( | |
} | ||
} | ||
other => { | ||
cx.struct_span_err( | ||
other.span(), | ||
"`#[test]` attribute is only allowed on non associated functions", | ||
) | ||
.emit(); | ||
not_testable_error(None); | ||
return vec![other]; | ||
} | ||
}; | ||
|
||
// Note: non-associated fn items are already handled by `expand_test_or_bench` | ||
let ast::ItemKind::Fn(fn_) = &item.kind else { | ||
let diag = &cx.sess.parse_sess.span_diagnostic; | ||
let msg = "the `#[test]` attribute may only be used on a non-associated function"; | ||
let mut err = match item.kind { | ||
// These were a warning before #92959 and need to continue being that to avoid breaking | ||
// stable user code (#94508). | ||
ast::ItemKind::MacCall(_) => diag.struct_span_warn(attr_sp, msg), | ||
// `.forget_guarantee()` needed to get these two arms to match types. Because of how | ||
// locally close the `.emit()` call is I'm comfortable with it, but if it can be | ||
// reworked in the future to not need it, it'd be nice. | ||
_ => diag.struct_span_err(attr_sp, msg).forget_guarantee(), | ||
not_testable_error(Some(&item)); | ||
return if is_stmt { | ||
vec![Annotatable::Stmt(P(ast::Stmt { | ||
id: ast::DUMMY_NODE_ID, | ||
span: item.span, | ||
kind: ast::StmtKind::Item(item), | ||
}))] | ||
} else { | ||
vec![Annotatable::Item(item)] | ||
}; | ||
err.span_label(attr_sp, "the `#[test]` macro causes a function to be run on a test and has no effect on non-functions") | ||
.span_label(item.span, format!("expected a non-associated function, found {} {}", item.kind.article(), item.kind.descr())) | ||
.span_suggestion(attr_sp, "replace with conditional compilation to make the item only exist when tests are being run", "#[cfg(test)]", Applicability::MaybeIncorrect) | ||
.emit(); | ||
|
||
return vec![Annotatable::Item(item)]; | ||
}; | ||
|
||
// has_*_signature will report any errors in the type so compilation | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
// compile-flags: --test | ||
|
||
fn align_offset_weird_strides() { | ||
#[test] | ||
//~^ ERROR the `#[test]` attribute may only be used on a non-associated function | ||
struct A5(u32, u8); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
error: the `#[test]` attribute may only be used on a non-associated function | ||
--> $DIR/issue-109816.rs:4:5 | ||
| | ||
LL | #[test] | ||
| ^^^^^^^ the `#[test]` macro causes a function to be run as a test and has no effect on non-functions | ||
LL | | ||
LL | struct A5(u32, u8); | ||
| ------------------- expected a non-associated function, found a struct | ||
| | ||
help: replace with conditional compilation to make the item only exist when tests are being run | ||
| | ||
LL | #[cfg(test)] | ||
| | ||
|
||
error: aborting due to previous error | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,24 @@ | ||
error: `#[test]` attribute is only allowed on non associated functions | ||
--> $DIR/test-attr-non-associated-functions.rs:9:5 | ||
| | ||
LL | / fn new() -> A { | ||
LL | | | ||
LL | | A {} | ||
LL | | } | ||
| |_____^ | ||
error: the `#[test]` attribute may only be used on a non-associated function | ||
--> $DIR/test-attr-non-associated-functions.rs:6:5 | ||
| | ||
LL | #[test] | ||
| ^^^^^^^ the `#[test]` macro causes a function to be run as a test and has no effect on non-functions | ||
| | ||
help: replace with conditional compilation to make the item only exist when tests are being run | ||
| | ||
LL | #[cfg(test)] | ||
| | ||
|
||
error: `#[test]` attribute is only allowed on non associated functions | ||
--> $DIR/test-attr-non-associated-functions.rs:14:5 | ||
| | ||
LL | / fn recovery_witness() -> A { | ||
LL | | | ||
LL | | A {} | ||
LL | | } | ||
| |_____^ | ||
error: the `#[test]` attribute may only be used on a non-associated function | ||
--> $DIR/test-attr-non-associated-functions.rs:11:5 | ||
| | ||
LL | #[test] | ||
| ^^^^^^^ the `#[test]` macro causes a function to be run as a test and has no effect on non-functions | ||
| | ||
help: replace with conditional compilation to make the item only exist when tests are being run | ||
| | ||
LL | #[cfg(test)] | ||
| | ||
|
||
error: aborting due to 2 previous errors | ||
|
Uh oh!
There was an error while loading. Please reload this page.