-
Notifications
You must be signed in to change notification settings - Fork 13.5k
Check assoc consts and tys later like assoc fns #143519
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -115,7 +115,10 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { | |
|
||
fn handle_res(&mut self, res: 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); | ||
} | ||
_ if self.in_pat => {} | ||
|
@@ -482,7 +485,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { | |
) -> bool { | ||
let trait_def_id = match self.tcx.def_kind(local_def_id) { | ||
// assoc impl items of traits are live if the corresponding trait items are live | ||
DefKind::AssocFn => self | ||
DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn => self | ||
.tcx | ||
.associated_item(local_def_id) | ||
.trait_item_def_id | ||
|
@@ -647,6 +650,29 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { | |
|
||
self.in_pat = in_pat; | ||
} | ||
|
||
fn visit_poly_trait_ref(&mut self, t: &'tcx hir::PolyTraitRef<'tcx>) { | ||
// Mark the assoc const appears in poly-trait-ref live | ||
if let Some(pathsegment) = t.trait_ref.path.segments.last() | ||
&& let Some(args) = pathsegment.args | ||
{ | ||
for constraint in args.constraints { | ||
if let Some(item) = self | ||
.tcx | ||
.associated_items(pathsegment.res.def_id()) | ||
.filter_by_name_unhygienic(constraint.ident.name) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm sufficiently sure that this name resolution is already performed somewhere else, and the result is stored in some table. |
||
.find(|i| { | ||
matches!(i.kind, ty::AssocKind::Const { .. }) | ||
&& i.ident(self.tcx).normalize_to_macros_2_0() == constraint.ident | ||
}) | ||
&& let Some(local_def_id) = item.def_id.as_local() | ||
{ | ||
self.worklist.push((local_def_id, ComesFromAllowExpect::No)); | ||
} | ||
} | ||
} | ||
intravisit::walk_poly_trait_ref(self, t); | ||
} | ||
} | ||
|
||
fn has_allow_dead_code_or_lang_attr( | ||
|
@@ -744,18 +770,12 @@ fn check_item<'tcx>( | |
{ | ||
worklist.push((local_def_id, comes_from_allow)); | ||
} else if of_trait { | ||
// FIXME: This condition can be removed | ||
// if we support dead check for assoc consts and tys. | ||
if !matches!(tcx.def_kind(local_def_id), DefKind::AssocFn) { | ||
worklist.push((local_def_id, ComesFromAllowExpect::No)); | ||
} else { | ||
// We only care about associated items of traits, | ||
// because they cannot be visited directly, | ||
// so we later mark them as live if their corresponding traits | ||
// or trait items and self types are both live, | ||
// but inherent associated items can be visited and marked directly. | ||
unsolved_items.push((id, local_def_id)); | ||
} | ||
// We only care about associated items of traits, | ||
// because they cannot be visited directly, | ||
// so we later mark them as live if their corresponding traits | ||
// or trait items and self types are both live, | ||
// but inherent associated items can be visited and marked directly. | ||
unsolved_items.push((id, local_def_id)); | ||
} | ||
} | ||
} | ||
|
@@ -792,7 +812,10 @@ fn check_trait_item( | |
id: hir::TraitItemId, | ||
) { | ||
use hir::TraitItemKind::{Const, Fn}; | ||
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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This condition is redundant, no? |
||
) { | ||
let trait_item = tcx.hir_trait_item(id); | ||
if matches!(trait_item.kind, Const(_, Some(_)) | Fn(..)) | ||
&& let Some(comes_from_allow) = | ||
|
@@ -1163,6 +1186,7 @@ impl<'tcx> DeadVisitor<'tcx> { | |
} | ||
match self.tcx.def_kind(def_id) { | ||
DefKind::AssocConst | ||
| DefKind::AssocTy | ||
| DefKind::AssocFn | ||
| DefKind::Fn | ||
| DefKind::Static { .. } | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
//@ check-pass | ||
|
||
#![feature(associated_const_equality)] | ||
#![deny(dead_code)] | ||
|
||
trait Tr { | ||
const I: i32; | ||
} | ||
|
||
impl Tr for () { | ||
const I: i32 = 1; | ||
} | ||
|
||
fn foo() -> impl Tr<I = 1> {} | ||
|
||
trait Tr2 { | ||
const J: i32; | ||
const K: i32; | ||
} | ||
|
||
impl Tr2 for () { | ||
const J: i32 = 1; | ||
const K: i32 = 1; | ||
} | ||
|
||
fn foo2() -> impl Tr2<J = 1, K = 1> {} | ||
|
||
mod t { | ||
pub trait Tr3 { | ||
const L: i32; | ||
} | ||
|
||
impl Tr3 for () { | ||
const L: i32 = 1; | ||
} | ||
} | ||
|
||
fn foo3() -> impl t::Tr3<L = 1> {} | ||
|
||
fn main() { | ||
foo(); | ||
foo2(); | ||
foo3(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
//@ run-rustfix | ||
|
||
#![allow(dead_code)] | ||
|
||
use std::ops::Add; | ||
|
||
struct A<B>(B); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
//@ run-rustfix | ||
|
||
#![allow(dead_code)] | ||
|
||
use std::ops::Add; | ||
|
||
struct A<B>(B); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#![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() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
error: trait `Tr` is never used | ||
--> $DIR/unused-trait-with-assoc-const.rs:3:7 | ||
| | ||
LL | trait Tr { | ||
| ^^ | ||
| | ||
note: the lint level is defined here | ||
--> $DIR/unused-trait-with-assoc-const.rs:1:9 | ||
| | ||
LL | #![deny(dead_code)] | ||
| ^^^^^^^^^ | ||
|
||
error: struct `Foo` is never constructed | ||
--> $DIR/unused-trait-with-assoc-const.rs:7:8 | ||
| | ||
LL | struct Foo; | ||
| ^^^ | ||
|
||
error: aborting due to 2 previous errors | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
|
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In theory, constraints can appear in non-last segments, and outside of poly trait refs too.
So, a safer choice here would probably be using
visit_assoc_item_constraint
.