diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 87c4bfae1af..f6b18bdea51 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -366,16 +366,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                          over time"
                     );
                 }
-                if self.sess.contains_name(&i.attrs[..], sym::main) {
-                    gate_feature_post!(
-                        &self,
-                        main,
-                        i.span,
-                        "declaration of a non-standard `#[main]` \
-                         function may change over time, for now \
-                         a top-level `fn main()` is required"
-                    );
-                }
             }
 
             ast::ItemKind::Struct(..) => {
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index 28e82597843..c8a7ff67b4d 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -142,7 +142,7 @@ fn entry_point_type(sess: &Session, item: &ast::Item, depth: usize) -> EntryPoin
         ast::ItemKind::Fn(..) => {
             if sess.contains_name(&item.attrs, sym::start) {
                 EntryPointType::Start
-            } else if sess.contains_name(&item.attrs, sym::main) {
+            } else if sess.contains_name(&item.attrs, sym::rustc_main) {
                 EntryPointType::MainAttr
             } else if item.ident.name == sym::main {
                 if depth == 1 {
@@ -187,7 +187,7 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> {
                     let attrs = attrs
                         .into_iter()
                         .filter(|attr| {
-                            !self.sess.check_name(attr, sym::main)
+                            !self.sess.check_name(attr, sym::rustc_main)
                                 && !self.sess.check_name(attr, sym::start)
                         })
                         .chain(iter::once(allow_dead_code))
@@ -220,7 +220,7 @@ fn generate_test_harness(
     let expn_id = ext_cx.resolver.expansion_for_ast_pass(
         DUMMY_SP,
         AstPass::TestHarness,
-        &[sym::main, sym::test, sym::rustc_attrs],
+        &[sym::test, sym::rustc_attrs],
         None,
     );
     let def_site = DUMMY_SP.with_def_site_ctxt(expn_id);
@@ -247,7 +247,7 @@ fn generate_test_harness(
 /// By default this expands to
 ///
 /// ```
-/// #[main]
+/// #[rustc_main]
 /// pub fn main() {
 ///     extern crate test;
 ///     test::test_main_static(&[
@@ -297,8 +297,8 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
     let test_extern_stmt =
         ecx.stmt_item(sp, ecx.item(sp, test_id, vec![], ast::ItemKind::ExternCrate(None)));
 
-    // #[main]
-    let main_meta = ecx.meta_word(sp, sym::main);
+    // #[rustc_main]
+    let main_meta = ecx.meta_word(sp, sym::rustc_main);
     let main_attr = ecx.attribute(main_meta);
 
     // pub fn main() { ... }
diff --git a/compiler/rustc_error_codes/src/error_codes/E0137.md b/compiler/rustc_error_codes/src/error_codes/E0137.md
index 0a02913d236..d4e19170f3f 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0137.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0137.md
@@ -1,8 +1,10 @@
+#### Note: this error code is no longer emitted by the compiler.
+
 More than one function was declared with the `#[main]` attribute.
 
 Erroneous code example:
 
-```compile_fail,E0137
+```compile_fail
 #![feature(main)]
 
 #[main]
@@ -16,7 +18,7 @@ This error indicates that the compiler found multiple functions with the
 `#[main]` attribute. This is an error because there must be a unique entry
 point into a Rust program. Example:
 
-```
+```compile_fail
 #![feature(main)]
 
 #[main]
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 1a91eb600a9..6fd1af60fe2 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -134,9 +134,6 @@ declare_features! (
     /// Allows using the `box $expr` syntax.
     (active, box_syntax, "1.0.0", Some(49733), None),
 
-    /// Allows using `#[main]` to replace the entrypoint `#[lang = "start"]` calls.
-    (active, main, "1.0.0", Some(29634), None),
-
     /// Allows using `#[start]` on a function indicating that it is the program entrypoint.
     (active, start, "1.0.0", Some(29633), None),
 
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 7df9b3f0a79..f286ea7cdec 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -536,6 +536,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         rustc_specialization_trait, Normal, template!(Word),
         "the `#[rustc_specialization_trait]` attribute is used to check specializations"
     ),
+    rustc_attr!(
+        rustc_main, Normal, template!(Word),
+        "the `#[rustc_main]` attribute is used internally to specify test entry point function",
+    ),
 
     // ==========================================================================
     // Internal attributes, Testing:
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index e1491576616..c2ad339ed41 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -132,6 +132,8 @@ declare_features! (
     (removed, link_args, "1.53.0", Some(29596), None,
      Some("removed in favor of using `-C link-arg=ARG` on command line, \
            which is available from cargo build scripts with `cargo:rustc-link-arg` now")),
+    /// Allows using `#[main]` to replace the entrypoint `#[lang = "start"]` calls.
+    (removed, main, "1.53.0", Some(29634), None, None),
 
     // -------------------------------------------------------------------------
     // feature-group-end: removed features
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index df292b14176..b1debcffd64 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -1489,7 +1489,7 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
         sym::path,
         sym::automatically_derived,
         sym::start,
-        sym::main,
+        sym::rustc_main,
     ];
 
     for attr in attrs {
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index e53f821e6da..e1b750df33c 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -84,7 +84,7 @@ fn entry_point_type(ctxt: &EntryContext<'_, '_>, item: &Item<'_>, at_root: bool)
     let attrs = ctxt.map.attrs(item.hir_id());
     if ctxt.session.contains_name(attrs, sym::start) {
         EntryPointType::Start
-    } else if ctxt.session.contains_name(attrs, sym::main) {
+    } else if ctxt.session.contains_name(attrs, sym::rustc_main) {
         EntryPointType::MainAttr
     } else if item.ident.name == sym::main {
         if at_root {
@@ -111,8 +111,8 @@ fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
             if let Some(attr) = ctxt.session.find_by_name(attrs, sym::start) {
                 throw_attr_err(&ctxt.session, attr.span, "start");
             }
-            if let Some(attr) = ctxt.session.find_by_name(attrs, sym::main) {
-                throw_attr_err(&ctxt.session, attr.span, "main");
+            if let Some(attr) = ctxt.session.find_by_name(attrs, sym::rustc_main) {
+                throw_attr_err(&ctxt.session, attr.span, "rustc_main");
             }
         }
         EntryPointType::MainNamed => {
@@ -193,10 +193,7 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) {
             err.span_note(span, "here is a function named `main`");
         }
         err.note("you have one or more functions named `main` not defined at the crate level");
-        err.help(
-            "either move the `main` function definitions or attach the `#[main]` attribute \
-                  to one of them",
-        );
+        err.help("consider moving the `main` function definitions");
         // There were some functions named `main` though. Try to give the user a hint.
         format!(
             "the main function must be defined at the crate level{}",
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 42e521a20a3..ac23e161726 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1008,6 +1008,7 @@ symbols! {
         rustc_layout_scalar_valid_range_start,
         rustc_legacy_const_generics,
         rustc_macro_transparency,
+        rustc_main,
         rustc_mir,
         rustc_nonnull_optimization_guaranteed,
         rustc_object_lifetime_default,
diff --git a/src/test/ui/attr-main-2.rs b/src/test/ui/attr-main-2.rs
deleted file mode 100644
index 3a51f83ba3b..00000000000
--- a/src/test/ui/attr-main-2.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-// run-pass
-
-#![feature(main)]
-
-pub fn main() {
-    panic!()
-}
-
-#[main]
-fn foo() {
-}
diff --git a/src/test/ui/attr-main.rs b/src/test/ui/attr-main.rs
deleted file mode 100644
index 9c4caaa4a42..00000000000
--- a/src/test/ui/attr-main.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// run-pass
-// pretty-expanded FIXME #23616
-
-#![feature(main)]
-
-#[main]
-fn foo() {
-}
diff --git a/src/test/ui/attr.rs b/src/test/ui/attr.rs
deleted file mode 100644
index 9c4caaa4a42..00000000000
--- a/src/test/ui/attr.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// run-pass
-// pretty-expanded FIXME #23616
-
-#![feature(main)]
-
-#[main]
-fn foo() {
-}
diff --git a/src/test/ui/error-codes/E0137.rs b/src/test/ui/error-codes/E0137.rs
deleted file mode 100644
index b8299c71bdf..00000000000
--- a/src/test/ui/error-codes/E0137.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-#![feature(main)]
-
-#[main]
-fn foo() {}
-
-#[main]
-fn f() {}
-//~^ ERROR E0137
diff --git a/src/test/ui/error-codes/E0137.stderr b/src/test/ui/error-codes/E0137.stderr
deleted file mode 100644
index f4d5e10369a..00000000000
--- a/src/test/ui/error-codes/E0137.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0137]: multiple functions with a `#[main]` attribute
-  --> $DIR/E0137.rs:7:1
-   |
-LL | fn foo() {}
-   | ----------- first `#[main]` function
-...
-LL | fn f() {}
-   | ^^^^^^^^^ additional `#[main]` function
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0137`.
diff --git a/src/test/ui/feature-gates/feature-gate-main.rs b/src/test/ui/feature-gates/feature-gate-main.rs
deleted file mode 100644
index 9c304a1792f..00000000000
--- a/src/test/ui/feature-gates/feature-gate-main.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#[main]
-fn foo() {} //~ ERROR: declaration of a non-standard `#[main]` function may change over time
diff --git a/src/test/ui/feature-gates/feature-gate-main.stderr b/src/test/ui/feature-gates/feature-gate-main.stderr
deleted file mode 100644
index f0ef3b38c62..00000000000
--- a/src/test/ui/feature-gates/feature-gate-main.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: declaration of a non-standard `#[main]` function may change over time, for now a top-level `fn main()` is required
-  --> $DIR/feature-gate-main.rs:2:1
-   |
-LL | fn foo() {}
-   | ^^^^^^^^^^^
-   |
-   = note: see issue #29634 <https://github.com/rust-lang/rust/issues/29634> for more information
-   = help: add `#![feature(main)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs
index 07167fa695e..d1fbd38ce07 100644
--- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs
+++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs
@@ -11,8 +11,8 @@
 
 #![macro_export]
 //~^ ERROR: `macro_export` attribute cannot be used at crate level
-#![main]
-//~^ ERROR: `main` attribute cannot be used at crate level
+#![rustc_main] //~ ERROR: the `#[rustc_main]` attribute is used internally to specify
+//~^ ERROR: `rustc_main` attribute cannot be used at crate level
 #![start]
 //~^ ERROR: `start` attribute cannot be used at crate level
 #![repr()]
@@ -106,24 +106,6 @@ mod export_name {
     //~| NOTE not a function or static
 }
 
-#[main]
-//~^ ERROR: `main` attribute can only be used on functions
-mod main {
-    mod inner { #![main] }
-    //~^ ERROR: `main` attribute can only be used on functions
-
-    // for `fn f()` case, see feature-gate-main.rs
-
-    #[main] struct S;
-    //~^ ERROR: `main` attribute can only be used on functions
-
-    #[main] type T = S;
-    //~^ ERROR: `main` attribute can only be used on functions
-
-    #[main] impl S { }
-    //~^ ERROR: `main` attribute can only be used on functions
-}
-
 #[start]
 //~^ ERROR: `start` attribute can only be used on functions
 mod start {
diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
index 33a5021cde4..ae2c428cc75 100644
--- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
+++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
@@ -1,3 +1,11 @@
+error[E0658]: the `#[rustc_main]` attribute is used internally to specify test entry point function
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:14:1
+   |
+LL | #![rustc_main]
+   | ^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
+
 error: attribute must be of the form `#[inline]` or `#[inline(always|never)]`
   --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:40:5
    |
@@ -8,62 +16,32 @@ LL |     #[inline = "2100"] fn f() { }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
 
-error: `main` attribute can only be used on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:109:1
-   |
-LL | #[main]
-   | ^^^^^^^
-
-error: `main` attribute can only be used on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:112:17
-   |
-LL |     mod inner { #![main] }
-   |                 ^^^^^^^^
-
-error: `main` attribute can only be used on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:117:5
-   |
-LL |     #[main] struct S;
-   |     ^^^^^^^
-
-error: `main` attribute can only be used on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:120:5
-   |
-LL |     #[main] type T = S;
-   |     ^^^^^^^
-
-error: `main` attribute can only be used on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:123:5
-   |
-LL |     #[main] impl S { }
-   |     ^^^^^^^
-
 error: `start` attribute can only be used on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:127:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:109:1
    |
 LL | #[start]
    | ^^^^^^^^
 
 error: `start` attribute can only be used on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:130:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:112:17
    |
 LL |     mod inner { #![start] }
    |                 ^^^^^^^^^
 
 error: `start` attribute can only be used on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:135:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:117:5
    |
 LL |     #[start] struct S;
    |     ^^^^^^^^
 
 error: `start` attribute can only be used on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:138:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:120:5
    |
 LL |     #[start] type T = S;
    |     ^^^^^^^^
 
 error: `start` attribute can only be used on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:141:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:123:5
    |
 LL |     #[start] impl S { }
    |     ^^^^^^^^
@@ -137,11 +115,11 @@ error: `macro_export` attribute cannot be used at crate level
 LL | #![macro_export]
    | ^^^^^^^^^^^^^^^^
 
-error: `main` attribute cannot be used at crate level
+error: `rustc_main` attribute cannot be used at crate level
   --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:14:1
    |
-LL | #![main]
-   | ^^^^^^^^
+LL | #![rustc_main]
+   | ^^^^^^^^^^^^^^
 
 error: `start` attribute cannot be used at crate level
   --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:16:1
@@ -245,6 +223,7 @@ error: attribute should be applied to a function or static
 LL |     #[export_name = "2200"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^ ---------- not a function or static
 
-error: aborting due to 36 previous errors
+error: aborting due to 32 previous errors
 
-For more information about this error, try `rustc --explain E0518`.
+Some errors have detailed explanations: E0518, E0658.
+For more information about an error, try `rustc --explain E0518`.
diff --git a/src/test/ui/intrinsics/intrinsic-alignment.rs b/src/test/ui/intrinsics/intrinsic-alignment.rs
index 2bf40db5ad2..592409ba89f 100644
--- a/src/test/ui/intrinsics/intrinsic-alignment.rs
+++ b/src/test/ui/intrinsics/intrinsic-alignment.rs
@@ -1,7 +1,7 @@
 // run-pass
 // ignore-wasm32-bare seems not important to test here
 
-#![feature(intrinsics, main)]
+#![feature(intrinsics)]
 
 mod rusti {
     extern "rust-intrinsic" {
@@ -21,7 +21,6 @@ mod rusti {
           target_os = "solaris",
           target_os = "vxworks"))]
 mod m {
-    #[main]
     #[cfg(target_arch = "x86")]
     pub fn main() {
         unsafe {
@@ -30,7 +29,6 @@ mod m {
         }
     }
 
-    #[main]
     #[cfg(not(target_arch = "x86"))]
     pub fn main() {
         unsafe {
@@ -42,7 +40,6 @@ mod m {
 
 #[cfg(target_env = "sgx")]
 mod m {
-    #[main]
     #[cfg(target_arch = "x86_64")]
     pub fn main() {
         unsafe {
@@ -54,7 +51,6 @@ mod m {
 
 #[cfg(target_os = "windows")]
 mod m {
-    #[main]
     pub fn main() {
         unsafe {
             assert_eq!(::rusti::pref_align_of::<u64>(), 8);
@@ -62,3 +58,7 @@ mod m {
         }
     }
 }
+
+fn main() {
+    m::main();
+}
diff --git a/src/test/ui/lint/dead-code/lint-dead-code-2.rs b/src/test/ui/lint/dead-code/lint-dead-code-2.rs
index 88db4f88c3f..2cfe6e539db 100644
--- a/src/test/ui/lint/dead-code/lint-dead-code-2.rs
+++ b/src/test/ui/lint/dead-code/lint-dead-code-2.rs
@@ -1,6 +1,6 @@
 #![allow(unused_variables)]
 #![deny(dead_code)]
-#![feature(main, start)]
+#![feature(rustc_attrs, start)]
 
 struct Foo;
 
@@ -21,7 +21,7 @@ fn live_fn() {}
 
 fn dead_fn() {} //~ ERROR: function is never used
 
-#[main]
+#[rustc_main]
 fn dead_fn2() {} //~ ERROR: function is never used
 
 fn used_fn() {}
diff --git a/src/test/ui/main-wrong-location.rs b/src/test/ui/main-wrong-location.rs
index f75d08813cd..f3acd80a7a4 100644
--- a/src/test/ui/main-wrong-location.rs
+++ b/src/test/ui/main-wrong-location.rs
@@ -1,6 +1,6 @@
 mod m {
 //~^ ERROR `main` function not found
-    // An inferred main entry point (that doesn't use #[main])
+    // An inferred main entry point
     // must appear at the top of the crate
     fn main() { }
 }
diff --git a/src/test/ui/main-wrong-location.stderr b/src/test/ui/main-wrong-location.stderr
index e301c2ff09a..754ff0f80eb 100644
--- a/src/test/ui/main-wrong-location.stderr
+++ b/src/test/ui/main-wrong-location.stderr
@@ -3,7 +3,7 @@ error[E0601]: `main` function not found in crate `main_wrong_location`
    |
 LL | / mod m {
 LL | |
-LL | |     // An inferred main entry point (that doesn't use #[main])
+LL | |     // An inferred main entry point
 LL | |     // must appear at the top of the crate
 LL | |     fn main() { }
 LL | | }
@@ -15,7 +15,7 @@ note: here is a function named `main`
 LL |     fn main() { }
    |     ^^^^^^^^^^^^^
    = note: you have one or more functions named `main` not defined at the crate level
-   = help: either move the `main` function definitions or attach the `#[main]` attribute to one of them
+   = help: consider moving the `main` function definitions
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/multiple-main-2.rs b/src/test/ui/multiple-main-2.rs
deleted file mode 100644
index e4685b1e004..00000000000
--- a/src/test/ui/multiple-main-2.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-#![feature(main)]
-
-#[main]
-fn bar() {
-}
-
-#[main]
-fn foo() { //~ ERROR multiple functions with a `#[main]` attribute
-}
diff --git a/src/test/ui/multiple-main-2.stderr b/src/test/ui/multiple-main-2.stderr
deleted file mode 100644
index 24bc9a8878b..00000000000
--- a/src/test/ui/multiple-main-2.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0137]: multiple functions with a `#[main]` attribute
-  --> $DIR/multiple-main-2.rs:8:1
-   |
-LL | / fn bar() {
-LL | | }
-   | |_- first `#[main]` function
-...
-LL | / fn foo() {
-LL | | }
-   | |_^ additional `#[main]` function
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0137`.
diff --git a/src/test/ui/multiple-main-3.rs b/src/test/ui/multiple-main-3.rs
deleted file mode 100644
index d1b5ae9a833..00000000000
--- a/src/test/ui/multiple-main-3.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-#![feature(main)]
-
-#[main]
-fn main1() {
-}
-
-mod foo {
-    #[main]
-    fn main2() { //~ ERROR multiple functions with a `#[main]` attribute
-    }
-}
diff --git a/src/test/ui/multiple-main-3.stderr b/src/test/ui/multiple-main-3.stderr
deleted file mode 100644
index ec171b76a28..00000000000
--- a/src/test/ui/multiple-main-3.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0137]: multiple functions with a `#[main]` attribute
-  --> $DIR/multiple-main-3.rs:9:5
-   |
-LL | / fn main1() {
-LL | | }
-   | |_- first `#[main]` function
-...
-LL | /     fn main2() {
-LL | |     }
-   | |_____^ additional `#[main]` function
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0137`.
diff --git a/src/test/ui/test-attrs/test-main-not-dead-attr.rs b/src/test/ui/test-attrs/test-main-not-dead-attr.rs
index 628b1896ace..0b2a9a3541b 100644
--- a/src/test/ui/test-attrs/test-main-not-dead-attr.rs
+++ b/src/test/ui/test-attrs/test-main-not-dead-attr.rs
@@ -1,9 +1,9 @@
 // run-pass
 // compile-flags: --test
 
-#![feature(main)]
+#![feature(rustc_attrs)]
 
 #![deny(dead_code)]
 
-#[main]
+#[rustc_main]
 fn foo() { panic!(); }
diff --git a/src/test/ui/test-attrs/test-runner-hides-buried-main.rs b/src/test/ui/test-attrs/test-runner-hides-buried-main.rs
index bf5482056d4..346aa868eb4 100644
--- a/src/test/ui/test-attrs/test-runner-hides-buried-main.rs
+++ b/src/test/ui/test-attrs/test-runner-hides-buried-main.rs
@@ -1,14 +1,14 @@
 // run-pass
 // compile-flags: --test
 
-#![feature(main)]
+#![feature(rustc_attrs)]
 
 #![allow(dead_code)]
 
 mod a {
     fn b() {
         (|| {
-            #[main]
+            #[rustc_main]
             fn c() { panic!(); }
         })();
     }
diff --git a/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs b/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs
index 995787c5336..7ff5a16ed86 100644
--- a/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs
+++ b/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.rs
@@ -1,11 +1,11 @@
 // ignore-macos
 // ignore-windows
 
-#![feature(main)]
+#![feature(rustc_attrs)]
 
 #[warn(clippy::main_recursion)]
 #[allow(unconditional_recursion)]
-#[main]
+#[rustc_main]
 fn a() {
     println!("Hello, World!");
     a();