Skip to content

Commit

Permalink
Rollup merge of rust-lang#89442 - GuillaumeGomez:duplicated-doc-alias…
Browse files Browse the repository at this point in the history
…, r=estebank

Add check for duplicated doc aliases

r? `@estebank`
  • Loading branch information
Manishearth authored Oct 5, 2021
2 parents ff6a77c + 013aa37 commit 0f3c2df
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 7 deletions.
42 changes: 36 additions & 6 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;

use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, NestedMetaItem};
use rustc_data_structures::stable_set::FxHashSet;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{pluralize, struct_span_err, Applicability};
use rustc_feature::{AttributeType, BUILTIN_ATTRIBUTE_MAP};
use rustc_hir as hir;
Expand Down Expand Up @@ -66,6 +66,7 @@ impl CheckAttrVisitor<'tcx> {
target: Target,
item: Option<ItemLike<'_>>,
) {
let mut doc_aliases = FxHashMap::default();
let mut is_valid = true;
let mut specified_inline = None;
let mut seen = FxHashSet::default();
Expand All @@ -79,7 +80,13 @@ impl CheckAttrVisitor<'tcx> {
sym::track_caller => {
self.check_track_caller(hir_id, &attr.span, attrs, span, target)
}
sym::doc => self.check_doc_attrs(attr, hir_id, target, &mut specified_inline),
sym::doc => self.check_doc_attrs(
attr,
hir_id,
target,
&mut specified_inline,
&mut doc_aliases,
),
sym::no_link => self.check_no_link(hir_id, &attr, span, target),
sym::export_name => self.check_export_name(hir_id, &attr, span, target),
sym::rustc_layout_scalar_valid_range_start
Expand Down Expand Up @@ -512,6 +519,7 @@ impl CheckAttrVisitor<'tcx> {
hir_id: HirId,
target: Target,
is_list: bool,
aliases: &mut FxHashMap<String, Span>,
) -> bool {
let tcx = self.tcx;
let err_fn = move |span: Span, msg: &str| {
Expand Down Expand Up @@ -582,17 +590,38 @@ impl CheckAttrVisitor<'tcx> {
if &*item_name.as_str() == doc_alias {
return err_fn(meta.span(), "is the same as the item's name");
}
let span = meta.span();
if let Err(entry) = aliases.try_insert(doc_alias.to_owned(), span) {
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, span, |lint| {
lint.build("doc alias is duplicated")
.span_label(*entry.entry.get(), "first defined here")
.emit();
});
}
true
}

fn check_doc_alias(&self, meta: &NestedMetaItem, hir_id: HirId, target: Target) -> bool {
fn check_doc_alias(
&self,
meta: &NestedMetaItem,
hir_id: HirId,
target: Target,
aliases: &mut FxHashMap<String, Span>,
) -> bool {
if let Some(values) = meta.meta_item_list() {
let mut errors = 0;
for v in values {
match v.literal() {
Some(l) => match l.kind {
LitKind::Str(s, _) => {
if !self.check_doc_alias_value(v, &s.as_str(), hir_id, target, true) {
if !self.check_doc_alias_value(
v,
&s.as_str(),
hir_id,
target,
true,
aliases,
) {
errors += 1;
}
}
Expand Down Expand Up @@ -621,7 +650,7 @@ impl CheckAttrVisitor<'tcx> {
}
errors == 0
} else if let Some(doc_alias) = meta.value_str().map(|s| s.to_string()) {
self.check_doc_alias_value(meta, &doc_alias, hir_id, target, false)
self.check_doc_alias_value(meta, &doc_alias, hir_id, target, false, aliases)
} else {
self.tcx
.sess
Expand Down Expand Up @@ -858,6 +887,7 @@ impl CheckAttrVisitor<'tcx> {
hir_id: HirId,
target: Target,
specified_inline: &mut Option<(bool, Span)>,
aliases: &mut FxHashMap<String, Span>,
) -> bool {
let mut is_valid = true;

Expand All @@ -867,7 +897,7 @@ impl CheckAttrVisitor<'tcx> {
match i_meta.name_or_empty() {
sym::alias
if !self.check_attr_not_crate_level(&meta, hir_id, "alias")
|| !self.check_doc_alias(&meta, hir_id, target) =>
|| !self.check_doc_alias(&meta, hir_id, target, aliases) =>
{
is_valid = false
}
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_passes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
#![feature(in_band_lifetimes)]
#![feature(format_args_capture)]
#![feature(iter_zip)]
#![feature(nll)]
#![feature(map_try_insert)]
#![feature(min_specialization)]
#![feature(nll)]
#![feature(try_blocks)]
#![recursion_limit = "256"]

Expand Down
9 changes: 9 additions & 0 deletions src/test/ui/duplicate_doc_alias.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#![deny(unused_attributes)]

#[doc(alias = "A")]
#[doc(alias = "A")] //~ ERROR
#[doc(alias = "B")]
#[doc(alias("B"))] //~ ERROR
pub struct Foo;

fn main() {}
24 changes: 24 additions & 0 deletions src/test/ui/duplicate_doc_alias.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
error: doc alias is duplicated
--> $DIR/duplicate_doc_alias.rs:4:7
|
LL | #[doc(alias = "A")]
| ----------- first defined here
LL | #[doc(alias = "A")]
| ^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/duplicate_doc_alias.rs:1:9
|
LL | #![deny(unused_attributes)]
| ^^^^^^^^^^^^^^^^^

error: doc alias is duplicated
--> $DIR/duplicate_doc_alias.rs:6:13
|
LL | #[doc(alias = "B")]
| ----------- first defined here
LL | #[doc(alias("B"))]
| ^^^

error: aborting due to 2 previous errors

0 comments on commit 0f3c2df

Please sign in to comment.