Skip to content

Commit 0f3c2df

Browse files
authored
Rollup merge of rust-lang#89442 - GuillaumeGomez:duplicated-doc-alias, r=estebank
Add check for duplicated doc aliases r? `@estebank`
2 parents ff6a77c + 013aa37 commit 0f3c2df

File tree

4 files changed

+71
-7
lines changed

4 files changed

+71
-7
lines changed

compiler/rustc_passes/src/check_attr.rs

+36-6
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_middle::ty::query::Providers;
99
use rustc_middle::ty::TyCtxt;
1010

1111
use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, NestedMetaItem};
12-
use rustc_data_structures::stable_set::FxHashSet;
12+
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1313
use rustc_errors::{pluralize, struct_span_err, Applicability};
1414
use rustc_feature::{AttributeType, BUILTIN_ATTRIBUTE_MAP};
1515
use rustc_hir as hir;
@@ -66,6 +66,7 @@ impl CheckAttrVisitor<'tcx> {
6666
target: Target,
6767
item: Option<ItemLike<'_>>,
6868
) {
69+
let mut doc_aliases = FxHashMap::default();
6970
let mut is_valid = true;
7071
let mut specified_inline = None;
7172
let mut seen = FxHashSet::default();
@@ -79,7 +80,13 @@ impl CheckAttrVisitor<'tcx> {
7980
sym::track_caller => {
8081
self.check_track_caller(hir_id, &attr.span, attrs, span, target)
8182
}
82-
sym::doc => self.check_doc_attrs(attr, hir_id, target, &mut specified_inline),
83+
sym::doc => self.check_doc_attrs(
84+
attr,
85+
hir_id,
86+
target,
87+
&mut specified_inline,
88+
&mut doc_aliases,
89+
),
8390
sym::no_link => self.check_no_link(hir_id, &attr, span, target),
8491
sym::export_name => self.check_export_name(hir_id, &attr, span, target),
8592
sym::rustc_layout_scalar_valid_range_start
@@ -512,6 +519,7 @@ impl CheckAttrVisitor<'tcx> {
512519
hir_id: HirId,
513520
target: Target,
514521
is_list: bool,
522+
aliases: &mut FxHashMap<String, Span>,
515523
) -> bool {
516524
let tcx = self.tcx;
517525
let err_fn = move |span: Span, msg: &str| {
@@ -582,17 +590,38 @@ impl CheckAttrVisitor<'tcx> {
582590
if &*item_name.as_str() == doc_alias {
583591
return err_fn(meta.span(), "is the same as the item's name");
584592
}
593+
let span = meta.span();
594+
if let Err(entry) = aliases.try_insert(doc_alias.to_owned(), span) {
595+
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, span, |lint| {
596+
lint.build("doc alias is duplicated")
597+
.span_label(*entry.entry.get(), "first defined here")
598+
.emit();
599+
});
600+
}
585601
true
586602
}
587603

588-
fn check_doc_alias(&self, meta: &NestedMetaItem, hir_id: HirId, target: Target) -> bool {
604+
fn check_doc_alias(
605+
&self,
606+
meta: &NestedMetaItem,
607+
hir_id: HirId,
608+
target: Target,
609+
aliases: &mut FxHashMap<String, Span>,
610+
) -> bool {
589611
if let Some(values) = meta.meta_item_list() {
590612
let mut errors = 0;
591613
for v in values {
592614
match v.literal() {
593615
Some(l) => match l.kind {
594616
LitKind::Str(s, _) => {
595-
if !self.check_doc_alias_value(v, &s.as_str(), hir_id, target, true) {
617+
if !self.check_doc_alias_value(
618+
v,
619+
&s.as_str(),
620+
hir_id,
621+
target,
622+
true,
623+
aliases,
624+
) {
596625
errors += 1;
597626
}
598627
}
@@ -621,7 +650,7 @@ impl CheckAttrVisitor<'tcx> {
621650
}
622651
errors == 0
623652
} else if let Some(doc_alias) = meta.value_str().map(|s| s.to_string()) {
624-
self.check_doc_alias_value(meta, &doc_alias, hir_id, target, false)
653+
self.check_doc_alias_value(meta, &doc_alias, hir_id, target, false, aliases)
625654
} else {
626655
self.tcx
627656
.sess
@@ -858,6 +887,7 @@ impl CheckAttrVisitor<'tcx> {
858887
hir_id: HirId,
859888
target: Target,
860889
specified_inline: &mut Option<(bool, Span)>,
890+
aliases: &mut FxHashMap<String, Span>,
861891
) -> bool {
862892
let mut is_valid = true;
863893

@@ -867,7 +897,7 @@ impl CheckAttrVisitor<'tcx> {
867897
match i_meta.name_or_empty() {
868898
sym::alias
869899
if !self.check_attr_not_crate_level(&meta, hir_id, "alias")
870-
|| !self.check_doc_alias(&meta, hir_id, target) =>
900+
|| !self.check_doc_alias(&meta, hir_id, target, aliases) =>
871901
{
872902
is_valid = false
873903
}

compiler/rustc_passes/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
#![feature(in_band_lifetimes)]
1010
#![feature(format_args_capture)]
1111
#![feature(iter_zip)]
12-
#![feature(nll)]
12+
#![feature(map_try_insert)]
1313
#![feature(min_specialization)]
14+
#![feature(nll)]
1415
#![feature(try_blocks)]
1516
#![recursion_limit = "256"]
1617

src/test/ui/duplicate_doc_alias.rs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#![deny(unused_attributes)]
2+
3+
#[doc(alias = "A")]
4+
#[doc(alias = "A")] //~ ERROR
5+
#[doc(alias = "B")]
6+
#[doc(alias("B"))] //~ ERROR
7+
pub struct Foo;
8+
9+
fn main() {}
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
error: doc alias is duplicated
2+
--> $DIR/duplicate_doc_alias.rs:4:7
3+
|
4+
LL | #[doc(alias = "A")]
5+
| ----------- first defined here
6+
LL | #[doc(alias = "A")]
7+
| ^^^^^^^^^^^
8+
|
9+
note: the lint level is defined here
10+
--> $DIR/duplicate_doc_alias.rs:1:9
11+
|
12+
LL | #![deny(unused_attributes)]
13+
| ^^^^^^^^^^^^^^^^^
14+
15+
error: doc alias is duplicated
16+
--> $DIR/duplicate_doc_alias.rs:6:13
17+
|
18+
LL | #[doc(alias = "B")]
19+
| ----------- first defined here
20+
LL | #[doc(alias("B"))]
21+
| ^^^
22+
23+
error: aborting due to 2 previous errors
24+

0 commit comments

Comments
 (0)