Move #[doc(alias)] attribute checks in rustc
This commit is contained in:
parent
51db2a65dd
commit
3b6e4a84f9
@ -70,7 +70,7 @@ fn check_attributes(
|
||||
} else if self.tcx.sess.check_name(attr, sym::track_caller) {
|
||||
self.check_track_caller(&attr.span, attrs, span, target)
|
||||
} else if self.tcx.sess.check_name(attr, sym::doc) {
|
||||
self.check_doc_alias(attr)
|
||||
self.check_doc_alias(attr, hir_id, target)
|
||||
} else {
|
||||
true
|
||||
};
|
||||
@ -217,7 +217,7 @@ fn check_target_feature(&self, attr: &Attribute, span: &Span, target: Target) ->
|
||||
}
|
||||
}
|
||||
|
||||
fn check_doc_alias(&self, attr: &Attribute) -> bool {
|
||||
fn check_doc_alias(&self, attr: &Attribute, hir_id: HirId, target: Target) -> bool {
|
||||
if let Some(mi) = attr.meta() {
|
||||
if let Some(list) = mi.meta_item_list() {
|
||||
for meta in list {
|
||||
@ -238,6 +238,32 @@ fn check_doc_alias(&self, attr: &Attribute) -> bool {
|
||||
.emit();
|
||||
return false;
|
||||
}
|
||||
if let Some(err) = match target {
|
||||
Target::Impl => Some("implementation block"),
|
||||
Target::ForeignMod => Some("extern block"),
|
||||
Target::AssocConst | Target::AssocTy => {
|
||||
let parent_hir_id = self.tcx.hir().get_parent_item(hir_id);
|
||||
let containing_item = self.tcx.hir().expect_item(parent_hir_id);
|
||||
if Target::from_item(containing_item) == Target::Impl {
|
||||
Some(if target == Target::AssocConst {
|
||||
"const in implementation block"
|
||||
} else {
|
||||
"type alias in implementation block"
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
} {
|
||||
self.tcx
|
||||
.sess
|
||||
.struct_span_err(
|
||||
meta.span(),
|
||||
&format!("`#[doc(alias = \"...\")]` isn't allowed on {}", err,),
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,27 +31,6 @@ fn def_id_to_path(tcx: TyCtxt<'_>, did: DefId) -> Vec<String> {
|
||||
std::iter::once(crate_name).chain(relative).collect()
|
||||
}
|
||||
|
||||
fn check_doc_alias_attrs(
|
||||
attrs: &[ast::Attribute],
|
||||
item_kind: &str,
|
||||
diagnostic: &::rustc_errors::Handler,
|
||||
) {
|
||||
for attr in attrs {
|
||||
if let Some(attr) = attr.meta() {
|
||||
if let Some(list) = attr.meta_item_list() {
|
||||
for meta in list {
|
||||
if meta.check_name(sym::alias) {
|
||||
diagnostic.span_err(
|
||||
meta.span(),
|
||||
&format!("`#[doc(alias = \"...\")]` isn't allowed on {}", item_kind),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Also, is there some reason that this doesn't use the 'visit'
|
||||
// framework from syntax?.
|
||||
|
||||
@ -408,7 +387,6 @@ fn visit_item(
|
||||
|
||||
match item.kind {
|
||||
hir::ItemKind::ForeignMod(ref fm) => {
|
||||
check_doc_alias_attrs(&item.attrs, "extern block", self.cx.sess().diagnostic());
|
||||
for item in fm.items {
|
||||
self.visit_foreign_item(item, None, om);
|
||||
}
|
||||
@ -583,22 +561,11 @@ fn visit_item(
|
||||
self_ty,
|
||||
ref items,
|
||||
} => {
|
||||
check_doc_alias_attrs(
|
||||
&item.attrs,
|
||||
"implementation block",
|
||||
self.cx.sess().diagnostic(),
|
||||
);
|
||||
// Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
|
||||
// them up regardless of where they're located.
|
||||
if !self.inlining && of_trait.is_none() {
|
||||
let items = items
|
||||
.iter()
|
||||
.map(|item| {
|
||||
let item = self.cx.tcx.hir().impl_item(item.id);
|
||||
self.check_impl_doc_alias_attr(item);
|
||||
item
|
||||
})
|
||||
.collect();
|
||||
let items =
|
||||
items.iter().map(|item| self.cx.tcx.hir().impl_item(item.id)).collect();
|
||||
let i = Impl {
|
||||
unsafety,
|
||||
polarity,
|
||||
@ -614,31 +581,11 @@ fn visit_item(
|
||||
vis: &item.vis,
|
||||
};
|
||||
om.impls.push(i);
|
||||
} else if of_trait.is_some() {
|
||||
for item in items.iter() {
|
||||
self.check_impl_doc_alias_attr(self.cx.tcx.hir().impl_item(item.id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_impl_doc_alias_attr(&self, item: &hir::ImplItem<'_>) {
|
||||
match item.kind {
|
||||
hir::ImplItemKind::Const(_, _) => check_doc_alias_attrs(
|
||||
&item.attrs,
|
||||
"const in implementation block",
|
||||
self.cx.sess().diagnostic(),
|
||||
),
|
||||
hir::ImplItemKind::TyAlias(_) => check_doc_alias_attrs(
|
||||
&item.attrs,
|
||||
"type alias in implementation block",
|
||||
self.cx.sess().diagnostic(),
|
||||
),
|
||||
hir::ImplItemKind::Fn(_, _) => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_foreign_item(
|
||||
&mut self,
|
||||
item: &'tcx hir::ForeignItem<'_>,
|
||||
|
@ -10,18 +10,18 @@ error: `#[doc(alias = "...")]` isn't allowed on implementation block
|
||||
LL | #[doc(alias = "bar")]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: `#[doc(alias = "...")]` isn't allowed on const in implementation block
|
||||
--> $DIR/check-doc-alias-attr-location.rs:14:11
|
||||
|
|
||||
LL | #[doc(alias = "const")]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: `#[doc(alias = "...")]` isn't allowed on implementation block
|
||||
--> $DIR/check-doc-alias-attr-location.rs:18:7
|
||||
|
|
||||
LL | #[doc(alias = "foobar")]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `#[doc(alias = "...")]` isn't allowed on const in implementation block
|
||||
--> $DIR/check-doc-alias-attr-location.rs:14:11
|
||||
|
|
||||
LL | #[doc(alias = "const")]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: `#[doc(alias = "...")]` isn't allowed on type alias in implementation block
|
||||
--> $DIR/check-doc-alias-attr-location.rs:20:11
|
||||
|
|
||||
|
24
src/test/ui/check-doc-alias-attr-location.rs
Normal file
24
src/test/ui/check-doc-alias-attr-location.rs
Normal file
@ -0,0 +1,24 @@
|
||||
#![crate_type="lib"]
|
||||
#![feature(doc_alias)]
|
||||
|
||||
pub struct Bar;
|
||||
pub trait Foo {
|
||||
type X;
|
||||
fn foo() -> Self::X;
|
||||
}
|
||||
|
||||
#[doc(alias = "foo")] //~ ERROR
|
||||
extern {}
|
||||
|
||||
#[doc(alias = "bar")] //~ ERROR
|
||||
impl Bar {
|
||||
#[doc(alias = "const")] //~ ERROR
|
||||
const A: u32 = 0;
|
||||
}
|
||||
|
||||
#[doc(alias = "foobar")] //~ ERROR
|
||||
impl Foo for Bar {
|
||||
#[doc(alias = "assoc")] //~ ERROR
|
||||
type X = i32;
|
||||
fn foo() -> Self::X { 0 }
|
||||
}
|
32
src/test/ui/check-doc-alias-attr-location.stderr
Normal file
32
src/test/ui/check-doc-alias-attr-location.stderr
Normal file
@ -0,0 +1,32 @@
|
||||
error: `#[doc(alias = "...")]` isn't allowed on extern block
|
||||
--> $DIR/check-doc-alias-attr-location.rs:10:7
|
||||
|
|
||||
LL | #[doc(alias = "foo")]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: `#[doc(alias = "...")]` isn't allowed on implementation block
|
||||
--> $DIR/check-doc-alias-attr-location.rs:13:7
|
||||
|
|
||||
LL | #[doc(alias = "bar")]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: `#[doc(alias = "...")]` isn't allowed on implementation block
|
||||
--> $DIR/check-doc-alias-attr-location.rs:19:7
|
||||
|
|
||||
LL | #[doc(alias = "foobar")]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `#[doc(alias = "...")]` isn't allowed on const in implementation block
|
||||
--> $DIR/check-doc-alias-attr-location.rs:15:11
|
||||
|
|
||||
LL | #[doc(alias = "const")]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: `#[doc(alias = "...")]` isn't allowed on type alias in implementation block
|
||||
--> $DIR/check-doc-alias-attr-location.rs:21:11
|
||||
|
|
||||
LL | #[doc(alias = "assoc")]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
Loading…
Reference in New Issue
Block a user