diff options
Diffstat (limited to 'compiler/rustc_passes/src')
| -rw-r--r-- | compiler/rustc_passes/src/check_attr.rs | 56 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/entry.rs | 44 |
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 => (), } } |
