fix: ensure bad #[test]
invocs retain correct AST
This commit is contained in:
parent
c934ce9e0a
commit
f4e7a99662
6 changed files with 95 additions and 52 deletions
|
@ -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";
|
||||
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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue