Skip to content

Commit

Permalink
Rollup merge of #76329 - GuillaumeGomez:doc-alias-crate-level, r=matt…
Browse files Browse the repository at this point in the history
…hewjasper

Add check for doc alias attribute at crate level

Fixes #76298, #64734, #69365.

r? @ollie27
  • Loading branch information
Dylan-DPC authored Oct 5, 2020
2 parents 5fa978f + 3641a37 commit e6e7ccc
Show file tree
Hide file tree
Showing 14 changed files with 547 additions and 404 deletions.
4 changes: 2 additions & 2 deletions compiler/rustc_hir/src/target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ use crate::{Item, ItemKind, TraitItem, TraitItemKind};

use std::fmt::{self, Display};

#[derive(Copy, Clone, PartialEq)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum MethodKind {
Trait { body: bool },
Inherent,
}

#[derive(Copy, Clone, PartialEq)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum Target {
ExternCrate,
Use,
Expand Down
56 changes: 53 additions & 3 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
Expand Down Expand Up @@ -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;
}
}
}
}
Expand Down Expand Up @@ -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) {
Expand Down
44 changes: 26 additions & 18 deletions compiler/rustc_passes/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -137,7 +146,6 @@ fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
.emit();
}
}
EntryPointType::None => (),
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_session/src/lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ declare_lint! {
/// ### Example
///
/// ```rust
/// #![macro_export]
/// #![ignore]
/// ```
///
/// {{produces}}
Expand Down
6 changes: 6 additions & 0 deletions src/test/rustdoc-ui/doc-alias-crate-level.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#![feature(doc_alias)]

#![doc(alias = "crate-level-not-working")] //~ ERROR

#[doc(alias = "shouldn't work!")] //~ ERROR
pub fn foo() {}
14 changes: 14 additions & 0 deletions src/test/rustdoc-ui/doc-alias-crate-level.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: '\'' character isn't allowed in `#[doc(alias = "...")]`
--> $DIR/doc-alias-crate-level.rs:5:7
|
LL | #[doc(alias = "shouldn't work!")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error: `#![doc(alias = "...")]` isn't allowed as a crate level attribute
--> $DIR/doc-alias-crate-level.rs:3:8
|
LL | #![doc(alias = "crate-level-not-working")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors

7 changes: 7 additions & 0 deletions src/test/ui/doc-alias-crate-level.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// compile-flags: -Zdeduplicate-diagnostics=no

#![feature(doc_alias)]

#![crate_type = "lib"]

#![doc(alias = "shouldn't work!")] //~ ERROR
8 changes: 8 additions & 0 deletions src/test/ui/doc-alias-crate-level.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error: '\'' character isn't allowed in `#[doc(alias = "...")]`
--> $DIR/doc-alias-crate-level.rs:7:8
|
LL | #![doc(alias = "shouldn't work!")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//~ NOTE: not an `extern crate` item
//~^ NOTE: not a function or static
//~^^ NOTE: not a function or closure
// This is testing whether various builtin attributes signals an
// error or warning when put in "weird" places.
//
Expand All @@ -7,9 +10,25 @@

// ignore-tidy-linelength

// Crate-level is accepted, though it is almost certainly unused?
#![macro_export]
//~^ ERROR: `macro_export` attribute cannot be used at crate level
#![main]
//~^ ERROR: `main` attribute cannot be used at crate level
#![start]
//~^ ERROR: `start` attribute cannot be used at crate level
#![repr()]
//~^ ERROR: `repr` attribute cannot be used at crate level
#![path = "3800"]
//~^ ERROR: `path` attribute cannot be used at crate level
#![automatically_derived]
//~^ ERROR: `automatically_derived` attribute cannot be used at crate level
#![no_mangle]
#![no_link]
//~^ ERROR: attribute should be applied to an `extern crate` item
#![export_name = "2200"]
//~^ ERROR: attribute should be applied to a function or static
#![inline]

//~^ ERROR: attribute should be applied to function or closure
#[inline]
//~^ ERROR attribute should be applied to function or closure
mod inline {
Expand Down Expand Up @@ -88,4 +107,40 @@ 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 {
mod inner { #![start] }
//~^ ERROR: `start` attribute can only be used on functions

// for `fn f()` case, see feature-gate-start.rs

#[start] struct S;
//~^ ERROR: `start` attribute can only be used on functions

#[start] type T = S;
//~^ ERROR: `start` attribute can only be used on functions

#[start] impl S { }
//~^ ERROR: `start` attribute can only be used on functions
}

fn main() {}
Loading

0 comments on commit e6e7ccc

Please sign in to comment.