]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_builtin_macros/src/test.rs
Rollup merge of #93400 - ChayimFriedman2:dont-suggest-using-const-with-bounds-unused...
[rust.git] / compiler / rustc_builtin_macros / src / test.rs
index 9459bb7047f5c64e2f45b53c7c8787431bd349e4..e658631d09038ee22ec243927e53074810f4c970 100644 (file)
@@ -6,6 +6,7 @@
 use rustc_ast::attr;
 use rustc_ast::ptr::P;
 use rustc_ast_pretty::pprust;
+use rustc_errors::Applicability;
 use rustc_expand::base::*;
 use rustc_session::Session;
 use rustc_span::symbol::{sym, Ident, Symbol};
@@ -102,11 +103,20 @@ pub fn expand_test_or_bench(
         }
     };
 
-    if let ast::ItemKind::MacCall(_) = item.kind {
-        cx.sess.parse_sess.span_diagnostic.span_warn(
-            item.span,
-            "`#[test]` attribute should not be used on macros. Use `#[cfg(test)]` instead.",
-        );
+    // Note: non-associated fn items are already handled by `expand_test_or_bench`
+    if !matches!(item.kind, ast::ItemKind::Fn(_)) {
+        cx.sess
+            .parse_sess
+            .span_diagnostic
+            .struct_span_err(
+                attr_sp,
+                "the `#[test]` attribute may only be used on a non-associated function",
+            )
+            .note("the `#[test]` macro causes a 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", String::from("#[cfg(test)]"), Applicability::MaybeIncorrect)
+            .emit();
+
         return vec![Annotatable::Item(item)];
     }
 
@@ -252,6 +262,15 @@ pub fn expand_test_or_bench(
                                         "ignore",
                                         cx.expr_bool(sp, should_ignore(&cx.sess, &item)),
                                     ),
+                                    // ignore_message: Some("...") | None
+                                    field(
+                                        "ignore_message",
+                                        if let Some(msg) = should_ignore_message(cx, &item) {
+                                            cx.expr_some(sp, cx.expr_str(sp, msg))
+                                        } else {
+                                            cx.expr_none(sp)
+                                        },
+                                    ),
                                     // compile_fail: true | false
                                     field("compile_fail", cx.expr_bool(sp, false)),
                                     // no_run: true | false
@@ -354,6 +373,20 @@ fn should_ignore(sess: &Session, i: &ast::Item) -> bool {
     sess.contains_name(&i.attrs, sym::ignore)
 }
 
+fn should_ignore_message(cx: &ExtCtxt<'_>, i: &ast::Item) -> Option<Symbol> {
+    match cx.sess.find_by_name(&i.attrs, sym::ignore) {
+        Some(attr) => {
+            match attr.meta_item_list() {
+                // Handle #[ignore(bar = "foo")]
+                Some(_) => None,
+                // Handle #[ignore] and #[ignore = "message"]
+                None => attr.value_str(),
+            }
+        }
+        None => None,
+    }
+}
+
 fn should_panic(cx: &ExtCtxt<'_>, i: &ast::Item) -> ShouldPanic {
     match cx.sess.find_by_name(&i.attrs, sym::should_panic) {
         Some(attr) => {
@@ -466,7 +499,7 @@ fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
             (false, _) => true,
         }
     } else {
-        sd.span_err(i.span, "only functions may be used as tests");
+        // should be unreachable because `is_test_fn_item` should catch all non-fn items
         false
     }
 }