Skip to content

Commit eca1577

Browse files
authored
Unrolled build for #143519
Rollup merge of #143519 - mu001999-contrib:dead-code/impl-items, r=petrochenkov Check assoc consts and tys later like assoc fns This PR 1. checks assoc consts and tys later like assoc fns 2. marks assoc consts appear in poly-trait-ref live For assoc consts, considering ```rust #![deny(dead_code)] trait Tr { // ERROR trait `Tr` is never used const I: Self; } struct Foo; //~ ERROR struct `Foo` is never constructed impl Tr for Foo { const I: Self = Foo; } fn main() {} ``` Current this will produce unused `I` instead of unused `Tr` and `Foo` ([play](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=e0490d4a2d522cb70437b26e514a3d9c)), because `const I: Self = Foo;` will be added into the worklist at first: ``` error: associated constant `I` is never used --> src/main.rs:4:11 | 3 | trait Tr { // ERROR trait `Tr` is never used | -- associated constant in this trait 4 | const I: Self; | ^ | note: the lint level is defined here --> src/main.rs:1:9 | 1 | #![deny(dead_code)] | ^^^^^^^^^ error: could not compile `playground` (bin "playground") due to 1 previous error ``` This also happens to assoc tys, see the [new test](https://github.com/rust-lang/rust/compare/master...mu001999-contrib:rust:dead-code/impl-items?expand=1#diff-bf45fa403934a31c9d610a073ed2603d885e7e81572e8edf38b7f4e08a1f3531) Fixes #126729 r? `````@petrochenkov`````
2 parents 7e310f4 + 889582e commit eca1577

File tree

12 files changed

+169
-44
lines changed

12 files changed

+169
-44
lines changed

compiler/rustc_passes/src/dead.rs

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc_hir::{self as hir, ImplItem, ImplItemKind, Node, PatKind, QPath, TyKin
1818
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
1919
use rustc_middle::middle::privacy::Level;
2020
use rustc_middle::query::Providers;
21-
use rustc_middle::ty::{self, TyCtxt};
21+
use rustc_middle::ty::{self, AssocTag, TyCtxt};
2222
use rustc_middle::{bug, span_bug};
2323
use rustc_session::lint::builtin::DEAD_CODE;
2424
use rustc_session::lint::{self, LintExpectationId};
@@ -115,7 +115,10 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
115115

116116
fn handle_res(&mut self, res: Res) {
117117
match res {
118-
Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::TyAlias, def_id) => {
118+
Res::Def(
119+
DefKind::Const | DefKind::AssocConst | DefKind::AssocTy | DefKind::TyAlias,
120+
def_id,
121+
) => {
119122
self.check_def_id(def_id);
120123
}
121124
_ if self.in_pat => {}
@@ -482,7 +485,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
482485
) -> bool {
483486
let trait_def_id = match self.tcx.def_kind(local_def_id) {
484487
// assoc impl items of traits are live if the corresponding trait items are live
485-
DefKind::AssocFn => self
488+
DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn => self
486489
.tcx
487490
.associated_item(local_def_id)
488491
.trait_item_def_id
@@ -647,6 +650,31 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
647650

648651
self.in_pat = in_pat;
649652
}
653+
654+
fn visit_trait_ref(&mut self, t: &'tcx hir::TraitRef<'tcx>) {
655+
if let Some(trait_def_id) = t.path.res.opt_def_id()
656+
&& let Some(segment) = t.path.segments.last()
657+
&& let Some(args) = segment.args
658+
{
659+
for constraint in args.constraints {
660+
if let Some(local_def_id) = self
661+
.tcx
662+
.associated_items(trait_def_id)
663+
.find_by_ident_and_kind(
664+
self.tcx,
665+
constraint.ident,
666+
AssocTag::Const,
667+
trait_def_id,
668+
)
669+
.and_then(|item| item.def_id.as_local())
670+
{
671+
self.worklist.push((local_def_id, ComesFromAllowExpect::No));
672+
}
673+
}
674+
}
675+
676+
intravisit::walk_trait_ref(self, t);
677+
}
650678
}
651679

652680
fn has_allow_dead_code_or_lang_attr(
@@ -744,18 +772,12 @@ fn check_item<'tcx>(
744772
{
745773
worklist.push((local_def_id, comes_from_allow));
746774
} else if of_trait {
747-
// FIXME: This condition can be removed
748-
// if we support dead check for assoc consts and tys.
749-
if !matches!(tcx.def_kind(local_def_id), DefKind::AssocFn) {
750-
worklist.push((local_def_id, ComesFromAllowExpect::No));
751-
} else {
752-
// We only care about associated items of traits,
753-
// because they cannot be visited directly,
754-
// so we later mark them as live if their corresponding traits
755-
// or trait items and self types are both live,
756-
// but inherent associated items can be visited and marked directly.
757-
unsolved_items.push((id, local_def_id));
758-
}
775+
// We only care about associated items of traits,
776+
// because they cannot be visited directly,
777+
// so we later mark them as live if their corresponding traits
778+
// or trait items and self types are both live,
779+
// but inherent associated items can be visited and marked directly.
780+
unsolved_items.push((id, local_def_id));
759781
}
760782
}
761783
}
@@ -791,15 +813,14 @@ fn check_trait_item(
791813
worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>,
792814
id: hir::TraitItemId,
793815
) {
794-
use hir::TraitItemKind::{Const, Fn};
795-
if matches!(tcx.def_kind(id.owner_id), DefKind::AssocConst | DefKind::AssocFn) {
796-
let trait_item = tcx.hir_trait_item(id);
797-
if matches!(trait_item.kind, Const(_, Some(_)) | Fn(..))
798-
&& let Some(comes_from_allow) =
799-
has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id)
800-
{
801-
worklist.push((trait_item.owner_id.def_id, comes_from_allow));
802-
}
816+
use hir::TraitItemKind::{Const, Fn, Type};
817+
818+
let trait_item = tcx.hir_trait_item(id);
819+
if matches!(trait_item.kind, Const(_, Some(_)) | Type(_, Some(_)) | Fn(..))
820+
&& let Some(comes_from_allow) =
821+
has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id)
822+
{
823+
worklist.push((trait_item.owner_id.def_id, comes_from_allow));
803824
}
804825
}
805826

@@ -1163,6 +1184,7 @@ impl<'tcx> DeadVisitor<'tcx> {
11631184
}
11641185
match self.tcx.def_kind(def_id) {
11651186
DefKind::AssocConst
1187+
| DefKind::AssocTy
11661188
| DefKind::AssocFn
11671189
| DefKind::Fn
11681190
| DefKind::Static { .. }
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//@ check-pass
2+
3+
#![feature(associated_const_equality)]
4+
#![deny(dead_code)]
5+
6+
trait Tr {
7+
const I: i32;
8+
}
9+
10+
impl Tr for () {
11+
const I: i32 = 1;
12+
}
13+
14+
fn foo() -> impl Tr<I = 1> {}
15+
16+
trait Tr2 {
17+
const J: i32;
18+
const K: i32;
19+
}
20+
21+
impl Tr2 for () {
22+
const J: i32 = 1;
23+
const K: i32 = 1;
24+
}
25+
26+
fn foo2() -> impl Tr2<J = 1, K = 1> {}
27+
28+
mod t {
29+
pub trait Tr3 {
30+
const L: i32;
31+
}
32+
33+
impl Tr3 for () {
34+
const L: i32 = 1;
35+
}
36+
}
37+
38+
fn foo3() -> impl t::Tr3<L = 1> {}
39+
40+
fn main() {
41+
foo();
42+
foo2();
43+
foo3();
44+
}

tests/ui/const-generics/cross_crate_complex.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ async fn foo() {
1111
async_in_foo(async_out_foo::<4>().await).await;
1212
}
1313

14+
#[allow(dead_code)]
1415
struct Faz<const N: usize>;
1516

1617
impl<const N: usize> Foo<N> for Faz<N> {}

tests/ui/generic-associated-types/missing-bounds.fixed

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//@ run-rustfix
22

3+
#![allow(dead_code)]
4+
35
use std::ops::Add;
46

57
struct A<B>(B);

tests/ui/generic-associated-types/missing-bounds.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//@ run-rustfix
22

3+
#![allow(dead_code)]
4+
35
use std::ops::Add;
46

57
struct A<B>(B);

tests/ui/generic-associated-types/missing-bounds.stderr

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: equality constraints are not yet supported in `where` clauses
2-
--> $DIR/missing-bounds.rs:37:33
2+
--> $DIR/missing-bounds.rs:39:33
33
|
44
LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B {
55
| ^^^^^^^^^^^^^^^^^^^^^^ not supported
@@ -12,7 +12,7 @@ LL + impl<B: Add> Add for E<B> where B: Add<Output = B> {
1212
|
1313

1414
error[E0308]: mismatched types
15-
--> $DIR/missing-bounds.rs:11:11
15+
--> $DIR/missing-bounds.rs:13:11
1616
|
1717
LL | impl<B> Add for A<B> where B: Add {
1818
| - expected this type parameter
@@ -25,14 +25,14 @@ LL | A(self.0 + rhs.0)
2525
= note: expected type parameter `B`
2626
found associated type `<B as Add>::Output`
2727
help: the type constructed contains `<B as Add>::Output` due to the type of the argument passed
28-
--> $DIR/missing-bounds.rs:11:9
28+
--> $DIR/missing-bounds.rs:13:9
2929
|
3030
LL | A(self.0 + rhs.0)
3131
| ^^--------------^
3232
| |
3333
| this argument influences the type of `A`
3434
note: tuple struct defined here
35-
--> $DIR/missing-bounds.rs:5:8
35+
--> $DIR/missing-bounds.rs:7:8
3636
|
3737
LL | struct A<B>(B);
3838
| ^
@@ -42,7 +42,7 @@ LL | impl<B> Add for A<B> where B: Add<Output = B> {
4242
| ++++++++++++
4343

4444
error[E0308]: mismatched types
45-
--> $DIR/missing-bounds.rs:21:14
45+
--> $DIR/missing-bounds.rs:23:14
4646
|
4747
LL | impl<B: Add> Add for C<B> {
4848
| - expected this type parameter
@@ -55,7 +55,7 @@ LL | Self(self.0 + rhs.0)
5555
= note: expected type parameter `B`
5656
found associated type `<B as Add>::Output`
5757
note: tuple struct defined here
58-
--> $DIR/missing-bounds.rs:15:8
58+
--> $DIR/missing-bounds.rs:17:8
5959
|
6060
LL | struct C<B>(B);
6161
| ^
@@ -65,7 +65,7 @@ LL | impl<B: Add<Output = B>> Add for C<B> {
6565
| ++++++++++++
6666

6767
error[E0369]: cannot add `B` to `B`
68-
--> $DIR/missing-bounds.rs:31:21
68+
--> $DIR/missing-bounds.rs:33:21
6969
|
7070
LL | Self(self.0 + rhs.0)
7171
| ------ ^ ----- B
@@ -78,7 +78,7 @@ LL | impl<B: std::ops::Add<Output = B>> Add for D<B> {
7878
| +++++++++++++++++++++++++++
7979

8080
error[E0308]: mismatched types
81-
--> $DIR/missing-bounds.rs:42:14
81+
--> $DIR/missing-bounds.rs:44:14
8282
|
8383
LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B {
8484
| - expected this type parameter
@@ -91,7 +91,7 @@ LL | Self(self.0 + rhs.0)
9191
= note: expected type parameter `B`
9292
found associated type `<B as Add>::Output`
9393
note: tuple struct defined here
94-
--> $DIR/missing-bounds.rs:35:8
94+
--> $DIR/missing-bounds.rs:37:8
9595
|
9696
LL | struct E<B>(B);
9797
| ^
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![deny(dead_code)]
2+
3+
trait Tr { //~ ERROR trait `Tr` is never used
4+
const I: Self;
5+
}
6+
7+
struct Foo; //~ ERROR struct `Foo` is never constructed
8+
9+
impl Tr for Foo {
10+
const I: Self = Foo;
11+
}
12+
13+
fn main() {}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: trait `Tr` is never used
2+
--> $DIR/unused-trait-with-assoc-const.rs:3:7
3+
|
4+
LL | trait Tr {
5+
| ^^
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/unused-trait-with-assoc-const.rs:1:9
9+
|
10+
LL | #![deny(dead_code)]
11+
| ^^^^^^^^^
12+
13+
error: struct `Foo` is never constructed
14+
--> $DIR/unused-trait-with-assoc-const.rs:7:8
15+
|
16+
LL | struct Foo;
17+
| ^^^
18+
19+
error: aborting due to 2 previous errors
20+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#![deny(dead_code)]
2+
3+
struct T1; //~ ERROR struct `T1` is never constructed
4+
5+
trait Foo { type Unused; } //~ ERROR trait `Foo` is never used
6+
impl Foo for T1 { type Unused = Self; }
7+
8+
pub trait Bar { type Used; }
9+
impl Bar for T1 { type Used = Self; }
10+
11+
fn main() {}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: struct `T1` is never constructed
2+
--> $DIR/unused-trait-with-assoc-ty.rs:3:8
3+
|
4+
LL | struct T1;
5+
| ^^
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/unused-trait-with-assoc-ty.rs:1:9
9+
|
10+
LL | #![deny(dead_code)]
11+
| ^^^^^^^^^
12+
13+
error: trait `Foo` is never used
14+
--> $DIR/unused-trait-with-assoc-ty.rs:5:7
15+
|
16+
LL | trait Foo { type Unused; }
17+
| ^^^
18+
19+
error: aborting due to 2 previous errors
20+

0 commit comments

Comments
 (0)