Rollup merge of #109003 - GuillaumeGomez:useless-anonymous-reexport-lint, r=cjgillot
Add `useless_anonymous_reexport` lint This is a follow-up of https://github.com/rust-lang/rust/pull/108936. We once again show all anonymous re-exports in rustdoc, however we also wanted to add a lint to let users know that it very likely doesn't have the effect they think it has.
This commit is contained in:
commit
462e7e7a10
@ -508,3 +508,6 @@ lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its ass
|
|||||||
.specifically = this associated type bound is unsatisfied for `{$proj_ty}`
|
.specifically = this associated type bound is unsatisfied for `{$proj_ty}`
|
||||||
|
|
||||||
lint_opaque_hidden_inferred_bound_sugg = add this bound
|
lint_opaque_hidden_inferred_bound_sugg = add this bound
|
||||||
|
|
||||||
|
lint_useless_anonymous_reexport = useless anonymous re-export
|
||||||
|
.note = only anonymous re-exports of traits are useful, this is {$article} `{$desc}`
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
mod pass_by_value;
|
mod pass_by_value;
|
||||||
mod passes;
|
mod passes;
|
||||||
mod redundant_semicolon;
|
mod redundant_semicolon;
|
||||||
|
mod reexports;
|
||||||
mod traits;
|
mod traits;
|
||||||
mod types;
|
mod types;
|
||||||
mod unused;
|
mod unused;
|
||||||
@ -111,6 +112,7 @@
|
|||||||
use opaque_hidden_inferred_bound::*;
|
use opaque_hidden_inferred_bound::*;
|
||||||
use pass_by_value::*;
|
use pass_by_value::*;
|
||||||
use redundant_semicolon::*;
|
use redundant_semicolon::*;
|
||||||
|
use reexports::*;
|
||||||
use traits::*;
|
use traits::*;
|
||||||
use types::*;
|
use types::*;
|
||||||
use unused::*;
|
use unused::*;
|
||||||
@ -242,6 +244,7 @@ fn lint_mod(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
|||||||
OpaqueHiddenInferredBound: OpaqueHiddenInferredBound,
|
OpaqueHiddenInferredBound: OpaqueHiddenInferredBound,
|
||||||
MultipleSupertraitUpcastable: MultipleSupertraitUpcastable,
|
MultipleSupertraitUpcastable: MultipleSupertraitUpcastable,
|
||||||
MapUnitFn: MapUnitFn,
|
MapUnitFn: MapUnitFn,
|
||||||
|
UselessAnonymousReexport: UselessAnonymousReexport,
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
@ -1528,3 +1528,11 @@ pub struct UnusedImportBracesDiag {
|
|||||||
#[derive(LintDiagnostic)]
|
#[derive(LintDiagnostic)]
|
||||||
#[diag(lint_unused_allocation_mut)]
|
#[diag(lint_unused_allocation_mut)]
|
||||||
pub struct UnusedAllocationMutDiag;
|
pub struct UnusedAllocationMutDiag;
|
||||||
|
|
||||||
|
#[derive(LintDiagnostic)]
|
||||||
|
#[diag(lint_useless_anonymous_reexport)]
|
||||||
|
#[note]
|
||||||
|
pub struct UselessAnonymousReexportDiag {
|
||||||
|
pub article: &'static str,
|
||||||
|
pub desc: &'static str,
|
||||||
|
}
|
||||||
|
82
compiler/rustc_lint/src/reexports.rs
Normal file
82
compiler/rustc_lint/src/reexports.rs
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
use crate::lints::UselessAnonymousReexportDiag;
|
||||||
|
use crate::{LateContext, LateLintPass, LintContext};
|
||||||
|
use rustc_hir::def::DefKind;
|
||||||
|
use rustc_hir::def_id::DefId;
|
||||||
|
use rustc_hir::{Item, ItemKind, UseKind};
|
||||||
|
use rustc_middle::ty::Visibility;
|
||||||
|
use rustc_span::symbol::kw;
|
||||||
|
use rustc_span::Span;
|
||||||
|
|
||||||
|
declare_lint! {
|
||||||
|
/// The `useless_anonymous_reexport` lint checks if anonymous re-exports
|
||||||
|
/// are re-exports of traits.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
///
|
||||||
|
/// ```rust,compile_fail
|
||||||
|
/// #![deny(useless_anonymous_reexport)]
|
||||||
|
///
|
||||||
|
/// mod sub {
|
||||||
|
/// pub struct Bar;
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// pub use self::sub::Bar as _;
|
||||||
|
/// # fn main() {}
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// {{produces}}
|
||||||
|
///
|
||||||
|
/// ### Explanation
|
||||||
|
///
|
||||||
|
/// Anonymous re-exports are only useful if it's a re-export of a trait
|
||||||
|
/// in case you want to give access to it. If you re-export any other kind,
|
||||||
|
/// you won't be able to use it since its name won't be accessible.
|
||||||
|
pub USELESS_ANONYMOUS_REEXPORT,
|
||||||
|
Warn,
|
||||||
|
"useless anonymous re-export"
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_lint_pass!(UselessAnonymousReexport => [USELESS_ANONYMOUS_REEXPORT]);
|
||||||
|
|
||||||
|
fn emit_err(cx: &LateContext<'_>, span: Span, def_id: DefId) {
|
||||||
|
let article = cx.tcx.def_descr_article(def_id);
|
||||||
|
let desc = cx.tcx.def_descr(def_id);
|
||||||
|
cx.emit_spanned_lint(
|
||||||
|
USELESS_ANONYMOUS_REEXPORT,
|
||||||
|
span,
|
||||||
|
UselessAnonymousReexportDiag { article, desc },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> LateLintPass<'tcx> for UselessAnonymousReexport {
|
||||||
|
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||||
|
if let ItemKind::Use(path, kind) = item.kind &&
|
||||||
|
!matches!(kind, UseKind::Glob) &&
|
||||||
|
item.ident.name == kw::Underscore &&
|
||||||
|
// We only want re-exports. If it's just a `use X;`, then we ignore it.
|
||||||
|
match cx.tcx.local_visibility(item.owner_id.def_id) {
|
||||||
|
Visibility::Public => true,
|
||||||
|
Visibility::Restricted(level) => {
|
||||||
|
level != cx.tcx.parent_module_from_def_id(item.owner_id.def_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
for def_id in path.res.iter().filter_map(|r| r.opt_def_id()) {
|
||||||
|
match cx.tcx.def_kind(def_id) {
|
||||||
|
DefKind::Trait | DefKind::TraitAlias => {}
|
||||||
|
DefKind::TyAlias => {
|
||||||
|
let ty = cx.tcx.type_of(def_id);
|
||||||
|
if !ty.0.is_trait() {
|
||||||
|
emit_err(cx, item.span, def_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
emit_err(cx, item.span, def_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
// run-rustfix
|
// run-rustfix
|
||||||
#![allow(unused, nonstandard_style)]
|
#![allow(unused, nonstandard_style, useless_anonymous_reexport)]
|
||||||
mod m {
|
mod m {
|
||||||
|
|
||||||
mod p {
|
mod p {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// run-rustfix
|
// run-rustfix
|
||||||
#![allow(unused, nonstandard_style)]
|
#![allow(unused, nonstandard_style, useless_anonymous_reexport)]
|
||||||
mod m {
|
mod m {
|
||||||
|
|
||||||
mod p {
|
mod p {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// run-rustfix
|
// run-rustfix
|
||||||
#![allow(unused, nonstandard_style)]
|
#![allow(unused, nonstandard_style, useless_anonymous_reexport)]
|
||||||
mod m {
|
mod m {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! nu {
|
macro_rules! nu {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// run-rustfix
|
// run-rustfix
|
||||||
#![allow(unused, nonstandard_style)]
|
#![allow(unused, nonstandard_style, useless_anonymous_reexport)]
|
||||||
mod m {
|
mod m {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! nu {
|
macro_rules! nu {
|
||||||
|
21
tests/ui/lint/anonymous-reexport.rs
Normal file
21
tests/ui/lint/anonymous-reexport.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#![deny(useless_anonymous_reexport)]
|
||||||
|
#![crate_type = "rlib"]
|
||||||
|
|
||||||
|
mod my_mod {
|
||||||
|
pub trait Foo {}
|
||||||
|
pub type TyFoo = dyn Foo;
|
||||||
|
pub struct Bar;
|
||||||
|
pub type TyBar = Bar;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub use self::my_mod::Foo as _;
|
||||||
|
pub use self::my_mod::TyFoo as _;
|
||||||
|
pub use self::my_mod::Bar as _; //~ ERROR
|
||||||
|
pub use self::my_mod::TyBar as _; //~ ERROR
|
||||||
|
pub use self::my_mod::{Bar as _}; //~ ERROR
|
||||||
|
pub use self::my_mod::{Bar as _, Foo as _}; //~ ERROR
|
||||||
|
pub use self::my_mod::{Bar as _, TyBar as _};
|
||||||
|
//~^ ERROR
|
||||||
|
//~| ERROR
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use self::my_mod::TyBar as _;
|
55
tests/ui/lint/anonymous-reexport.stderr
Normal file
55
tests/ui/lint/anonymous-reexport.stderr
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
error: useless anonymous re-export
|
||||||
|
--> $DIR/anonymous-reexport.rs:13:1
|
||||||
|
|
|
||||||
|
LL | pub use self::my_mod::Bar as _;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: only anonymous re-exports of traits are useful, this is a `struct`
|
||||||
|
note: the lint level is defined here
|
||||||
|
--> $DIR/anonymous-reexport.rs:1:9
|
||||||
|
|
|
||||||
|
LL | #![deny(useless_anonymous_reexport)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: useless anonymous re-export
|
||||||
|
--> $DIR/anonymous-reexport.rs:14:1
|
||||||
|
|
|
||||||
|
LL | pub use self::my_mod::TyBar as _;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: only anonymous re-exports of traits are useful, this is a `type alias`
|
||||||
|
|
||||||
|
error: useless anonymous re-export
|
||||||
|
--> $DIR/anonymous-reexport.rs:15:24
|
||||||
|
|
|
||||||
|
LL | pub use self::my_mod::{Bar as _};
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: only anonymous re-exports of traits are useful, this is a `struct`
|
||||||
|
|
||||||
|
error: useless anonymous re-export
|
||||||
|
--> $DIR/anonymous-reexport.rs:16:24
|
||||||
|
|
|
||||||
|
LL | pub use self::my_mod::{Bar as _, Foo as _};
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: only anonymous re-exports of traits are useful, this is a `struct`
|
||||||
|
|
||||||
|
error: useless anonymous re-export
|
||||||
|
--> $DIR/anonymous-reexport.rs:17:24
|
||||||
|
|
|
||||||
|
LL | pub use self::my_mod::{Bar as _, TyBar as _};
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: only anonymous re-exports of traits are useful, this is a `struct`
|
||||||
|
|
||||||
|
error: useless anonymous re-export
|
||||||
|
--> $DIR/anonymous-reexport.rs:17:34
|
||||||
|
|
|
||||||
|
LL | pub use self::my_mod::{Bar as _, TyBar as _};
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: only anonymous re-exports of traits are useful, this is a `type alias`
|
||||||
|
|
||||||
|
error: aborting due to 6 previous errors
|
||||||
|
|
Loading…
Reference in New Issue
Block a user