about summary refs log tree commit diff
path: root/compiler/rustc_passes/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-10-05 02:49:51 +0000
committerbors <bors@rust-lang.org>2020-10-05 02:49:51 +0000
commitefbaa413061c2a6e52f06f00a60ee7830fcf3ea5 (patch)
treed728ec6e5c6bbcaaf0accc89b53a176515718745 /compiler/rustc_passes/src
parentced813fec0fb9e883906f18b76d618baf9f5bc08 (diff)
parent9dbc9ed870a3956d938c823338ac8943377845e8 (diff)
downloadrust-efbaa413061c2a6e52f06f00a60ee7830fcf3ea5.tar.gz
rust-efbaa413061c2a6e52f06f00a60ee7830fcf3ea5.zip
Auto merge of #77557 - Dylan-DPC:rollup-aib9ptp, r=Dylan-DPC
Rollup of 11 pull requests

Successful merges:

 - #75853 (Use more intra-doc-links in `core::fmt`)
 - #75928 (Remove trait_selection error message in specific case)
 - #76329 (Add check for doc alias attribute at crate level)
 - #77219 (core::global_allocator docs link to std::alloc::GlobalAlloc)
 - #77395 (BTreeMap: admit the existence of leaf edges in comments)
 - #77407 (Improve build-manifest to work with the improved promote-release)
 - #77426 (Include scope id in SocketAddrV6::Display)
 - #77439 (Fix missing diagnostic span for `impl Trait` with const generics, and add various tests for `min_const_generics` and `const_generics`)
 - #77471 (BTreeMap: refactoring around edges, missed spots)
 - #77512 (Allow `Abort` terminators in all const-contexts)
 - #77514 (Replace some once(x).chain(once(y)) with [x, y] IntoIter)

Failed merges:

r? `@ghost`
Diffstat (limited to 'compiler/rustc_passes/src')
-rw-r--r--compiler/rustc_passes/src/check_attr.rs56
-rw-r--r--compiler/rustc_passes/src/entry.rs44
2 files changed, 79 insertions, 21 deletions
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index b52216c45ce..59955b27334 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -13,12 +13,14 @@ use rustc_errors::{pluralize, struct_span_err};
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc_hir::{self, FnSig, ForeignItem, ForeignItemKind, HirId, Item, ItemKind, TraitItem};
+use rustc_hir::{
+    self, FnSig, ForeignItem, ForeignItemKind, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID,
+};
 use rustc_hir::{MethodKind, Target};
 use rustc_session::lint::builtin::{CONFLICTING_REPR_HINTS, UNUSED_ATTRIBUTES};
 use rustc_session::parse::feature_err;
-use rustc_span::symbol::sym;
-use rustc_span::Span;
+use rustc_span::symbol::{sym, Symbol};
+use rustc_span::{Span, DUMMY_SP};
 
 pub(crate) fn target_from_impl_item<'tcx>(
     tcx: TyCtxt<'tcx>,
@@ -333,6 +335,17 @@ impl CheckAttrVisitor<'tcx> {
                                 .emit();
                             return false;
                         }
+                        if CRATE_HIR_ID == hir_id {
+                            self.tcx
+                                .sess
+                                .struct_span_err(
+                                    meta.span(),
+                                    "`#![doc(alias = \"...\")]` isn't allowed as a crate \
+                                     level attribute",
+                                )
+                                .emit();
+                            return false;
+                        }
                     }
                 }
             }
@@ -808,9 +821,46 @@ fn is_c_like_enum(item: &Item<'_>) -> bool {
     }
 }
 
+fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
+    const ATTRS_TO_CHECK: &[Symbol] = &[
+        sym::macro_export,
+        sym::repr,
+        sym::path,
+        sym::automatically_derived,
+        sym::start,
+        sym::main,
+    ];
+
+    for attr in attrs {
+        for attr_to_check in ATTRS_TO_CHECK {
+            if tcx.sess.check_name(attr, *attr_to_check) {
+                tcx.sess
+                    .struct_span_err(
+                        attr.span,
+                        &format!(
+                            "`{}` attribute cannot be used at crate level",
+                            attr_to_check.to_ident_string()
+                        ),
+                    )
+                    .emit();
+            }
+        }
+    }
+}
+
 fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
     tcx.hir()
         .visit_item_likes_in_module(module_def_id, &mut CheckAttrVisitor { tcx }.as_deep_visitor());
+    if module_def_id.is_top_level_module() {
+        CheckAttrVisitor { tcx }.check_attributes(
+            CRATE_HIR_ID,
+            tcx.hir().krate_attrs(),
+            &DUMMY_SP,
+            Target::Mod,
+            None,
+        );
+        check_invalid_crate_level_attr(tcx, tcx.hir().krate_attrs());
+    }
 }
 
 pub(crate) fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index 8aa6e7936be..e87adb378e7 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -78,29 +78,38 @@ fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(LocalDefId, EntryFnType)
 // Beware, this is duplicated in `librustc_builtin_macros/test_harness.rs`
 // (with `ast::Item`), so make sure to keep them in sync.
 fn entry_point_type(sess: &Session, item: &Item<'_>, at_root: bool) -> EntryPointType {
-    match item.kind {
-        ItemKind::Fn(..) => {
-            if sess.contains_name(&item.attrs, sym::start) {
-                EntryPointType::Start
-            } else if sess.contains_name(&item.attrs, sym::main) {
-                EntryPointType::MainAttr
-            } else if item.ident.name == sym::main {
-                if at_root {
-                    // This is a top-level function so can be `main`.
-                    EntryPointType::MainNamed
-                } else {
-                    EntryPointType::OtherMain
-                }
-            } else {
-                EntryPointType::None
-            }
+    if sess.contains_name(&item.attrs, sym::start) {
+        EntryPointType::Start
+    } else if sess.contains_name(&item.attrs, sym::main) {
+        EntryPointType::MainAttr
+    } else if item.ident.name == sym::main {
+        if at_root {
+            // This is a top-level function so can be `main`.
+            EntryPointType::MainNamed
+        } else {
+            EntryPointType::OtherMain
         }
-        _ => EntryPointType::None,
+    } else {
+        EntryPointType::None
     }
 }
 
+fn throw_attr_err(sess: &Session, span: Span, attr: &str) {
+    sess.struct_span_err(span, &format!("`{}` attribute can only be used on functions", attr))
+        .emit();
+}
+
 fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
     match entry_point_type(&ctxt.session, item, at_root) {
+        EntryPointType::None => (),
+        _ if !matches!(item.kind, ItemKind::Fn(..)) => {
+            if let Some(attr) = ctxt.session.find_by_name(item.attrs, sym::start) {
+                throw_attr_err(&ctxt.session, attr.span, "start");
+            }
+            if let Some(attr) = ctxt.session.find_by_name(item.attrs, sym::main) {
+                throw_attr_err(&ctxt.session, attr.span, "main");
+            }
+        }
         EntryPointType::MainNamed => {
             if ctxt.main_fn.is_none() {
                 ctxt.main_fn = Some((item.hir_id, item.span));
@@ -137,7 +146,6 @@ fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
                     .emit();
             }
         }
-        EntryPointType::None => (),
     }
 }