Skip to content

Commit 4c02363

Browse files
authored
Auto merge of #35317 - TimNN:internal-deprecated, r=eddyb
Ignore deprecation for items deprecated by the same attribute Whenever a node would be reported as deprecated: - check if the parent item is also deprecated - if it is and both were deprecated by the same attribute - skip the deprecation warning fixes #35128 closes #16490 r? @eddyb
2 parents 41fe4b7 + 627b1e8 commit 4c02363

File tree

5 files changed

+205
-25
lines changed

5 files changed

+205
-25
lines changed

src/librustc/middle/stability.rs

+56-17
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use session::Session;
1919
use lint;
2020
use middle::cstore::LOCAL_CRATE;
2121
use hir::def::Def;
22-
use hir::def_id::{CRATE_DEF_INDEX, DefId};
22+
use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
2323
use ty::{self, TyCtxt};
2424
use middle::privacy::AccessLevels;
2525
use syntax::parse::token::InternedString;
@@ -61,12 +61,46 @@ enum AnnotationKind {
6161
Container,
6262
}
6363

64+
/// An entry in the `depr_map`.
65+
#[derive(Clone)]
66+
pub struct DeprecationEntry {
67+
/// The metadata of the attribute associated with this entry.
68+
pub attr: Deprecation,
69+
/// The def id where the attr was originally attached. `None` for non-local
70+
/// `DefId`'s.
71+
origin: Option<DefIndex>,
72+
}
73+
74+
impl DeprecationEntry {
75+
fn local(attr: Deprecation, id: DefId) -> DeprecationEntry {
76+
assert!(id.is_local());
77+
DeprecationEntry {
78+
attr: attr,
79+
origin: Some(id.index),
80+
}
81+
}
82+
83+
fn external(attr: Deprecation) -> DeprecationEntry {
84+
DeprecationEntry {
85+
attr: attr,
86+
origin: None,
87+
}
88+
}
89+
90+
pub fn same_origin(&self, other: &DeprecationEntry) -> bool {
91+
match (self.origin, other.origin) {
92+
(Some(o1), Some(o2)) => o1 == o2,
93+
_ => false
94+
}
95+
}
96+
}
97+
6498
/// A stability index, giving the stability level for items and methods.
6599
pub struct Index<'tcx> {
66100
/// This is mostly a cache, except the stabilities of local items
67101
/// are filled by the annotator.
68102
stab_map: DefIdMap<Option<&'tcx Stability>>,
69-
depr_map: DefIdMap<Option<Deprecation>>,
103+
depr_map: DefIdMap<Option<DeprecationEntry>>,
70104

71105
/// Maps for each crate whether it is part of the staged API.
72106
staged_api: FnvHashMap<ast::CrateNum, bool>
@@ -77,7 +111,7 @@ struct Annotator<'a, 'tcx: 'a> {
77111
tcx: TyCtxt<'a, 'tcx, 'tcx>,
78112
index: &'a mut Index<'tcx>,
79113
parent_stab: Option<&'tcx Stability>,
80-
parent_depr: Option<Deprecation>,
114+
parent_depr: Option<DeprecationEntry>,
81115
access_levels: &'a AccessLevels,
82116
in_trait_impl: bool,
83117
}
@@ -184,14 +218,15 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
184218

185219
// `Deprecation` is just two pointers, no need to intern it
186220
let def_id = self.tcx.map.local_def_id(id);
187-
self.index.depr_map.insert(def_id, Some(depr.clone()));
221+
let depr_entry = Some(DeprecationEntry::local(depr, def_id));
222+
self.index.depr_map.insert(def_id, depr_entry.clone());
188223

189-
let orig_parent_depr = replace(&mut self.parent_depr, Some(depr));
224+
let orig_parent_depr = replace(&mut self.parent_depr, depr_entry);
190225
visit_children(self);
191226
self.parent_depr = orig_parent_depr;
192-
} else if let Some(depr) = self.parent_depr.clone() {
227+
} else if let parent_depr @ Some(_) = self.parent_depr.clone() {
193228
let def_id = self.tcx.map.local_def_id(id);
194-
self.index.depr_map.insert(def_id, Some(depr));
229+
self.index.depr_map.insert(def_id, parent_depr);
195230
visit_children(self);
196231
} else {
197232
visit_children(self);
@@ -351,7 +386,7 @@ struct Checker<'a, 'tcx: 'a> {
351386

352387
impl<'a, 'tcx> Checker<'a, 'tcx> {
353388
fn check(&mut self, id: DefId, span: Span,
354-
stab: &Option<&Stability>, _depr: &Option<Deprecation>) {
389+
stab: &Option<&Stability>, _depr: &Option<DeprecationEntry>) {
355390
if !is_staged_api(self.tcx, id) {
356391
return;
357392
}
@@ -476,7 +511,7 @@ pub fn check_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
476511
warn_about_defns: bool,
477512
cb: &mut FnMut(DefId, Span,
478513
&Option<&Stability>,
479-
&Option<Deprecation>)) {
514+
&Option<DeprecationEntry>)) {
480515
match item.node {
481516
hir::ItemExternCrate(_) => {
482517
// compiler-generated `extern crate` items have a dummy span.
@@ -515,7 +550,7 @@ pub fn check_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
515550
pub fn check_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, e: &hir::Expr,
516551
cb: &mut FnMut(DefId, Span,
517552
&Option<&Stability>,
518-
&Option<Deprecation>)) {
553+
&Option<DeprecationEntry>)) {
519554
let span;
520555
let id = match e.node {
521556
hir::ExprMethodCall(i, _, _) => {
@@ -579,7 +614,7 @@ pub fn check_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
579614
path: &hir::Path, id: ast::NodeId,
580615
cb: &mut FnMut(DefId, Span,
581616
&Option<&Stability>,
582-
&Option<Deprecation>)) {
617+
&Option<DeprecationEntry>)) {
583618
// Paths in import prefixes may have no resolution.
584619
match tcx.expect_def_or_none(id) {
585620
Some(Def::PrimTy(..)) => {}
@@ -595,7 +630,7 @@ pub fn check_path_list_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
595630
item: &hir::PathListItem,
596631
cb: &mut FnMut(DefId, Span,
597632
&Option<&Stability>,
598-
&Option<Deprecation>)) {
633+
&Option<DeprecationEntry>)) {
599634
match tcx.expect_def(item.node.id()) {
600635
Def::PrimTy(..) => {}
601636
def => {
@@ -607,7 +642,7 @@ pub fn check_path_list_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
607642
pub fn check_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &hir::Pat,
608643
cb: &mut FnMut(DefId, Span,
609644
&Option<&Stability>,
610-
&Option<Deprecation>)) {
645+
&Option<DeprecationEntry>)) {
611646
debug!("check_pat(pat = {:?})", pat);
612647
if is_internal(tcx, pat.span) { return; }
613648

@@ -638,7 +673,7 @@ fn maybe_do_stability_check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
638673
id: DefId, span: Span,
639674
cb: &mut FnMut(DefId, Span,
640675
&Option<&Stability>,
641-
&Option<Deprecation>)) {
676+
&Option<DeprecationEntry>)) {
642677
if is_internal(tcx, span) {
643678
debug!("maybe_do_stability_check: \
644679
skipping span={:?} since it is internal", span);
@@ -647,7 +682,7 @@ fn maybe_do_stability_check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
647682
let (stability, deprecation) = if is_staged_api(tcx, id) {
648683
(tcx.lookup_stability(id), None)
649684
} else {
650-
(None, tcx.lookup_deprecation(id))
685+
(None, tcx.lookup_deprecation_entry(id))
651686
};
652687
debug!("maybe_do_stability_check: \
653688
inspecting id={:?} span={:?} of stability={:?}", id, span, stability);
@@ -685,6 +720,10 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
685720
}
686721

687722
pub fn lookup_deprecation(self, id: DefId) -> Option<Deprecation> {
723+
self.lookup_deprecation_entry(id).map(|depr| depr.attr)
724+
}
725+
726+
pub fn lookup_deprecation_entry(self, id: DefId) -> Option<DeprecationEntry> {
688727
if let Some(depr) = self.stability.borrow().depr_map.get(&id) {
689728
return depr.clone();
690729
}
@@ -703,12 +742,12 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
703742
}
704743
}
705744

706-
fn lookup_deprecation_uncached(self, id: DefId) -> Option<Deprecation> {
745+
fn lookup_deprecation_uncached(self, id: DefId) -> Option<DeprecationEntry> {
707746
debug!("lookup(id={:?})", id);
708747
if id.is_local() {
709748
None // The stability cache is filled partially lazily
710749
} else {
711-
self.sess.cstore.deprecation(id)
750+
self.sess.cstore.deprecation(id).map(DeprecationEntry::external)
712751
}
713752
}
714753
}

src/librustc_lint/builtin.rs

+65-5
Original file line numberDiff line numberDiff line change
@@ -567,18 +567,36 @@ declare_lint! {
567567
}
568568

569569
/// Checks for use of items with `#[deprecated]` or `#[rustc_deprecated]` attributes
570-
#[derive(Copy, Clone)]
571-
pub struct Deprecated;
570+
#[derive(Clone)]
571+
pub struct Deprecated {
572+
/// Tracks the `NodeId` of the current item.
573+
///
574+
/// This is required since not all node ids are present in the hir map.
575+
current_item: ast::NodeId,
576+
}
572577

573578
impl Deprecated {
579+
pub fn new() -> Deprecated {
580+
Deprecated {
581+
current_item: ast::CRATE_NODE_ID,
582+
}
583+
}
584+
574585
fn lint(&self, cx: &LateContext, _id: DefId, span: Span,
575-
stability: &Option<&attr::Stability>, deprecation: &Option<attr::Deprecation>) {
586+
stability: &Option<&attr::Stability>,
587+
deprecation: &Option<stability::DeprecationEntry>) {
576588
// Deprecated attributes apply in-crate and cross-crate.
577589
if let Some(&attr::Stability{rustc_depr: Some(attr::RustcDeprecation{ref reason, ..}), ..})
578590
= *stability {
579591
output(cx, DEPRECATED, span, Some(&reason))
580-
} else if let Some(attr::Deprecation{ref note, ..}) = *deprecation {
581-
output(cx, DEPRECATED, span, note.as_ref().map(|x| &**x))
592+
} else if let Some(ref depr_entry) = *deprecation {
593+
if let Some(parent_depr) = cx.tcx.lookup_deprecation_entry(self.parent_def(cx)) {
594+
if parent_depr.same_origin(depr_entry) {
595+
return;
596+
}
597+
}
598+
599+
output(cx, DEPRECATED, span, depr_entry.attr.note.as_ref().map(|x| &**x))
582600
}
583601

584602
fn output(cx: &LateContext, lint: &'static Lint, span: Span, note: Option<&str>) {
@@ -591,6 +609,19 @@ impl Deprecated {
591609
cx.span_lint(lint, span, &msg);
592610
}
593611
}
612+
613+
fn push_item(&mut self, item_id: ast::NodeId) {
614+
self.current_item = item_id;
615+
}
616+
617+
fn item_post(&mut self, cx: &LateContext, item_id: ast::NodeId) {
618+
assert_eq!(self.current_item, item_id);
619+
self.current_item = cx.tcx.map.get_parent(item_id);
620+
}
621+
622+
fn parent_def(&self, cx: &LateContext) -> DefId {
623+
cx.tcx.map.local_def_id(self.current_item)
624+
}
594625
}
595626

596627
impl LintPass for Deprecated {
@@ -601,11 +632,16 @@ impl LintPass for Deprecated {
601632

602633
impl LateLintPass for Deprecated {
603634
fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
635+
self.push_item(item.id);
604636
stability::check_item(cx.tcx, item, false,
605637
&mut |id, sp, stab, depr|
606638
self.lint(cx, id, sp, &stab, &depr));
607639
}
608640

641+
fn check_item_post(&mut self, cx: &LateContext, item: &hir::Item) {
642+
self.item_post(cx, item.id);
643+
}
644+
609645
fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
610646
stability::check_expr(cx.tcx, e,
611647
&mut |id, sp, stab, depr|
@@ -629,6 +665,30 @@ impl LateLintPass for Deprecated {
629665
&mut |id, sp, stab, depr|
630666
self.lint(cx, id, sp, &stab, &depr));
631667
}
668+
669+
fn check_impl_item(&mut self, _: &LateContext, item: &hir::ImplItem) {
670+
self.push_item(item.id);
671+
}
672+
673+
fn check_impl_item_post(&mut self, cx: &LateContext, item: &hir::ImplItem) {
674+
self.item_post(cx, item.id);
675+
}
676+
677+
fn check_trait_item(&mut self, _: &LateContext, item: &hir::TraitItem) {
678+
self.push_item(item.id);
679+
}
680+
681+
fn check_trait_item_post(&mut self, cx: &LateContext, item: &hir::TraitItem) {
682+
self.item_post(cx, item.id);
683+
}
684+
685+
fn check_foreign_item(&mut self, _: &LateContext, item: &hir::ForeignItem) {
686+
self.push_item(item.id);
687+
}
688+
689+
fn check_foreign_item_post(&mut self, cx: &LateContext, item: &hir::ForeignItem) {
690+
self.item_post(cx, item.id);
691+
}
632692
}
633693

634694
declare_lint! {

src/librustc_lint/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
124124
UnusedAllocation,
125125
MissingCopyImplementations,
126126
UnstableFeatures,
127-
Deprecated,
128127
UnconditionalRecursion,
129128
InvalidNoMangleItems,
130129
PluginAsLibrary,
@@ -133,6 +132,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
133132
);
134133

135134
add_builtin_with_new!(sess,
135+
Deprecated,
136136
TypeLimits,
137137
MissingDoc,
138138
MissingDebugImplementations,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![deny(deprecated)]
12+
#![allow(warnings)]
13+
14+
#[deprecated]
15+
fn issue_35128() {
16+
format_args!("foo");
17+
}
18+
19+
#[deprecated]
20+
fn issue_35128_minimal() {
21+
static FOO: &'static str = "foo";
22+
let _ = FOO;
23+
}
24+
25+
#[deprecated]
26+
mod silent {
27+
type DeprecatedType = u8;
28+
struct DeprecatedStruct;
29+
fn deprecated_fn() {}
30+
trait DeprecatedTrait {}
31+
static DEPRECATED_STATIC: u8 = 0;
32+
const DEPRECATED_CONST: u8 = 1;
33+
34+
struct Foo(DeprecatedType);
35+
36+
impl DeprecatedTrait for Foo {}
37+
38+
impl Foo {
39+
fn bar<T: DeprecatedTrait>() {
40+
deprecated_fn();
41+
}
42+
}
43+
44+
fn foo() -> u8 {
45+
DEPRECATED_STATIC +
46+
DEPRECATED_CONST
47+
}
48+
}
49+
50+
#[deprecated]
51+
mod loud {
52+
#[deprecated]
53+
type DeprecatedType = u8;
54+
#[deprecated]
55+
struct DeprecatedStruct;
56+
#[deprecated]
57+
fn deprecated_fn() {}
58+
#[deprecated]
59+
trait DeprecatedTrait {}
60+
#[deprecated]
61+
static DEPRECATED_STATIC: u8 = 0;
62+
#[deprecated]
63+
const DEPRECATED_CONST: u8 = 1;
64+
65+
struct Foo(DeprecatedType); //~ ERROR use of deprecated item
66+
67+
impl DeprecatedTrait for Foo {} //~ ERROR use of deprecated item
68+
69+
impl Foo {
70+
fn bar<T: DeprecatedTrait>() { //~ ERROR use of deprecated item
71+
deprecated_fn(); //~ ERROR use of deprecated item
72+
}
73+
}
74+
75+
fn foo() -> u8 {
76+
DEPRECATED_STATIC + //~ ERROR use of deprecated item
77+
DEPRECATED_CONST //~ ERROR use of deprecated item
78+
}
79+
}
80+
81+
fn main() {}

0 commit comments

Comments
 (0)