Skip to content

Commit e6e7ccc

Browse files
authored
Rollup merge of #76329 - GuillaumeGomez:doc-alias-crate-level, r=matthewjasper
Add check for doc alias attribute at crate level Fixes #76298, #64734, #69365. r? @ollie27
2 parents 5fa978f + 3641a37 commit e6e7ccc

14 files changed

+547
-404
lines changed

compiler/rustc_hir/src/target.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ use crate::{Item, ItemKind, TraitItem, TraitItemKind};
99

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

12-
#[derive(Copy, Clone, PartialEq)]
12+
#[derive(Copy, Clone, PartialEq, Debug)]
1313
pub enum MethodKind {
1414
Trait { body: bool },
1515
Inherent,
1616
}
1717

18-
#[derive(Copy, Clone, PartialEq)]
18+
#[derive(Copy, Clone, PartialEq, Debug)]
1919
pub enum Target {
2020
ExternCrate,
2121
Use,

compiler/rustc_passes/src/check_attr.rs

+53-3
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@ use rustc_errors::{pluralize, struct_span_err};
1313
use rustc_hir as hir;
1414
use rustc_hir::def_id::LocalDefId;
1515
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
16-
use rustc_hir::{self, FnSig, ForeignItem, ForeignItemKind, HirId, Item, ItemKind, TraitItem};
16+
use rustc_hir::{
17+
self, FnSig, ForeignItem, ForeignItemKind, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID,
18+
};
1719
use rustc_hir::{MethodKind, Target};
1820
use rustc_session::lint::builtin::{CONFLICTING_REPR_HINTS, UNUSED_ATTRIBUTES};
1921
use rustc_session::parse::feature_err;
20-
use rustc_span::symbol::sym;
21-
use rustc_span::Span;
22+
use rustc_span::symbol::{sym, Symbol};
23+
use rustc_span::{Span, DUMMY_SP};
2224

2325
pub(crate) fn target_from_impl_item<'tcx>(
2426
tcx: TyCtxt<'tcx>,
@@ -333,6 +335,17 @@ impl CheckAttrVisitor<'tcx> {
333335
.emit();
334336
return false;
335337
}
338+
if CRATE_HIR_ID == hir_id {
339+
self.tcx
340+
.sess
341+
.struct_span_err(
342+
meta.span(),
343+
"`#![doc(alias = \"...\")]` isn't allowed as a crate \
344+
level attribute",
345+
)
346+
.emit();
347+
return false;
348+
}
336349
}
337350
}
338351
}
@@ -808,9 +821,46 @@ fn is_c_like_enum(item: &Item<'_>) -> bool {
808821
}
809822
}
810823

824+
fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
825+
const ATTRS_TO_CHECK: &[Symbol] = &[
826+
sym::macro_export,
827+
sym::repr,
828+
sym::path,
829+
sym::automatically_derived,
830+
sym::start,
831+
sym::main,
832+
];
833+
834+
for attr in attrs {
835+
for attr_to_check in ATTRS_TO_CHECK {
836+
if tcx.sess.check_name(attr, *attr_to_check) {
837+
tcx.sess
838+
.struct_span_err(
839+
attr.span,
840+
&format!(
841+
"`{}` attribute cannot be used at crate level",
842+
attr_to_check.to_ident_string()
843+
),
844+
)
845+
.emit();
846+
}
847+
}
848+
}
849+
}
850+
811851
fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
812852
tcx.hir()
813853
.visit_item_likes_in_module(module_def_id, &mut CheckAttrVisitor { tcx }.as_deep_visitor());
854+
if module_def_id.is_top_level_module() {
855+
CheckAttrVisitor { tcx }.check_attributes(
856+
CRATE_HIR_ID,
857+
tcx.hir().krate_attrs(),
858+
&DUMMY_SP,
859+
Target::Mod,
860+
None,
861+
);
862+
check_invalid_crate_level_attr(tcx, tcx.hir().krate_attrs());
863+
}
814864
}
815865

816866
pub(crate) fn provide(providers: &mut Providers) {

compiler/rustc_passes/src/entry.rs

+26-18
Original file line numberDiff line numberDiff line change
@@ -78,29 +78,38 @@ fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(LocalDefId, EntryFnType)
7878
// Beware, this is duplicated in `librustc_builtin_macros/test_harness.rs`
7979
// (with `ast::Item`), so make sure to keep them in sync.
8080
fn entry_point_type(sess: &Session, item: &Item<'_>, at_root: bool) -> EntryPointType {
81-
match item.kind {
82-
ItemKind::Fn(..) => {
83-
if sess.contains_name(&item.attrs, sym::start) {
84-
EntryPointType::Start
85-
} else if sess.contains_name(&item.attrs, sym::main) {
86-
EntryPointType::MainAttr
87-
} else if item.ident.name == sym::main {
88-
if at_root {
89-
// This is a top-level function so can be `main`.
90-
EntryPointType::MainNamed
91-
} else {
92-
EntryPointType::OtherMain
93-
}
94-
} else {
95-
EntryPointType::None
96-
}
81+
if sess.contains_name(&item.attrs, sym::start) {
82+
EntryPointType::Start
83+
} else if sess.contains_name(&item.attrs, sym::main) {
84+
EntryPointType::MainAttr
85+
} else if item.ident.name == sym::main {
86+
if at_root {
87+
// This is a top-level function so can be `main`.
88+
EntryPointType::MainNamed
89+
} else {
90+
EntryPointType::OtherMain
9791
}
98-
_ => EntryPointType::None,
92+
} else {
93+
EntryPointType::None
9994
}
10095
}
10196

97+
fn throw_attr_err(sess: &Session, span: Span, attr: &str) {
98+
sess.struct_span_err(span, &format!("`{}` attribute can only be used on functions", attr))
99+
.emit();
100+
}
101+
102102
fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
103103
match entry_point_type(&ctxt.session, item, at_root) {
104+
EntryPointType::None => (),
105+
_ if !matches!(item.kind, ItemKind::Fn(..)) => {
106+
if let Some(attr) = ctxt.session.find_by_name(item.attrs, sym::start) {
107+
throw_attr_err(&ctxt.session, attr.span, "start");
108+
}
109+
if let Some(attr) = ctxt.session.find_by_name(item.attrs, sym::main) {
110+
throw_attr_err(&ctxt.session, attr.span, "main");
111+
}
112+
}
104113
EntryPointType::MainNamed => {
105114
if ctxt.main_fn.is_none() {
106115
ctxt.main_fn = Some((item.hir_id, item.span));
@@ -137,7 +146,6 @@ fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
137146
.emit();
138147
}
139148
}
140-
EntryPointType::None => (),
141149
}
142150
}
143151

compiler/rustc_session/src/lint/builtin.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ declare_lint! {
518518
/// ### Example
519519
///
520520
/// ```rust
521-
/// #![macro_export]
521+
/// #![ignore]
522522
/// ```
523523
///
524524
/// {{produces}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#![feature(doc_alias)]
2+
3+
#![doc(alias = "crate-level-not-working")] //~ ERROR
4+
5+
#[doc(alias = "shouldn't work!")] //~ ERROR
6+
pub fn foo() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: '\'' character isn't allowed in `#[doc(alias = "...")]`
2+
--> $DIR/doc-alias-crate-level.rs:5:7
3+
|
4+
LL | #[doc(alias = "shouldn't work!")]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
6+
7+
error: `#![doc(alias = "...")]` isn't allowed as a crate level attribute
8+
--> $DIR/doc-alias-crate-level.rs:3:8
9+
|
10+
LL | #![doc(alias = "crate-level-not-working")]
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
error: aborting due to 2 previous errors
14+

src/test/ui/doc-alias-crate-level.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// compile-flags: -Zdeduplicate-diagnostics=no
2+
3+
#![feature(doc_alias)]
4+
5+
#![crate_type = "lib"]
6+
7+
#![doc(alias = "shouldn't work!")] //~ ERROR
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: '\'' character isn't allowed in `#[doc(alias = "...")]`
2+
--> $DIR/doc-alias-crate-level.rs:7:8
3+
|
4+
LL | #![doc(alias = "shouldn't work!")]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
6+
7+
error: aborting due to previous error
8+

src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs-error.rs

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

811
// ignore-tidy-linelength
912

10-
// Crate-level is accepted, though it is almost certainly unused?
13+
#![macro_export]
14+
//~^ ERROR: `macro_export` attribute cannot be used at crate level
15+
#![main]
16+
//~^ ERROR: `main` attribute cannot be used at crate level
17+
#![start]
18+
//~^ ERROR: `start` attribute cannot be used at crate level
19+
#![repr()]
20+
//~^ ERROR: `repr` attribute cannot be used at crate level
21+
#![path = "3800"]
22+
//~^ ERROR: `path` attribute cannot be used at crate level
23+
#![automatically_derived]
24+
//~^ ERROR: `automatically_derived` attribute cannot be used at crate level
25+
#![no_mangle]
26+
#![no_link]
27+
//~^ ERROR: attribute should be applied to an `extern crate` item
28+
#![export_name = "2200"]
29+
//~^ ERROR: attribute should be applied to a function or static
1130
#![inline]
12-
31+
//~^ ERROR: attribute should be applied to function or closure
1332
#[inline]
1433
//~^ ERROR attribute should be applied to function or closure
1534
mod inline {
@@ -88,4 +107,40 @@ mod export_name {
88107
//~| NOTE not a function or static
89108
}
90109

110+
#[main]
111+
//~^ ERROR: `main` attribute can only be used on functions
112+
mod main {
113+
mod inner { #![main] }
114+
//~^ ERROR: `main` attribute can only be used on functions
115+
116+
// for `fn f()` case, see feature-gate-main.rs
117+
118+
#[main] struct S;
119+
//~^ ERROR: `main` attribute can only be used on functions
120+
121+
#[main] type T = S;
122+
//~^ ERROR: `main` attribute can only be used on functions
123+
124+
#[main] impl S { }
125+
//~^ ERROR: `main` attribute can only be used on functions
126+
}
127+
128+
#[start]
129+
//~^ ERROR: `start` attribute can only be used on functions
130+
mod start {
131+
mod inner { #![start] }
132+
//~^ ERROR: `start` attribute can only be used on functions
133+
134+
// for `fn f()` case, see feature-gate-start.rs
135+
136+
#[start] struct S;
137+
//~^ ERROR: `start` attribute can only be used on functions
138+
139+
#[start] type T = S;
140+
//~^ ERROR: `start` attribute can only be used on functions
141+
142+
#[start] impl S { }
143+
//~^ ERROR: `start` attribute can only be used on functions
144+
}
145+
91146
fn main() {}

0 commit comments

Comments
 (0)