Rollup merge of #126618 - mu001999-contrib:dead/enhance, r=pnkfelix
Mark assoc tys live only if the corresponding trait is live r? ````@pnkfelix````
This commit is contained in:
commit
2724aeaaeb
@ -155,7 +155,10 @@ fn insert_def_id(&mut self, def_id: DefId) {
|
|||||||
|
|
||||||
fn handle_res(&mut self, res: Res) {
|
fn handle_res(&mut self, res: Res) {
|
||||||
match res {
|
match res {
|
||||||
Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::TyAlias, def_id) => {
|
Res::Def(
|
||||||
|
DefKind::Const | DefKind::AssocConst | DefKind::AssocTy | DefKind::TyAlias,
|
||||||
|
def_id,
|
||||||
|
) => {
|
||||||
self.check_def_id(def_id);
|
self.check_def_id(def_id);
|
||||||
}
|
}
|
||||||
_ if self.in_pat => {}
|
_ if self.in_pat => {}
|
||||||
@ -441,7 +444,7 @@ fn visit_node(&mut self, node: Node<'tcx>) {
|
|||||||
intravisit::walk_item(self, item)
|
intravisit::walk_item(self, item)
|
||||||
}
|
}
|
||||||
hir::ItemKind::ForeignMod { .. } => {}
|
hir::ItemKind::ForeignMod { .. } => {}
|
||||||
hir::ItemKind::Trait(..) => {
|
hir::ItemKind::Trait(_, _, _, _, trait_item_refs) => {
|
||||||
for impl_def_id in self.tcx.all_impls(item.owner_id.to_def_id()) {
|
for impl_def_id in self.tcx.all_impls(item.owner_id.to_def_id()) {
|
||||||
if let Some(local_def_id) = impl_def_id.as_local()
|
if let Some(local_def_id) = impl_def_id.as_local()
|
||||||
&& let ItemKind::Impl(impl_ref) =
|
&& let ItemKind::Impl(impl_ref) =
|
||||||
@ -454,7 +457,12 @@ fn visit_node(&mut self, node: Node<'tcx>) {
|
|||||||
intravisit::walk_path(self, impl_ref.of_trait.unwrap().path);
|
intravisit::walk_path(self, impl_ref.of_trait.unwrap().path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// mark assoc ty live if the trait is live
|
||||||
|
for trait_item in trait_item_refs {
|
||||||
|
if let hir::AssocItemKind::Type = trait_item.kind {
|
||||||
|
self.check_def_id(trait_item.id.owner_id.to_def_id());
|
||||||
|
}
|
||||||
|
}
|
||||||
intravisit::walk_item(self, item)
|
intravisit::walk_item(self, item)
|
||||||
}
|
}
|
||||||
_ => intravisit::walk_item(self, item),
|
_ => intravisit::walk_item(self, item),
|
||||||
@ -471,8 +479,7 @@ fn visit_node(&mut self, node: Node<'tcx>) {
|
|||||||
&& let ItemKind::Impl(impl_ref) =
|
&& let ItemKind::Impl(impl_ref) =
|
||||||
self.tcx.hir().expect_item(local_impl_id).kind
|
self.tcx.hir().expect_item(local_impl_id).kind
|
||||||
{
|
{
|
||||||
if !matches!(trait_item.kind, hir::TraitItemKind::Type(..))
|
if !ty_ref_to_pub_struct(self.tcx, impl_ref.self_ty)
|
||||||
&& !ty_ref_to_pub_struct(self.tcx, impl_ref.self_ty)
|
|
||||||
.ty_and_all_fields_are_public
|
.ty_and_all_fields_are_public
|
||||||
{
|
{
|
||||||
// skip impl-items of non pure pub ty,
|
// skip impl-items of non pure pub ty,
|
||||||
@ -812,8 +819,7 @@ fn check_item<'tcx>(
|
|||||||
// for trait impl blocks,
|
// for trait impl blocks,
|
||||||
// mark the method live if the self_ty is public,
|
// mark the method live if the self_ty is public,
|
||||||
// or the method is public and may construct self
|
// or the method is public and may construct self
|
||||||
if of_trait && matches!(tcx.def_kind(local_def_id), DefKind::AssocTy)
|
if tcx.visibility(local_def_id).is_public()
|
||||||
|| tcx.visibility(local_def_id).is_public()
|
|
||||||
&& (ty_and_all_fields_are_public || may_construct_self)
|
&& (ty_and_all_fields_are_public || may_construct_self)
|
||||||
{
|
{
|
||||||
// if the impl item is public,
|
// if the impl item is public,
|
||||||
@ -851,10 +857,13 @@ fn check_trait_item(
|
|||||||
worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>,
|
worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>,
|
||||||
id: hir::TraitItemId,
|
id: hir::TraitItemId,
|
||||||
) {
|
) {
|
||||||
use hir::TraitItemKind::{Const, Fn};
|
use hir::TraitItemKind::{Const, Fn, Type};
|
||||||
if matches!(tcx.def_kind(id.owner_id), DefKind::AssocConst | DefKind::AssocFn) {
|
if matches!(
|
||||||
|
tcx.def_kind(id.owner_id),
|
||||||
|
DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn
|
||||||
|
) {
|
||||||
let trait_item = tcx.hir().trait_item(id);
|
let trait_item = tcx.hir().trait_item(id);
|
||||||
if matches!(trait_item.kind, Const(_, Some(_)) | Fn(..))
|
if matches!(trait_item.kind, Const(_, Some(_)) | Type(_, Some(_)) | Fn(..))
|
||||||
&& let Some(comes_from_allow) =
|
&& let Some(comes_from_allow) =
|
||||||
has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id)
|
has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id)
|
||||||
{
|
{
|
||||||
@ -896,7 +905,7 @@ fn create_and_seed_worklist(
|
|||||||
// checks impls, impl-items and pub structs with all public fields later
|
// checks impls, impl-items and pub structs with all public fields later
|
||||||
match tcx.def_kind(id) {
|
match tcx.def_kind(id) {
|
||||||
DefKind::Impl { .. } => false,
|
DefKind::Impl { .. } => false,
|
||||||
DefKind::AssocConst | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer),
|
DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer),
|
||||||
DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id()) || has_allow_dead_code_or_lang_attr(tcx, id).is_some(),
|
DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id()) || has_allow_dead_code_or_lang_attr(tcx, id).is_some(),
|
||||||
_ => true
|
_ => true
|
||||||
})
|
})
|
||||||
@ -1183,6 +1192,7 @@ fn check_definition(&mut self, def_id: LocalDefId) {
|
|||||||
}
|
}
|
||||||
match self.tcx.def_kind(def_id) {
|
match self.tcx.def_kind(def_id) {
|
||||||
DefKind::AssocConst
|
DefKind::AssocConst
|
||||||
|
| DefKind::AssocTy
|
||||||
| DefKind::AssocFn
|
| DefKind::AssocFn
|
||||||
| DefKind::Fn
|
| DefKind::Fn
|
||||||
| DefKind::Static { .. }
|
| DefKind::Static { .. }
|
||||||
@ -1224,15 +1234,14 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
|
|||||||
|| (def_kind == DefKind::Trait && live_symbols.contains(&item.owner_id.def_id))
|
|| (def_kind == DefKind::Trait && live_symbols.contains(&item.owner_id.def_id))
|
||||||
{
|
{
|
||||||
for &def_id in tcx.associated_item_def_ids(item.owner_id.def_id) {
|
for &def_id in tcx.associated_item_def_ids(item.owner_id.def_id) {
|
||||||
// We have diagnosed unused assoc consts and fns in traits
|
// We have diagnosed unused assocs in traits
|
||||||
if matches!(def_kind, DefKind::Impl { of_trait: true })
|
if matches!(def_kind, DefKind::Impl { of_trait: true })
|
||||||
&& matches!(tcx.def_kind(def_id), DefKind::AssocConst | DefKind::AssocFn)
|
&& matches!(tcx.def_kind(def_id), DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn)
|
||||||
// skip unused public inherent methods,
|
// skip unused public inherent methods,
|
||||||
// cause we have diagnosed unconstructed struct
|
// cause we have diagnosed unconstructed struct
|
||||||
|| matches!(def_kind, DefKind::Impl { of_trait: false })
|
|| matches!(def_kind, DefKind::Impl { of_trait: false })
|
||||||
&& tcx.visibility(def_id).is_public()
|
&& tcx.visibility(def_id).is_public()
|
||||||
&& ty_ref_to_pub_struct(tcx, tcx.hir().item(item).expect_impl().self_ty).ty_is_public
|
&& ty_ref_to_pub_struct(tcx, tcx.hir().item(item).expect_impl().self_ty).ty_is_public
|
||||||
|| def_kind == DefKind::Trait && tcx.def_kind(def_id) == DefKind::AssocTy
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ async fn foo() {
|
|||||||
async_in_foo(async_out_foo::<4>().await).await;
|
async_in_foo(async_out_foo::<4>().await).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
struct Faz<const N: usize>;
|
struct Faz<const N: usize>;
|
||||||
|
|
||||||
impl<const N: usize> Foo<N> for Faz<N> {}
|
impl<const N: usize> Foo<N> for Faz<N> {}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use std::ops::Add;
|
use std::ops::Add;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
struct A<B>(B);
|
struct A<B>(B);
|
||||||
|
|
||||||
impl<B> Add for A<B> where B: Add<Output = B> {
|
impl<B> Add for A<B> where B: Add<Output = B> {
|
||||||
@ -12,6 +13,7 @@ impl<B> Add for A<B> where B: Add<Output = B> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
struct C<B>(B);
|
struct C<B>(B);
|
||||||
|
|
||||||
impl<B: Add<Output = B>> Add for C<B> {
|
impl<B: Add<Output = B>> Add for C<B> {
|
||||||
@ -22,6 +24,7 @@ impl<B: Add<Output = B>> Add for C<B> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
struct D<B>(B);
|
struct D<B>(B);
|
||||||
|
|
||||||
impl<B: std::ops::Add<Output = B>> Add for D<B> {
|
impl<B: std::ops::Add<Output = B>> Add for D<B> {
|
||||||
@ -32,6 +35,7 @@ impl<B: std::ops::Add<Output = B>> Add for D<B> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
struct E<B>(B);
|
struct E<B>(B);
|
||||||
|
|
||||||
impl<B: Add<Output = B>> Add for E<B> where B: Add<Output = B> {
|
impl<B: Add<Output = B>> Add for E<B> where B: Add<Output = B> {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use std::ops::Add;
|
use std::ops::Add;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
struct A<B>(B);
|
struct A<B>(B);
|
||||||
|
|
||||||
impl<B> Add for A<B> where B: Add {
|
impl<B> Add for A<B> where B: Add {
|
||||||
@ -12,6 +13,7 @@ fn add(self, rhs: Self) -> Self {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
struct C<B>(B);
|
struct C<B>(B);
|
||||||
|
|
||||||
impl<B: Add> Add for C<B> {
|
impl<B: Add> Add for C<B> {
|
||||||
@ -22,6 +24,7 @@ fn add(self, rhs: Self) -> Self {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
struct D<B>(B);
|
struct D<B>(B);
|
||||||
|
|
||||||
impl<B> Add for D<B> {
|
impl<B> Add for D<B> {
|
||||||
@ -32,6 +35,7 @@ fn add(self, rhs: Self) -> Self {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
struct E<B>(B);
|
struct E<B>(B);
|
||||||
|
|
||||||
impl<B: Add> Add for E<B> where <B as Add>::Output = B {
|
impl<B: Add> Add for E<B> where <B as Add>::Output = B {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
error: equality constraints are not yet supported in `where` clauses
|
error: equality constraints are not yet supported in `where` clauses
|
||||||
--> $DIR/missing-bounds.rs:37:33
|
--> $DIR/missing-bounds.rs:41:33
|
||||||
|
|
|
|
||||||
LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B {
|
LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^ not supported
|
| ^^^^^^^^^^^^^^^^^^^^^^ not supported
|
||||||
@ -11,7 +11,7 @@ LL | impl<B: Add> Add for E<B> where B: Add<Output = B> {
|
|||||||
| ~~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/missing-bounds.rs:11:11
|
--> $DIR/missing-bounds.rs:12:11
|
||||||
|
|
|
|
||||||
LL | impl<B> Add for A<B> where B: Add {
|
LL | impl<B> Add for A<B> where B: Add {
|
||||||
| - expected this type parameter
|
| - expected this type parameter
|
||||||
@ -24,14 +24,14 @@ LL | A(self.0 + rhs.0)
|
|||||||
= note: expected type parameter `B`
|
= note: expected type parameter `B`
|
||||||
found associated type `<B as Add>::Output`
|
found associated type `<B as Add>::Output`
|
||||||
help: the type constructed contains `<B as Add>::Output` due to the type of the argument passed
|
help: the type constructed contains `<B as Add>::Output` due to the type of the argument passed
|
||||||
--> $DIR/missing-bounds.rs:11:9
|
--> $DIR/missing-bounds.rs:12:9
|
||||||
|
|
|
|
||||||
LL | A(self.0 + rhs.0)
|
LL | A(self.0 + rhs.0)
|
||||||
| ^^--------------^
|
| ^^--------------^
|
||||||
| |
|
| |
|
||||||
| this argument influences the type of `A`
|
| this argument influences the type of `A`
|
||||||
note: tuple struct defined here
|
note: tuple struct defined here
|
||||||
--> $DIR/missing-bounds.rs:5:8
|
--> $DIR/missing-bounds.rs:6:8
|
||||||
|
|
|
|
||||||
LL | struct A<B>(B);
|
LL | struct A<B>(B);
|
||||||
| ^
|
| ^
|
||||||
@ -41,7 +41,7 @@ LL | impl<B> Add for A<B> where B: Add<Output = B> {
|
|||||||
| ++++++++++++
|
| ++++++++++++
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/missing-bounds.rs:21:14
|
--> $DIR/missing-bounds.rs:23:14
|
||||||
|
|
|
|
||||||
LL | impl<B: Add> Add for C<B> {
|
LL | impl<B: Add> Add for C<B> {
|
||||||
| - expected this type parameter
|
| - expected this type parameter
|
||||||
@ -54,7 +54,7 @@ LL | Self(self.0 + rhs.0)
|
|||||||
= note: expected type parameter `B`
|
= note: expected type parameter `B`
|
||||||
found associated type `<B as Add>::Output`
|
found associated type `<B as Add>::Output`
|
||||||
note: tuple struct defined here
|
note: tuple struct defined here
|
||||||
--> $DIR/missing-bounds.rs:15:8
|
--> $DIR/missing-bounds.rs:17:8
|
||||||
|
|
|
|
||||||
LL | struct C<B>(B);
|
LL | struct C<B>(B);
|
||||||
| ^
|
| ^
|
||||||
@ -64,7 +64,7 @@ LL | impl<B: Add<Output = B>> Add for C<B> {
|
|||||||
| ++++++++++++
|
| ++++++++++++
|
||||||
|
|
||||||
error[E0369]: cannot add `B` to `B`
|
error[E0369]: cannot add `B` to `B`
|
||||||
--> $DIR/missing-bounds.rs:31:21
|
--> $DIR/missing-bounds.rs:34:21
|
||||||
|
|
|
|
||||||
LL | Self(self.0 + rhs.0)
|
LL | Self(self.0 + rhs.0)
|
||||||
| ------ ^ ----- B
|
| ------ ^ ----- B
|
||||||
@ -77,7 +77,7 @@ LL | impl<B: std::ops::Add<Output = B>> Add for D<B> {
|
|||||||
| +++++++++++++++++++++++++++
|
| +++++++++++++++++++++++++++
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/missing-bounds.rs:42:14
|
--> $DIR/missing-bounds.rs:46:14
|
||||||
|
|
|
|
||||||
LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B {
|
LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B {
|
||||||
| - expected this type parameter
|
| - expected this type parameter
|
||||||
@ -90,7 +90,7 @@ LL | Self(self.0 + rhs.0)
|
|||||||
= note: expected type parameter `B`
|
= note: expected type parameter `B`
|
||||||
found associated type `<B as Add>::Output`
|
found associated type `<B as Add>::Output`
|
||||||
note: tuple struct defined here
|
note: tuple struct defined here
|
||||||
--> $DIR/missing-bounds.rs:35:8
|
--> $DIR/missing-bounds.rs:39:8
|
||||||
|
|
|
|
||||||
LL | struct E<B>(B);
|
LL | struct E<B>(B);
|
||||||
| ^
|
| ^
|
||||||
|
11
tests/ui/lint/dead-code/unused-trait-with-assoc-ty.rs
Normal file
11
tests/ui/lint/dead-code/unused-trait-with-assoc-ty.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#![deny(dead_code)]
|
||||||
|
|
||||||
|
struct T1; //~ ERROR struct `T1` is never constructed
|
||||||
|
|
||||||
|
trait Foo { type Unused; } //~ ERROR trait `Foo` is never used
|
||||||
|
impl Foo for T1 { type Unused = Self; }
|
||||||
|
|
||||||
|
pub trait Bar { type Used; }
|
||||||
|
impl Bar for T1 { type Used = Self; }
|
||||||
|
|
||||||
|
fn main() {}
|
20
tests/ui/lint/dead-code/unused-trait-with-assoc-ty.stderr
Normal file
20
tests/ui/lint/dead-code/unused-trait-with-assoc-ty.stderr
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
error: struct `T1` is never constructed
|
||||||
|
--> $DIR/unused-trait-with-assoc-ty.rs:3:8
|
||||||
|
|
|
||||||
|
LL | struct T1;
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
note: the lint level is defined here
|
||||||
|
--> $DIR/unused-trait-with-assoc-ty.rs:1:9
|
||||||
|
|
|
||||||
|
LL | #![deny(dead_code)]
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
||||||
|
error: trait `Foo` is never used
|
||||||
|
--> $DIR/unused-trait-with-assoc-ty.rs:5:7
|
||||||
|
|
|
||||||
|
LL | trait Foo { type Unused; }
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
@ -15,7 +15,7 @@ fn foo(&self) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Tr { //~ WARN trait `Tr` is never used
|
trait Tr {
|
||||||
type U;
|
type U;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
warning: trait `Tr` is never used
|
|
||||||
--> $DIR/issue-22546.rs:18:7
|
|
||||||
|
|
|
||||||
LL | trait Tr {
|
|
||||||
| ^^
|
|
||||||
|
|
|
||||||
= note: `#[warn(dead_code)]` on by default
|
|
||||||
|
|
||||||
warning: 1 warning emitted
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user