Skip to content

Commit e7f6ed1

Browse files
committed
Auto merge of rust-lang#74098 - GuillaumeGomez:doc-alias-checks, r=ollie27
Doc alias checks: ensure only items appearing in search index can use it Following the discussion in rust-lang#73721, I added checks to ensure that only items appearing in the search are allowed to have doc alias. r? @ollie27
2 parents 11a44ad + fc6fb3f commit e7f6ed1

10 files changed

+174
-9
lines changed

src/librustc_passes/check_attr.rs

+24-2
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ impl CheckAttrVisitor<'tcx> {
7070
} else if self.tcx.sess.check_name(attr, sym::track_caller) {
7171
self.check_track_caller(&attr.span, attrs, span, target)
7272
} else if self.tcx.sess.check_name(attr, sym::doc) {
73-
self.check_doc_alias(attr)
73+
self.check_doc_alias(attr, hir_id, target)
7474
} else {
7575
true
7676
};
@@ -217,7 +217,7 @@ impl CheckAttrVisitor<'tcx> {
217217
}
218218
}
219219

220-
fn check_doc_alias(&self, attr: &Attribute) -> bool {
220+
fn check_doc_alias(&self, attr: &Attribute, hir_id: HirId, target: Target) -> bool {
221221
if let Some(mi) = attr.meta() {
222222
if let Some(list) = mi.meta_item_list() {
223223
for meta in list {
@@ -238,6 +238,28 @@ impl CheckAttrVisitor<'tcx> {
238238
.emit();
239239
return false;
240240
}
241+
if let Some(err) = match target {
242+
Target::Impl => Some("implementation block"),
243+
Target::ForeignMod => Some("extern block"),
244+
Target::AssocTy => {
245+
let parent_hir_id = self.tcx.hir().get_parent_item(hir_id);
246+
let containing_item = self.tcx.hir().expect_item(parent_hir_id);
247+
if Target::from_item(containing_item) == Target::Impl {
248+
Some("type alias in implementation block")
249+
} else {
250+
None
251+
}
252+
}
253+
_ => None,
254+
} {
255+
self.tcx
256+
.sess
257+
.struct_span_err(
258+
meta.span(),
259+
&format!("`#[doc(alias = \"...\")]` isn't allowed on {}", err,),
260+
)
261+
.emit();
262+
}
241263
}
242264
}
243265
}

src/librustdoc/core.rs

+4
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,10 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
470470
sess.time("missing_docs", || {
471471
rustc_lint::check_crate(tcx, rustc_lint::builtin::MissingDoc::new);
472472
});
473+
for &module in tcx.hir().krate().modules.keys() {
474+
let local_def_id = tcx.hir().local_def_id(module);
475+
tcx.ensure().check_mod_attrs(local_def_id);
476+
}
473477

474478
let access_levels = tcx.privacy_access_levels(LOCAL_CRATE);
475479
// Convert from a HirId set to a DefId set since we don't always have easy access

src/test/rustdoc-js/doc-alias.js

+15-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const QUERY = [
55
'StructFieldItem',
66
'StructMethodItem',
77
'ImplTraitItem',
8-
'ImplAssociatedConstItem',
8+
'StructImplConstItem',
99
'ImplTraitFunction',
1010
'EnumItem',
1111
'VariantItem',
@@ -64,8 +64,16 @@ const EXPECTED = [
6464
'others': [],
6565
},
6666
{
67-
// ImplAssociatedConstItem
68-
'others': [],
67+
// StructImplConstItem
68+
'others': [
69+
{
70+
'path': 'doc_alias::Struct',
71+
'name': 'ImplConstItem',
72+
'alias': 'StructImplConstItem',
73+
'href': '../doc_alias/struct.Struct.html#associatedconstant.ImplConstItem',
74+
'is_alias': true
75+
},
76+
],
6977
},
7078
{
7179
'others': [
@@ -197,6 +205,10 @@ const EXPECTED = [
197205
'href': '../doc_alias/constant.Const.html',
198206
'is_alias': true
199207
},
208+
{
209+
'path': 'doc_alias::Struct',
210+
'name': 'ImplConstItem',
211+
},
200212
],
201213
},
202214
{

src/test/rustdoc-js/doc-alias.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,14 @@ pub struct Struct {
77
}
88

99
impl Struct {
10+
#[doc(alias = "StructImplConstItem")]
11+
pub const ImplConstItem: i32 = 0;
1012
#[doc(alias = "StructMethodItem")]
1113
pub fn method(&self) {}
1214
}
1315

1416
impl Trait for Struct {
15-
// Shouldn't be listed in aliases!
16-
#[doc(alias = "ImplTraitItem")]
1717
type Target = u32;
18-
// Shouldn't be listed in aliases!
19-
#[doc(alias = "ImplAssociatedConstItem")]
2018
const AssociatedConst: i32 = 12;
2119

2220
#[doc(alias = "ImplTraitFunction")]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#![feature(doc_alias)]
2+
3+
pub struct Bar;
4+
pub trait Foo {
5+
type X;
6+
fn foo() -> Self::X;
7+
}
8+
9+
#[doc(alias = "foo")] //~ ERROR
10+
extern {}
11+
12+
#[doc(alias = "bar")] //~ ERROR
13+
impl Bar {
14+
#[doc(alias = "const")]
15+
pub const A: u32 = 0;
16+
}
17+
18+
#[doc(alias = "foobar")] //~ ERROR
19+
impl Foo for Bar {
20+
#[doc(alias = "assoc")] //~ ERROR
21+
type X = i32;
22+
fn foo() -> Self::X { 0 }
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error: `#[doc(alias = "...")]` isn't allowed on extern block
2+
--> $DIR/check-doc-alias-attr-location.rs:9:7
3+
|
4+
LL | #[doc(alias = "foo")]
5+
| ^^^^^^^^^^^^^
6+
7+
error: `#[doc(alias = "...")]` isn't allowed on implementation block
8+
--> $DIR/check-doc-alias-attr-location.rs:12:7
9+
|
10+
LL | #[doc(alias = "bar")]
11+
| ^^^^^^^^^^^^^
12+
13+
error: `#[doc(alias = "...")]` isn't allowed on implementation block
14+
--> $DIR/check-doc-alias-attr-location.rs:18:7
15+
|
16+
LL | #[doc(alias = "foobar")]
17+
| ^^^^^^^^^^^^^^^^
18+
19+
error: `#[doc(alias = "...")]` isn't allowed on type alias in implementation block
20+
--> $DIR/check-doc-alias-attr-location.rs:20:11
21+
|
22+
LL | #[doc(alias = "assoc")]
23+
| ^^^^^^^^^^^^^^^
24+
25+
error: aborting due to 4 previous errors
26+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#![crate_type = "lib"]
2+
#![feature(doc_alias)]
3+
4+
#[doc(alias = "foo")] // ok!
5+
pub struct Bar;
6+
7+
#[doc(alias)] //~ ERROR
8+
#[doc(alias = 0)] //~ ERROR
9+
#[doc(alias("bar"))] //~ ERROR
10+
pub struct Foo;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: doc alias attribute expects a string: #[doc(alias = "0")]
2+
--> $DIR/check-doc-alias-attr.rs:7:7
3+
|
4+
LL | #[doc(alias)]
5+
| ^^^^^
6+
7+
error: doc alias attribute expects a string: #[doc(alias = "0")]
8+
--> $DIR/check-doc-alias-attr.rs:8:7
9+
|
10+
LL | #[doc(alias = 0)]
11+
| ^^^^^^^^^
12+
13+
error: doc alias attribute expects a string: #[doc(alias = "0")]
14+
--> $DIR/check-doc-alias-attr.rs:9:7
15+
|
16+
LL | #[doc(alias("bar"))]
17+
| ^^^^^^^^^^^^
18+
19+
error: aborting due to 3 previous errors
20+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#![crate_type="lib"]
2+
#![feature(doc_alias)]
3+
4+
pub struct Bar;
5+
pub trait Foo {
6+
type X;
7+
fn foo() -> Self::X;
8+
}
9+
10+
#[doc(alias = "foo")] //~ ERROR
11+
extern {}
12+
13+
#[doc(alias = "bar")] //~ ERROR
14+
impl Bar {
15+
#[doc(alias = "const")]
16+
const A: u32 = 0;
17+
}
18+
19+
#[doc(alias = "foobar")] //~ ERROR
20+
impl Foo for Bar {
21+
#[doc(alias = "assoc")] //~ ERROR
22+
type X = i32;
23+
fn foo() -> Self::X { 0 }
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error: `#[doc(alias = "...")]` isn't allowed on extern block
2+
--> $DIR/check-doc-alias-attr-location.rs:10:7
3+
|
4+
LL | #[doc(alias = "foo")]
5+
| ^^^^^^^^^^^^^
6+
7+
error: `#[doc(alias = "...")]` isn't allowed on implementation block
8+
--> $DIR/check-doc-alias-attr-location.rs:13:7
9+
|
10+
LL | #[doc(alias = "bar")]
11+
| ^^^^^^^^^^^^^
12+
13+
error: `#[doc(alias = "...")]` isn't allowed on implementation block
14+
--> $DIR/check-doc-alias-attr-location.rs:19:7
15+
|
16+
LL | #[doc(alias = "foobar")]
17+
| ^^^^^^^^^^^^^^^^
18+
19+
error: `#[doc(alias = "...")]` isn't allowed on type alias in implementation block
20+
--> $DIR/check-doc-alias-attr-location.rs:21:11
21+
|
22+
LL | #[doc(alias = "assoc")]
23+
| ^^^^^^^^^^^^^^^
24+
25+
error: aborting due to 4 previous errors
26+

0 commit comments

Comments
 (0)