Implement #[deprecated]
attribute (RFC 1270)
This commit is contained in:
parent
45a73c8c0c
commit
e3ed7b0501
20 changed files with 899 additions and 110 deletions
|
@ -2390,6 +2390,8 @@ The currently implemented features of the reference compiler are:
|
||||||
* - `stmt_expr_attributes` - Allows attributes on expressions and
|
* - `stmt_expr_attributes` - Allows attributes on expressions and
|
||||||
non-item statements.
|
non-item statements.
|
||||||
|
|
||||||
|
* - `deprecated` - Allows using the `#[deprecated]` attribute.
|
||||||
|
|
||||||
If a feature is promoted to a language feature, then all existing programs will
|
If a feature is promoted to a language feature, then all existing programs will
|
||||||
start to receive compilation warnings about `#![feature]` directives which enabled
|
start to receive compilation warnings about `#![feature]` directives which enabled
|
||||||
the new feature (because the directive is no longer necessary). However, if a
|
the new feature (because the directive is no longer necessary). However, if a
|
||||||
|
|
|
@ -135,6 +135,7 @@ pub enum FoundAst<'ast> {
|
||||||
pub trait CrateStore<'tcx> : Any {
|
pub trait CrateStore<'tcx> : Any {
|
||||||
// item info
|
// item info
|
||||||
fn stability(&self, def: DefId) -> Option<attr::Stability>;
|
fn stability(&self, def: DefId) -> Option<attr::Stability>;
|
||||||
|
fn deprecation(&self, def: DefId) -> Option<attr::Deprecation>;
|
||||||
fn closure_kind(&self, tcx: &ty::ctxt<'tcx>, def_id: DefId)
|
fn closure_kind(&self, tcx: &ty::ctxt<'tcx>, def_id: DefId)
|
||||||
-> ty::ClosureKind;
|
-> ty::ClosureKind;
|
||||||
fn closure_ty(&self, tcx: &ty::ctxt<'tcx>, def_id: DefId)
|
fn closure_ty(&self, tcx: &ty::ctxt<'tcx>, def_id: DefId)
|
||||||
|
@ -292,6 +293,7 @@ pub struct DummyCrateStore;
|
||||||
impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
|
impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
|
||||||
// item info
|
// item info
|
||||||
fn stability(&self, def: DefId) -> Option<attr::Stability> { unimplemented!() }
|
fn stability(&self, def: DefId) -> Option<attr::Stability> { unimplemented!() }
|
||||||
|
fn deprecation(&self, def: DefId) -> Option<attr::Deprecation> { unimplemented!() }
|
||||||
fn closure_kind(&self, tcx: &ty::ctxt<'tcx>, def_id: DefId)
|
fn closure_kind(&self, tcx: &ty::ctxt<'tcx>, def_id: DefId)
|
||||||
-> ty::ClosureKind { unimplemented!() }
|
-> ty::ClosureKind { unimplemented!() }
|
||||||
fn closure_ty(&self, tcx: &ty::ctxt<'tcx>, def_id: DefId)
|
fn closure_ty(&self, tcx: &ty::ctxt<'tcx>, def_id: DefId)
|
||||||
|
|
|
@ -25,7 +25,7 @@ use syntax::codemap::{Span, DUMMY_SP};
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::ast::{NodeId, Attribute};
|
use syntax::ast::{NodeId, Attribute};
|
||||||
use syntax::feature_gate::{GateIssue, emit_feature_err};
|
use syntax::feature_gate::{GateIssue, emit_feature_err};
|
||||||
use syntax::attr::{self, Stability, AttrMetaMethods};
|
use syntax::attr::{self, Stability, Deprecation, AttrMetaMethods};
|
||||||
use util::nodemap::{DefIdMap, FnvHashSet, FnvHashMap};
|
use util::nodemap::{DefIdMap, FnvHashSet, FnvHashMap};
|
||||||
|
|
||||||
use rustc_front::hir;
|
use rustc_front::hir;
|
||||||
|
@ -61,7 +61,8 @@ enum AnnotationKind {
|
||||||
pub struct Index<'tcx> {
|
pub struct Index<'tcx> {
|
||||||
/// This is mostly a cache, except the stabilities of local items
|
/// This is mostly a cache, except the stabilities of local items
|
||||||
/// are filled by the annotator.
|
/// are filled by the annotator.
|
||||||
map: DefIdMap<Option<&'tcx Stability>>,
|
stab_map: DefIdMap<Option<&'tcx Stability>>,
|
||||||
|
depr_map: DefIdMap<Option<Deprecation>>,
|
||||||
|
|
||||||
/// Maps for each crate whether it is part of the staged API.
|
/// Maps for each crate whether it is part of the staged API.
|
||||||
staged_api: FnvHashMap<ast::CrateNum, bool>
|
staged_api: FnvHashMap<ast::CrateNum, bool>
|
||||||
|
@ -71,7 +72,8 @@ pub struct Index<'tcx> {
|
||||||
struct Annotator<'a, 'tcx: 'a> {
|
struct Annotator<'a, 'tcx: 'a> {
|
||||||
tcx: &'a ty::ctxt<'tcx>,
|
tcx: &'a ty::ctxt<'tcx>,
|
||||||
index: &'a mut Index<'tcx>,
|
index: &'a mut Index<'tcx>,
|
||||||
parent: Option<&'tcx Stability>,
|
parent_stab: Option<&'tcx Stability>,
|
||||||
|
parent_depr: Option<Deprecation>,
|
||||||
access_levels: &'a AccessLevels,
|
access_levels: &'a AccessLevels,
|
||||||
in_trait_impl: bool,
|
in_trait_impl: bool,
|
||||||
in_enum: bool,
|
in_enum: bool,
|
||||||
|
@ -86,22 +88,26 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
|
||||||
{
|
{
|
||||||
if self.index.staged_api[&LOCAL_CRATE] && self.tcx.sess.features.borrow().staged_api {
|
if self.index.staged_api[&LOCAL_CRATE] && self.tcx.sess.features.borrow().staged_api {
|
||||||
debug!("annotate(id = {:?}, attrs = {:?})", id, attrs);
|
debug!("annotate(id = {:?}, attrs = {:?})", id, attrs);
|
||||||
|
if let Some(..) = attr::find_deprecation(self.tcx.sess.diagnostic(), attrs, item_sp) {
|
||||||
|
self.tcx.sess.span_err(item_sp, "`#[deprecated]` cannot be used in staged api, \
|
||||||
|
use `#[rustc_deprecated]` instead");
|
||||||
|
}
|
||||||
if let Some(mut stab) = attr::find_stability(self.tcx.sess.diagnostic(),
|
if let Some(mut stab) = attr::find_stability(self.tcx.sess.diagnostic(),
|
||||||
attrs, item_sp) {
|
attrs, item_sp) {
|
||||||
// Error if prohibited, or can't inherit anything from a container
|
// Error if prohibited, or can't inherit anything from a container
|
||||||
if kind == AnnotationKind::Prohibited ||
|
if kind == AnnotationKind::Prohibited ||
|
||||||
(kind == AnnotationKind::Container &&
|
(kind == AnnotationKind::Container &&
|
||||||
stab.level.is_stable() &&
|
stab.level.is_stable() &&
|
||||||
stab.depr.is_none()) {
|
stab.rustc_depr.is_none()) {
|
||||||
self.tcx.sess.span_err(item_sp, "This stability annotation is useless");
|
self.tcx.sess.span_err(item_sp, "This stability annotation is useless");
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("annotate: found {:?}", stab);
|
debug!("annotate: found {:?}", stab);
|
||||||
// If parent is deprecated and we're not, inherit this by merging
|
// If parent is deprecated and we're not, inherit this by merging
|
||||||
// deprecated_since and its reason.
|
// deprecated_since and its reason.
|
||||||
if let Some(parent_stab) = self.parent {
|
if let Some(parent_stab) = self.parent_stab {
|
||||||
if parent_stab.depr.is_some() && stab.depr.is_none() {
|
if parent_stab.rustc_depr.is_some() && stab.rustc_depr.is_none() {
|
||||||
stab.depr = parent_stab.depr.clone()
|
stab.rustc_depr = parent_stab.rustc_depr.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,8 +115,8 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
|
||||||
|
|
||||||
// Check if deprecated_since < stable_since. If it is,
|
// Check if deprecated_since < stable_since. If it is,
|
||||||
// this is *almost surely* an accident.
|
// this is *almost surely* an accident.
|
||||||
if let (&Some(attr::Deprecation {since: ref dep_since, ..}),
|
if let (&Some(attr::RustcDeprecation {since: ref dep_since, ..}),
|
||||||
&attr::Stable {since: ref stab_since}) = (&stab.depr, &stab.level) {
|
&attr::Stable {since: ref stab_since}) = (&stab.rustc_depr, &stab.level) {
|
||||||
// Explicit version of iter::order::lt to handle parse errors properly
|
// Explicit version of iter::order::lt to handle parse errors properly
|
||||||
for (dep_v, stab_v) in dep_since.split(".").zip(stab_since.split(".")) {
|
for (dep_v, stab_v) in dep_since.split(".").zip(stab_since.split(".")) {
|
||||||
if let (Ok(dep_v), Ok(stab_v)) = (dep_v.parse::<u64>(), stab_v.parse()) {
|
if let (Ok(dep_v), Ok(stab_v)) = (dep_v.parse::<u64>(), stab_v.parse()) {
|
||||||
|
@ -134,20 +140,20 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let def_id = self.tcx.map.local_def_id(id);
|
let def_id = self.tcx.map.local_def_id(id);
|
||||||
self.index.map.insert(def_id, Some(stab));
|
self.index.stab_map.insert(def_id, Some(stab));
|
||||||
|
|
||||||
let parent = replace(&mut self.parent, Some(stab));
|
let orig_parent_stab = replace(&mut self.parent_stab, Some(stab));
|
||||||
visit_children(self);
|
visit_children(self);
|
||||||
self.parent = parent;
|
self.parent_stab = orig_parent_stab;
|
||||||
} else {
|
} else {
|
||||||
debug!("annotate: not found, parent = {:?}", self.parent);
|
debug!("annotate: not found, parent = {:?}", self.parent_stab);
|
||||||
let mut is_error = kind == AnnotationKind::Required &&
|
let mut is_error = kind == AnnotationKind::Required &&
|
||||||
self.access_levels.is_reachable(id) &&
|
self.access_levels.is_reachable(id) &&
|
||||||
!self.tcx.sess.opts.test;
|
!self.tcx.sess.opts.test;
|
||||||
if let Some(stab) = self.parent {
|
if let Some(stab) = self.parent_stab {
|
||||||
if stab.level.is_unstable() {
|
if stab.level.is_unstable() {
|
||||||
let def_id = self.tcx.map.local_def_id(id);
|
let def_id = self.tcx.map.local_def_id(id);
|
||||||
self.index.map.insert(def_id, Some(stab));
|
self.index.stab_map.insert(def_id, Some(stab));
|
||||||
is_error = false;
|
is_error = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,9 +171,35 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
|
||||||
attr::mark_used(attr);
|
attr::mark_used(attr);
|
||||||
self.tcx.sess.span_err(attr.span(), "stability attributes may not be used \
|
self.tcx.sess.span_err(attr.span(), "stability attributes may not be used \
|
||||||
outside of the standard library");
|
outside of the standard library");
|
||||||
|
} else if tag == "deprecated" {
|
||||||
|
if !self.tcx.sess.features.borrow().deprecated {
|
||||||
|
self.tcx.sess.span_err(attr.span(),
|
||||||
|
"`#[deprecated]` attribute is unstable");
|
||||||
|
fileline_help!(self.tcx.sess, attr.span(), "add #![feature(deprecated)] to \
|
||||||
|
the crate features to enable");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
visit_children(self);
|
|
||||||
|
if let Some(depr) = attr::find_deprecation(self.tcx.sess.diagnostic(), attrs, item_sp) {
|
||||||
|
if kind == AnnotationKind::Prohibited {
|
||||||
|
self.tcx.sess.span_err(item_sp, "This deprecation annotation is useless");
|
||||||
|
}
|
||||||
|
|
||||||
|
// `Deprecation` is just two pointers, no need to intern it
|
||||||
|
let def_id = self.tcx.map.local_def_id(id);
|
||||||
|
self.index.depr_map.insert(def_id, Some(depr.clone()));
|
||||||
|
|
||||||
|
let orig_parent_depr = replace(&mut self.parent_depr, Some(depr));
|
||||||
|
visit_children(self);
|
||||||
|
self.parent_depr = orig_parent_depr;
|
||||||
|
} else if let Some(depr) = self.parent_depr.clone() {
|
||||||
|
let def_id = self.tcx.map.local_def_id(id);
|
||||||
|
self.index.depr_map.insert(def_id, Some(depr));
|
||||||
|
visit_children(self);
|
||||||
|
} else {
|
||||||
|
visit_children(self);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -269,7 +301,8 @@ impl<'tcx> Index<'tcx> {
|
||||||
let mut annotator = Annotator {
|
let mut annotator = Annotator {
|
||||||
tcx: tcx,
|
tcx: tcx,
|
||||||
index: self,
|
index: self,
|
||||||
parent: None,
|
parent_stab: None,
|
||||||
|
parent_depr: None,
|
||||||
access_levels: access_levels,
|
access_levels: access_levels,
|
||||||
in_trait_impl: false,
|
in_trait_impl: false,
|
||||||
in_enum: false,
|
in_enum: false,
|
||||||
|
@ -291,7 +324,8 @@ impl<'tcx> Index<'tcx> {
|
||||||
staged_api.insert(LOCAL_CRATE, is_staged_api);
|
staged_api.insert(LOCAL_CRATE, is_staged_api);
|
||||||
Index {
|
Index {
|
||||||
staged_api: staged_api,
|
staged_api: staged_api,
|
||||||
map: DefIdMap(),
|
stab_map: DefIdMap(),
|
||||||
|
depr_map: DefIdMap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -327,7 +361,11 @@ struct Checker<'a, 'tcx: 'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Checker<'a, 'tcx> {
|
impl<'a, 'tcx> Checker<'a, 'tcx> {
|
||||||
fn check(&mut self, id: DefId, span: Span, stab: &Option<&Stability>) {
|
fn check(&mut self, id: DefId, span: Span,
|
||||||
|
stab: &Option<&Stability>, _depr: &Option<Deprecation>) {
|
||||||
|
if !is_staged_api(self.tcx, id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Only the cross-crate scenario matters when checking unstable APIs
|
// Only the cross-crate scenario matters when checking unstable APIs
|
||||||
let cross_crate = !id.is_local();
|
let cross_crate = !id.is_local();
|
||||||
if !cross_crate {
|
if !cross_crate {
|
||||||
|
@ -395,31 +433,31 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> {
|
||||||
if item.span == DUMMY_SP && item.name.as_str() == "__test" { return }
|
if item.span == DUMMY_SP && item.name.as_str() == "__test" { return }
|
||||||
|
|
||||||
check_item(self.tcx, item, true,
|
check_item(self.tcx, item, true,
|
||||||
&mut |id, sp, stab| self.check(id, sp, stab));
|
&mut |id, sp, stab, depr| self.check(id, sp, stab, depr));
|
||||||
intravisit::walk_item(self, item);
|
intravisit::walk_item(self, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expr(&mut self, ex: &hir::Expr) {
|
fn visit_expr(&mut self, ex: &hir::Expr) {
|
||||||
check_expr(self.tcx, ex,
|
check_expr(self.tcx, ex,
|
||||||
&mut |id, sp, stab| self.check(id, sp, stab));
|
&mut |id, sp, stab, depr| self.check(id, sp, stab, depr));
|
||||||
intravisit::walk_expr(self, ex);
|
intravisit::walk_expr(self, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_path(&mut self, path: &hir::Path, id: ast::NodeId) {
|
fn visit_path(&mut self, path: &hir::Path, id: ast::NodeId) {
|
||||||
check_path(self.tcx, path, id,
|
check_path(self.tcx, path, id,
|
||||||
&mut |id, sp, stab| self.check(id, sp, stab));
|
&mut |id, sp, stab, depr| self.check(id, sp, stab, depr));
|
||||||
intravisit::walk_path(self, path)
|
intravisit::walk_path(self, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_path_list_item(&mut self, prefix: &hir::Path, item: &hir::PathListItem) {
|
fn visit_path_list_item(&mut self, prefix: &hir::Path, item: &hir::PathListItem) {
|
||||||
check_path_list_item(self.tcx, item,
|
check_path_list_item(self.tcx, item,
|
||||||
&mut |id, sp, stab| self.check(id, sp, stab));
|
&mut |id, sp, stab, depr| self.check(id, sp, stab, depr));
|
||||||
intravisit::walk_path_list_item(self, prefix, item)
|
intravisit::walk_path_list_item(self, prefix, item)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_pat(&mut self, pat: &hir::Pat) {
|
fn visit_pat(&mut self, pat: &hir::Pat) {
|
||||||
check_pat(self.tcx, pat,
|
check_pat(self.tcx, pat,
|
||||||
&mut |id, sp, stab| self.check(id, sp, stab));
|
&mut |id, sp, stab, depr| self.check(id, sp, stab, depr));
|
||||||
intravisit::walk_pat(self, pat)
|
intravisit::walk_pat(self, pat)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,7 +479,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> {
|
||||||
|
|
||||||
/// Helper for discovering nodes to check for stability
|
/// Helper for discovering nodes to check for stability
|
||||||
pub fn check_item(tcx: &ty::ctxt, item: &hir::Item, warn_about_defns: bool,
|
pub fn check_item(tcx: &ty::ctxt, item: &hir::Item, warn_about_defns: bool,
|
||||||
cb: &mut FnMut(DefId, Span, &Option<&Stability>)) {
|
cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option<Deprecation>)) {
|
||||||
match item.node {
|
match item.node {
|
||||||
hir::ItemExternCrate(_) => {
|
hir::ItemExternCrate(_) => {
|
||||||
// compiler-generated `extern crate` items have a dummy span.
|
// compiler-generated `extern crate` items have a dummy span.
|
||||||
|
@ -478,7 +516,7 @@ pub fn check_item(tcx: &ty::ctxt, item: &hir::Item, warn_about_defns: bool,
|
||||||
|
|
||||||
/// Helper for discovering nodes to check for stability
|
/// Helper for discovering nodes to check for stability
|
||||||
pub fn check_expr(tcx: &ty::ctxt, e: &hir::Expr,
|
pub fn check_expr(tcx: &ty::ctxt, e: &hir::Expr,
|
||||||
cb: &mut FnMut(DefId, Span, &Option<&Stability>)) {
|
cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option<Deprecation>)) {
|
||||||
let span;
|
let span;
|
||||||
let id = match e.node {
|
let id = match e.node {
|
||||||
hir::ExprMethodCall(i, _, _) => {
|
hir::ExprMethodCall(i, _, _) => {
|
||||||
|
@ -539,7 +577,7 @@ pub fn check_expr(tcx: &ty::ctxt, e: &hir::Expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_path(tcx: &ty::ctxt, path: &hir::Path, id: ast::NodeId,
|
pub fn check_path(tcx: &ty::ctxt, path: &hir::Path, id: ast::NodeId,
|
||||||
cb: &mut FnMut(DefId, Span, &Option<&Stability>)) {
|
cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option<Deprecation>)) {
|
||||||
match tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
|
match tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
|
||||||
Some(def::DefPrimTy(..)) => {}
|
Some(def::DefPrimTy(..)) => {}
|
||||||
Some(def::DefSelfTy(..)) => {}
|
Some(def::DefSelfTy(..)) => {}
|
||||||
|
@ -551,7 +589,7 @@ pub fn check_path(tcx: &ty::ctxt, path: &hir::Path, id: ast::NodeId,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_path_list_item(tcx: &ty::ctxt, item: &hir::PathListItem,
|
pub fn check_path_list_item(tcx: &ty::ctxt, item: &hir::PathListItem,
|
||||||
cb: &mut FnMut(DefId, Span, &Option<&Stability>)) {
|
cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option<Deprecation>)) {
|
||||||
match tcx.def_map.borrow().get(&item.node.id()).map(|d| d.full_def()) {
|
match tcx.def_map.borrow().get(&item.node.id()).map(|d| d.full_def()) {
|
||||||
Some(def::DefPrimTy(..)) => {}
|
Some(def::DefPrimTy(..)) => {}
|
||||||
Some(def) => {
|
Some(def) => {
|
||||||
|
@ -562,7 +600,7 @@ pub fn check_path_list_item(tcx: &ty::ctxt, item: &hir::PathListItem,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_pat(tcx: &ty::ctxt, pat: &hir::Pat,
|
pub fn check_pat(tcx: &ty::ctxt, pat: &hir::Pat,
|
||||||
cb: &mut FnMut(DefId, Span, &Option<&Stability>)) {
|
cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option<Deprecation>)) {
|
||||||
debug!("check_pat(pat = {:?})", pat);
|
debug!("check_pat(pat = {:?})", pat);
|
||||||
if is_internal(tcx, pat.span) { return; }
|
if is_internal(tcx, pat.span) { return; }
|
||||||
|
|
||||||
|
@ -591,21 +629,21 @@ pub fn check_pat(tcx: &ty::ctxt, pat: &hir::Pat,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maybe_do_stability_check(tcx: &ty::ctxt, id: DefId, span: Span,
|
fn maybe_do_stability_check(tcx: &ty::ctxt, id: DefId, span: Span,
|
||||||
cb: &mut FnMut(DefId, Span, &Option<&Stability>)) {
|
cb: &mut FnMut(DefId, Span,
|
||||||
if !is_staged_api(tcx, id) {
|
&Option<&Stability>, &Option<Deprecation>)) {
|
||||||
debug!("maybe_do_stability_check: \
|
|
||||||
skipping id={:?} since it is not staged_api", id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if is_internal(tcx, span) {
|
if is_internal(tcx, span) {
|
||||||
debug!("maybe_do_stability_check: \
|
debug!("maybe_do_stability_check: \
|
||||||
skipping span={:?} since it is internal", span);
|
skipping span={:?} since it is internal", span);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let ref stability = lookup(tcx, id);
|
let (stability, deprecation) = if is_staged_api(tcx, id) {
|
||||||
|
(lookup_stability(tcx, id), None)
|
||||||
|
} else {
|
||||||
|
(None, lookup_deprecation(tcx, id))
|
||||||
|
};
|
||||||
debug!("maybe_do_stability_check: \
|
debug!("maybe_do_stability_check: \
|
||||||
inspecting id={:?} span={:?} of stability={:?}", id, span, stability);
|
inspecting id={:?} span={:?} of stability={:?}", id, span, stability);
|
||||||
cb(id, span, stability);
|
cb(id, span, &stability, &deprecation);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_internal(tcx: &ty::ctxt, span: Span) -> bool {
|
fn is_internal(tcx: &ty::ctxt, span: Span) -> bool {
|
||||||
|
@ -627,24 +665,34 @@ fn is_staged_api(tcx: &ty::ctxt, id: DefId) -> bool {
|
||||||
|
|
||||||
/// Lookup the stability for a node, loading external crate
|
/// Lookup the stability for a node, loading external crate
|
||||||
/// metadata as necessary.
|
/// metadata as necessary.
|
||||||
pub fn lookup<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<&'tcx Stability> {
|
pub fn lookup_stability<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<&'tcx Stability> {
|
||||||
if let Some(st) = tcx.stability.borrow().map.get(&id) {
|
if let Some(st) = tcx.stability.borrow().stab_map.get(&id) {
|
||||||
return *st;
|
return *st;
|
||||||
}
|
}
|
||||||
|
|
||||||
let st = lookup_uncached(tcx, id);
|
let st = lookup_stability_uncached(tcx, id);
|
||||||
tcx.stability.borrow_mut().map.insert(id, st);
|
tcx.stability.borrow_mut().stab_map.insert(id, st);
|
||||||
st
|
st
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_uncached<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<&'tcx Stability> {
|
pub fn lookup_deprecation<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<Deprecation> {
|
||||||
|
if let Some(depr) = tcx.stability.borrow().depr_map.get(&id) {
|
||||||
|
return depr.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
let depr = lookup_deprecation_uncached(tcx, id);
|
||||||
|
tcx.stability.borrow_mut().depr_map.insert(id, depr.clone());
|
||||||
|
depr
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lookup_stability_uncached<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<&'tcx Stability> {
|
||||||
debug!("lookup(id={:?})", id);
|
debug!("lookup(id={:?})", id);
|
||||||
|
|
||||||
// is this definition the implementation of a trait method?
|
// is this definition the implementation of a trait method?
|
||||||
match tcx.trait_item_of_item(id) {
|
match tcx.trait_item_of_item(id) {
|
||||||
Some(ty::MethodTraitItemId(trait_method_id)) if trait_method_id != id => {
|
Some(ty::MethodTraitItemId(trait_method_id)) if trait_method_id != id => {
|
||||||
debug!("lookup: trait_method_id={:?}", trait_method_id);
|
debug!("lookup: trait_method_id={:?}", trait_method_id);
|
||||||
return lookup(tcx, trait_method_id)
|
return lookup_stability(tcx, trait_method_id)
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -663,7 +711,40 @@ fn lookup_uncached<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<&'tcx Stabil
|
||||||
// unmarked impls for it. See FIXME above for more details.
|
// unmarked impls for it. See FIXME above for more details.
|
||||||
|
|
||||||
debug!("lookup: trait_id={:?}", trait_id);
|
debug!("lookup: trait_id={:?}", trait_id);
|
||||||
return lookup(tcx, trait_id);
|
return lookup_stability(tcx, trait_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lookup_deprecation_uncached<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<Deprecation> {
|
||||||
|
debug!("lookup(id={:?})", id);
|
||||||
|
|
||||||
|
// is this definition the implementation of a trait method?
|
||||||
|
match tcx.trait_item_of_item(id) {
|
||||||
|
Some(ty::MethodTraitItemId(trait_method_id)) if trait_method_id != id => {
|
||||||
|
debug!("lookup: trait_method_id={:?}", trait_method_id);
|
||||||
|
return lookup_deprecation(tcx, trait_method_id)
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let item_depr = if id.is_local() {
|
||||||
|
None // The stability cache is filled partially lazily
|
||||||
|
} else {
|
||||||
|
tcx.sess.cstore.deprecation(id)
|
||||||
|
};
|
||||||
|
|
||||||
|
item_depr.or_else(|| {
|
||||||
|
if tcx.is_impl(id) {
|
||||||
|
if let Some(trait_id) = tcx.trait_id_of_impl(id) {
|
||||||
|
// FIXME (#18969): for the time being, simply use the
|
||||||
|
// stability of the trait to determine the stability of any
|
||||||
|
// unmarked impls for it. See FIXME above for more details.
|
||||||
|
|
||||||
|
debug!("lookup: trait_id={:?}", trait_id);
|
||||||
|
return lookup_deprecation(tcx, trait_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
|
|
@ -575,74 +575,71 @@ impl LateLintPass for MissingDebugImplementations {
|
||||||
declare_lint! {
|
declare_lint! {
|
||||||
DEPRECATED,
|
DEPRECATED,
|
||||||
Warn,
|
Warn,
|
||||||
"detects use of #[rustc_deprecated] items"
|
"detects use of `#[deprecated]` or `#[rustc_deprecated]` items"
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks for use of items with `#[rustc_deprecated]` attributes
|
/// Checks for use of items with `#[deprecated]` or `#[rustc_deprecated]` attributes
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct Stability;
|
pub struct Deprecated;
|
||||||
|
|
||||||
impl Stability {
|
impl Deprecated {
|
||||||
fn lint(&self, cx: &LateContext, _id: DefId,
|
fn lint(&self, cx: &LateContext, _id: DefId, span: Span,
|
||||||
span: Span, stability: &Option<&attr::Stability>) {
|
stability: &Option<&attr::Stability>, deprecation: &Option<attr::Deprecation>) {
|
||||||
// Deprecated attributes apply in-crate and cross-crate.
|
// Deprecated attributes apply in-crate and cross-crate.
|
||||||
let (lint, label) = match *stability {
|
if let Some(&attr::Stability{rustc_depr: Some(attr::RustcDeprecation{ref reason, ..}), ..})
|
||||||
Some(&attr::Stability { depr: Some(_), .. }) =>
|
= *stability {
|
||||||
(DEPRECATED, "deprecated"),
|
output(cx, DEPRECATED, span, Some(&reason))
|
||||||
_ => return
|
} else if let Some(attr::Deprecation{ref note, ..}) = *deprecation {
|
||||||
};
|
output(cx, DEPRECATED, span, note.as_ref().map(|x| &**x))
|
||||||
|
}
|
||||||
|
|
||||||
output(cx, span, stability, lint, label);
|
fn output(cx: &LateContext, lint: &'static Lint, span: Span, note: Option<&str>) {
|
||||||
|
let msg = if let Some(note) = note {
|
||||||
fn output(cx: &LateContext, span: Span, stability: &Option<&attr::Stability>,
|
format!("use of deprecated item: {}", note)
|
||||||
lint: &'static Lint, label: &'static str) {
|
} else {
|
||||||
let msg = match *stability {
|
format!("use of deprecated item")
|
||||||
Some(&attr::Stability {depr: Some(attr::Deprecation {ref reason, ..}), ..}) => {
|
|
||||||
format!("use of {} item: {}", label, reason)
|
|
||||||
}
|
|
||||||
_ => format!("use of {} item", label)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
cx.span_lint(lint, span, &msg[..]);
|
cx.span_lint(lint, span, &msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LintPass for Stability {
|
impl LintPass for Deprecated {
|
||||||
fn get_lints(&self) -> LintArray {
|
fn get_lints(&self) -> LintArray {
|
||||||
lint_array!(DEPRECATED)
|
lint_array!(DEPRECATED)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Stability {
|
impl LateLintPass for Deprecated {
|
||||||
fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
|
fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
|
||||||
stability::check_item(cx.tcx, item, false,
|
stability::check_item(cx.tcx, item, false,
|
||||||
&mut |id, sp, stab|
|
&mut |id, sp, stab, depr|
|
||||||
self.lint(cx, id, sp, &stab));
|
self.lint(cx, id, sp, &stab, &depr));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
|
fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
|
||||||
stability::check_expr(cx.tcx, e,
|
stability::check_expr(cx.tcx, e,
|
||||||
&mut |id, sp, stab|
|
&mut |id, sp, stab, depr|
|
||||||
self.lint(cx, id, sp, &stab));
|
self.lint(cx, id, sp, &stab, &depr));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_path(&mut self, cx: &LateContext, path: &hir::Path, id: ast::NodeId) {
|
fn check_path(&mut self, cx: &LateContext, path: &hir::Path, id: ast::NodeId) {
|
||||||
stability::check_path(cx.tcx, path, id,
|
stability::check_path(cx.tcx, path, id,
|
||||||
&mut |id, sp, stab|
|
&mut |id, sp, stab, depr|
|
||||||
self.lint(cx, id, sp, &stab));
|
self.lint(cx, id, sp, &stab, &depr));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_path_list_item(&mut self, cx: &LateContext, item: &hir::PathListItem) {
|
fn check_path_list_item(&mut self, cx: &LateContext, item: &hir::PathListItem) {
|
||||||
stability::check_path_list_item(cx.tcx, item,
|
stability::check_path_list_item(cx.tcx, item,
|
||||||
&mut |id, sp, stab|
|
&mut |id, sp, stab, depr|
|
||||||
self.lint(cx, id, sp, &stab));
|
self.lint(cx, id, sp, &stab, &depr));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) {
|
fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) {
|
||||||
stability::check_pat(cx.tcx, pat,
|
stability::check_pat(cx.tcx, pat,
|
||||||
&mut |id, sp, stab|
|
&mut |id, sp, stab, depr|
|
||||||
self.lint(cx, id, sp, &stab));
|
self.lint(cx, id, sp, &stab, &depr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
|
||||||
UnusedAllocation,
|
UnusedAllocation,
|
||||||
MissingCopyImplementations,
|
MissingCopyImplementations,
|
||||||
UnstableFeatures,
|
UnstableFeatures,
|
||||||
Stability,
|
Deprecated,
|
||||||
UnconditionalRecursion,
|
UnconditionalRecursion,
|
||||||
InvalidNoMangleItems,
|
InvalidNoMangleItems,
|
||||||
PluginAsLibrary,
|
PluginAsLibrary,
|
||||||
|
|
|
@ -237,6 +237,8 @@ pub const tag_impl_coerce_unsized_kind: usize = 0xa5;
|
||||||
|
|
||||||
pub const tag_items_data_item_constness: usize = 0xa6;
|
pub const tag_items_data_item_constness: usize = 0xa6;
|
||||||
|
|
||||||
|
pub const tag_items_data_item_deprecation: usize = 0xa7;
|
||||||
|
|
||||||
pub const tag_rustc_version: usize = 0x10f;
|
pub const tag_rustc_version: usize = 0x10f;
|
||||||
pub fn rustc_version() -> String {
|
pub fn rustc_version() -> String {
|
||||||
format!(
|
format!(
|
||||||
|
|
|
@ -42,6 +42,12 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
|
||||||
decoder::get_stability(&*cdata, def.index)
|
decoder::get_stability(&*cdata, def.index)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deprecation(&self, def: DefId) -> Option<attr::Deprecation>
|
||||||
|
{
|
||||||
|
let cdata = self.get_crate_data(def.krate);
|
||||||
|
decoder::get_deprecation(&*cdata, def.index)
|
||||||
|
}
|
||||||
|
|
||||||
fn closure_kind(&self, _tcx: &ty::ctxt<'tcx>, def_id: DefId) -> ty::ClosureKind
|
fn closure_kind(&self, _tcx: &ty::ctxt<'tcx>, def_id: DefId) -> ty::ClosureKind
|
||||||
{
|
{
|
||||||
assert!(!def_id.is_local());
|
assert!(!def_id.is_local());
|
||||||
|
|
|
@ -526,6 +526,14 @@ pub fn get_stability(cdata: Cmd, id: DefIndex) -> Option<attr::Stability> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_deprecation(cdata: Cmd, id: DefIndex) -> Option<attr::Deprecation> {
|
||||||
|
let item = cdata.lookup_item(id);
|
||||||
|
reader::maybe_get_doc(item, tag_items_data_item_deprecation).map(|doc| {
|
||||||
|
let mut decoder = reader::Decoder::new(doc);
|
||||||
|
Decodable::decode(&mut decoder).unwrap()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_repr_attrs(cdata: Cmd, id: DefIndex) -> Vec<attr::ReprAttr> {
|
pub fn get_repr_attrs(cdata: Cmd, id: DefIndex) -> Vec<attr::ReprAttr> {
|
||||||
let item = cdata.lookup_item(id);
|
let item = cdata.lookup_item(id);
|
||||||
match reader::maybe_get_doc(item, tag_items_data_item_repr).map(|doc| {
|
match reader::maybe_get_doc(item, tag_items_data_item_repr).map(|doc| {
|
||||||
|
|
|
@ -342,8 +342,10 @@ fn encode_enum_variant_info<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||||
encode_attributes(rbml_w, &attrs);
|
encode_attributes(rbml_w, &attrs);
|
||||||
encode_repr_attrs(rbml_w, ecx, &attrs);
|
encode_repr_attrs(rbml_w, ecx, &attrs);
|
||||||
|
|
||||||
let stab = stability::lookup(ecx.tcx, vid);
|
let stab = stability::lookup_stability(ecx.tcx, vid);
|
||||||
|
let depr = stability::lookup_deprecation(ecx.tcx, vid);
|
||||||
encode_stability(rbml_w, stab);
|
encode_stability(rbml_w, stab);
|
||||||
|
encode_deprecation(rbml_w, depr);
|
||||||
|
|
||||||
encode_struct_fields(rbml_w, variant);
|
encode_struct_fields(rbml_w, variant);
|
||||||
|
|
||||||
|
@ -450,8 +452,10 @@ fn encode_info_for_mod(ecx: &EncodeContext,
|
||||||
encode_path(rbml_w, path.clone());
|
encode_path(rbml_w, path.clone());
|
||||||
encode_visibility(rbml_w, vis);
|
encode_visibility(rbml_w, vis);
|
||||||
|
|
||||||
let stab = stability::lookup(ecx.tcx, ecx.tcx.map.local_def_id(id));
|
let stab = stability::lookup_stability(ecx.tcx, ecx.tcx.map.local_def_id(id));
|
||||||
|
let depr = stability::lookup_deprecation(ecx.tcx, ecx.tcx.map.local_def_id(id));
|
||||||
encode_stability(rbml_w, stab);
|
encode_stability(rbml_w, stab);
|
||||||
|
encode_deprecation(rbml_w, depr);
|
||||||
|
|
||||||
// Encode the reexports of this module, if this module is public.
|
// Encode the reexports of this module, if this module is public.
|
||||||
if vis == hir::Public {
|
if vis == hir::Public {
|
||||||
|
@ -538,8 +542,10 @@ fn encode_field<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||||
encode_bounds_and_type_for_item(rbml_w, ecx, index, id);
|
encode_bounds_and_type_for_item(rbml_w, ecx, index, id);
|
||||||
encode_def_id_and_key(ecx, rbml_w, field.did);
|
encode_def_id_and_key(ecx, rbml_w, field.did);
|
||||||
|
|
||||||
let stab = stability::lookup(ecx.tcx, field.did);
|
let stab = stability::lookup_stability(ecx.tcx, field.did);
|
||||||
|
let depr = stability::lookup_deprecation(ecx.tcx, field.did);
|
||||||
encode_stability(rbml_w, stab);
|
encode_stability(rbml_w, stab);
|
||||||
|
encode_deprecation(rbml_w, depr);
|
||||||
|
|
||||||
rbml_w.end_tag();
|
rbml_w.end_tag();
|
||||||
}
|
}
|
||||||
|
@ -565,8 +571,10 @@ fn encode_info_for_struct_ctor<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||||
encode_symbol(ecx, rbml_w, ctor_id);
|
encode_symbol(ecx, rbml_w, ctor_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
let stab = stability::lookup(ecx.tcx, ecx.tcx.map.local_def_id(ctor_id));
|
let stab = stability::lookup_stability(ecx.tcx, ecx.tcx.map.local_def_id(ctor_id));
|
||||||
|
let depr= stability::lookup_deprecation(ecx.tcx, ecx.tcx.map.local_def_id(ctor_id));
|
||||||
encode_stability(rbml_w, stab);
|
encode_stability(rbml_w, stab);
|
||||||
|
encode_deprecation(rbml_w, depr);
|
||||||
|
|
||||||
// indicate that this is a tuple struct ctor, because downstream users will normally want
|
// indicate that this is a tuple struct ctor, because downstream users will normally want
|
||||||
// the tuple struct definition, but without this there is no way for them to tell that
|
// the tuple struct definition, but without this there is no way for them to tell that
|
||||||
|
@ -700,8 +708,10 @@ fn encode_info_for_associated_const<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||||
encode_bounds_and_type_for_item(rbml_w, ecx, index,
|
encode_bounds_and_type_for_item(rbml_w, ecx, index,
|
||||||
ecx.local_id(associated_const.def_id));
|
ecx.local_id(associated_const.def_id));
|
||||||
|
|
||||||
let stab = stability::lookup(ecx.tcx, associated_const.def_id);
|
let stab = stability::lookup_stability(ecx.tcx, associated_const.def_id);
|
||||||
|
let depr = stability::lookup_deprecation(ecx.tcx, associated_const.def_id);
|
||||||
encode_stability(rbml_w, stab);
|
encode_stability(rbml_w, stab);
|
||||||
|
encode_deprecation(rbml_w, depr);
|
||||||
|
|
||||||
let elem = ast_map::PathName(associated_const.name);
|
let elem = ast_map::PathName(associated_const.name);
|
||||||
encode_path(rbml_w, impl_path.chain(Some(elem)));
|
encode_path(rbml_w, impl_path.chain(Some(elem)));
|
||||||
|
@ -735,8 +745,10 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||||
encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(parent_id));
|
encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(parent_id));
|
||||||
encode_item_sort(rbml_w, 'r');
|
encode_item_sort(rbml_w, 'r');
|
||||||
|
|
||||||
let stab = stability::lookup(ecx.tcx, m.def_id);
|
let stab = stability::lookup_stability(ecx.tcx, m.def_id);
|
||||||
|
let depr = stability::lookup_deprecation(ecx.tcx, m.def_id);
|
||||||
encode_stability(rbml_w, stab);
|
encode_stability(rbml_w, stab);
|
||||||
|
encode_deprecation(rbml_w, depr);
|
||||||
|
|
||||||
let m_node_id = ecx.local_id(m.def_id);
|
let m_node_id = ecx.local_id(m.def_id);
|
||||||
encode_bounds_and_type_for_item(rbml_w, ecx, index, m_node_id);
|
encode_bounds_and_type_for_item(rbml_w, ecx, index, m_node_id);
|
||||||
|
@ -789,8 +801,10 @@ fn encode_info_for_associated_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||||
encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(parent_id));
|
encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(parent_id));
|
||||||
encode_item_sort(rbml_w, 't');
|
encode_item_sort(rbml_w, 't');
|
||||||
|
|
||||||
let stab = stability::lookup(ecx.tcx, associated_type.def_id);
|
let stab = stability::lookup_stability(ecx.tcx, associated_type.def_id);
|
||||||
|
let depr = stability::lookup_deprecation(ecx.tcx, associated_type.def_id);
|
||||||
encode_stability(rbml_w, stab);
|
encode_stability(rbml_w, stab);
|
||||||
|
encode_deprecation(rbml_w, depr);
|
||||||
|
|
||||||
let elem = ast_map::PathName(associated_type.name);
|
let elem = ast_map::PathName(associated_type.name);
|
||||||
encode_path(rbml_w, impl_path.chain(Some(elem)));
|
encode_path(rbml_w, impl_path.chain(Some(elem)));
|
||||||
|
@ -891,6 +905,14 @@ fn encode_stability(rbml_w: &mut Encoder, stab_opt: Option<&attr::Stability>) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn encode_deprecation(rbml_w: &mut Encoder, depr_opt: Option<attr::Deprecation>) {
|
||||||
|
depr_opt.map(|depr| {
|
||||||
|
rbml_w.start_tag(tag_items_data_item_deprecation);
|
||||||
|
depr.encode(rbml_w).unwrap();
|
||||||
|
rbml_w.end_tag();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn encode_xrefs<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
fn encode_xrefs<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||||
rbml_w: &mut Encoder,
|
rbml_w: &mut Encoder,
|
||||||
xrefs: FnvHashMap<XRef<'tcx>, u32>)
|
xrefs: FnvHashMap<XRef<'tcx>, u32>)
|
||||||
|
@ -931,7 +953,8 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||||
tcx.sess.codemap().span_to_string(item.span));
|
tcx.sess.codemap().span_to_string(item.span));
|
||||||
|
|
||||||
let def_id = ecx.tcx.map.local_def_id(item.id);
|
let def_id = ecx.tcx.map.local_def_id(item.id);
|
||||||
let stab = stability::lookup(tcx, ecx.tcx.map.local_def_id(item.id));
|
let stab = stability::lookup_stability(tcx, ecx.tcx.map.local_def_id(item.id));
|
||||||
|
let depr = stability::lookup_deprecation(tcx, ecx.tcx.map.local_def_id(item.id));
|
||||||
|
|
||||||
match item.node {
|
match item.node {
|
||||||
hir::ItemStatic(_, m, _) => {
|
hir::ItemStatic(_, m, _) => {
|
||||||
|
@ -949,6 +972,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||||
encode_path(rbml_w, path);
|
encode_path(rbml_w, path);
|
||||||
encode_visibility(rbml_w, vis);
|
encode_visibility(rbml_w, vis);
|
||||||
encode_stability(rbml_w, stab);
|
encode_stability(rbml_w, stab);
|
||||||
|
encode_deprecation(rbml_w, depr);
|
||||||
encode_attributes(rbml_w, &item.attrs);
|
encode_attributes(rbml_w, &item.attrs);
|
||||||
rbml_w.end_tag();
|
rbml_w.end_tag();
|
||||||
}
|
}
|
||||||
|
@ -964,6 +988,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||||
encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
|
encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
|
||||||
encode_visibility(rbml_w, vis);
|
encode_visibility(rbml_w, vis);
|
||||||
encode_stability(rbml_w, stab);
|
encode_stability(rbml_w, stab);
|
||||||
|
encode_deprecation(rbml_w, depr);
|
||||||
rbml_w.end_tag();
|
rbml_w.end_tag();
|
||||||
}
|
}
|
||||||
hir::ItemFn(ref decl, _, constness, _, ref generics, _) => {
|
hir::ItemFn(ref decl, _, constness, _, ref generics, _) => {
|
||||||
|
@ -986,6 +1011,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||||
encode_constness(rbml_w, constness);
|
encode_constness(rbml_w, constness);
|
||||||
encode_visibility(rbml_w, vis);
|
encode_visibility(rbml_w, vis);
|
||||||
encode_stability(rbml_w, stab);
|
encode_stability(rbml_w, stab);
|
||||||
|
encode_deprecation(rbml_w, depr);
|
||||||
encode_method_argument_names(rbml_w, &**decl);
|
encode_method_argument_names(rbml_w, &**decl);
|
||||||
rbml_w.end_tag();
|
rbml_w.end_tag();
|
||||||
}
|
}
|
||||||
|
@ -1015,6 +1041,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
encode_visibility(rbml_w, vis);
|
encode_visibility(rbml_w, vis);
|
||||||
encode_stability(rbml_w, stab);
|
encode_stability(rbml_w, stab);
|
||||||
|
encode_deprecation(rbml_w, depr);
|
||||||
rbml_w.end_tag();
|
rbml_w.end_tag();
|
||||||
}
|
}
|
||||||
hir::ItemTy(..) => {
|
hir::ItemTy(..) => {
|
||||||
|
@ -1027,6 +1054,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||||
encode_path(rbml_w, path);
|
encode_path(rbml_w, path);
|
||||||
encode_visibility(rbml_w, vis);
|
encode_visibility(rbml_w, vis);
|
||||||
encode_stability(rbml_w, stab);
|
encode_stability(rbml_w, stab);
|
||||||
|
encode_deprecation(rbml_w, depr);
|
||||||
rbml_w.end_tag();
|
rbml_w.end_tag();
|
||||||
}
|
}
|
||||||
hir::ItemEnum(ref enum_definition, _) => {
|
hir::ItemEnum(ref enum_definition, _) => {
|
||||||
|
@ -1051,6 +1079,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||||
|
|
||||||
encode_visibility(rbml_w, vis);
|
encode_visibility(rbml_w, vis);
|
||||||
encode_stability(rbml_w, stab);
|
encode_stability(rbml_w, stab);
|
||||||
|
encode_deprecation(rbml_w, depr);
|
||||||
rbml_w.end_tag();
|
rbml_w.end_tag();
|
||||||
|
|
||||||
encode_enum_variant_info(ecx,
|
encode_enum_variant_info(ecx,
|
||||||
|
@ -1077,6 +1106,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||||
encode_attributes(rbml_w, &item.attrs);
|
encode_attributes(rbml_w, &item.attrs);
|
||||||
encode_path(rbml_w, path.clone());
|
encode_path(rbml_w, path.clone());
|
||||||
encode_stability(rbml_w, stab);
|
encode_stability(rbml_w, stab);
|
||||||
|
encode_deprecation(rbml_w, depr);
|
||||||
encode_visibility(rbml_w, vis);
|
encode_visibility(rbml_w, vis);
|
||||||
encode_repr_attrs(rbml_w, ecx, &item.attrs);
|
encode_repr_attrs(rbml_w, ecx, &item.attrs);
|
||||||
|
|
||||||
|
@ -1167,6 +1197,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
encode_path(rbml_w, path.clone());
|
encode_path(rbml_w, path.clone());
|
||||||
encode_stability(rbml_w, stab);
|
encode_stability(rbml_w, stab);
|
||||||
|
encode_deprecation(rbml_w, depr);
|
||||||
rbml_w.end_tag();
|
rbml_w.end_tag();
|
||||||
|
|
||||||
// Iterate down the trait items, emitting them. We rely on the
|
// Iterate down the trait items, emitting them. We rely on the
|
||||||
|
@ -1236,6 +1267,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||||
encode_attributes(rbml_w, &item.attrs);
|
encode_attributes(rbml_w, &item.attrs);
|
||||||
encode_visibility(rbml_w, vis);
|
encode_visibility(rbml_w, vis);
|
||||||
encode_stability(rbml_w, stab);
|
encode_stability(rbml_w, stab);
|
||||||
|
encode_deprecation(rbml_w, depr);
|
||||||
for &method_def_id in tcx.trait_item_def_ids(def_id).iter() {
|
for &method_def_id in tcx.trait_item_def_ids(def_id).iter() {
|
||||||
rbml_w.start_tag(tag_item_trait_item);
|
rbml_w.start_tag(tag_item_trait_item);
|
||||||
match method_def_id {
|
match method_def_id {
|
||||||
|
@ -1274,8 +1306,10 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||||
|
|
||||||
encode_parent_item(rbml_w, def_id);
|
encode_parent_item(rbml_w, def_id);
|
||||||
|
|
||||||
let stab = stability::lookup(tcx, item_def_id.def_id());
|
let stab = stability::lookup_stability(tcx, item_def_id.def_id());
|
||||||
|
let depr = stability::lookup_deprecation(tcx, item_def_id.def_id());
|
||||||
encode_stability(rbml_w, stab);
|
encode_stability(rbml_w, stab);
|
||||||
|
encode_deprecation(rbml_w, depr);
|
||||||
|
|
||||||
let trait_item_type =
|
let trait_item_type =
|
||||||
tcx.impl_or_trait_item(item_def_id.def_id());
|
tcx.impl_or_trait_item(item_def_id.def_id());
|
||||||
|
@ -1407,8 +1441,10 @@ fn encode_info_for_foreign_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||||
encode_inlined_item(ecx, rbml_w, InlinedItemRef::Foreign(nitem));
|
encode_inlined_item(ecx, rbml_w, InlinedItemRef::Foreign(nitem));
|
||||||
}
|
}
|
||||||
encode_attributes(rbml_w, &*nitem.attrs);
|
encode_attributes(rbml_w, &*nitem.attrs);
|
||||||
let stab = stability::lookup(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
|
let stab = stability::lookup_stability(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
|
||||||
|
let depr = stability::lookup_deprecation(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
|
||||||
encode_stability(rbml_w, stab);
|
encode_stability(rbml_w, stab);
|
||||||
|
encode_deprecation(rbml_w, depr);
|
||||||
encode_symbol(ecx, rbml_w, nitem.id);
|
encode_symbol(ecx, rbml_w, nitem.id);
|
||||||
encode_method_argument_names(rbml_w, &*fndecl);
|
encode_method_argument_names(rbml_w, &*fndecl);
|
||||||
}
|
}
|
||||||
|
@ -1420,8 +1456,10 @@ fn encode_info_for_foreign_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
encode_bounds_and_type_for_item(rbml_w, ecx, index, nitem.id);
|
encode_bounds_and_type_for_item(rbml_w, ecx, index, nitem.id);
|
||||||
encode_attributes(rbml_w, &*nitem.attrs);
|
encode_attributes(rbml_w, &*nitem.attrs);
|
||||||
let stab = stability::lookup(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
|
let stab = stability::lookup_stability(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
|
||||||
|
let depr = stability::lookup_deprecation(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
|
||||||
encode_stability(rbml_w, stab);
|
encode_stability(rbml_w, stab);
|
||||||
|
encode_deprecation(rbml_w, depr);
|
||||||
encode_symbol(ecx, rbml_w, nitem.id);
|
encode_symbol(ecx, rbml_w, nitem.id);
|
||||||
encode_name(rbml_w, nitem.name);
|
encode_name(rbml_w, nitem.name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,7 +120,7 @@ fn try_inline_def(cx: &DocContext, tcx: &ty::ctxt,
|
||||||
attrs: load_attrs(cx, tcx, did),
|
attrs: load_attrs(cx, tcx, did),
|
||||||
inner: inner,
|
inner: inner,
|
||||||
visibility: Some(hir::Public),
|
visibility: Some(hir::Public),
|
||||||
stability: stability::lookup(tcx, did).clean(cx),
|
stability: stability::lookup_stability(tcx, did).clean(cx),
|
||||||
def_id: did,
|
def_id: did,
|
||||||
});
|
});
|
||||||
Some(ret)
|
Some(ret)
|
||||||
|
@ -303,7 +303,7 @@ pub fn build_impl(cx: &DocContext,
|
||||||
name: None,
|
name: None,
|
||||||
attrs: attrs,
|
attrs: attrs,
|
||||||
visibility: Some(hir::Inherited),
|
visibility: Some(hir::Inherited),
|
||||||
stability: stability::lookup(tcx, did).clean(cx),
|
stability: stability::lookup_stability(tcx, did).clean(cx),
|
||||||
def_id: did,
|
def_id: did,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -333,7 +333,7 @@ pub fn build_impl(cx: &DocContext,
|
||||||
source: clean::Span::empty(),
|
source: clean::Span::empty(),
|
||||||
attrs: vec![],
|
attrs: vec![],
|
||||||
visibility: None,
|
visibility: None,
|
||||||
stability: stability::lookup(tcx, did).clean(cx),
|
stability: stability::lookup_stability(tcx, did).clean(cx),
|
||||||
def_id: did
|
def_id: did
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -381,7 +381,7 @@ pub fn build_impl(cx: &DocContext,
|
||||||
source: clean::Span::empty(),
|
source: clean::Span::empty(),
|
||||||
attrs: vec![],
|
attrs: vec![],
|
||||||
visibility: None,
|
visibility: None,
|
||||||
stability: stability::lookup(tcx, did).clean(cx),
|
stability: stability::lookup_stability(tcx, did).clean(cx),
|
||||||
def_id: did
|
def_id: did
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -414,7 +414,7 @@ pub fn build_impl(cx: &DocContext,
|
||||||
name: None,
|
name: None,
|
||||||
attrs: attrs,
|
attrs: attrs,
|
||||||
visibility: Some(hir::Inherited),
|
visibility: Some(hir::Inherited),
|
||||||
stability: stability::lookup(tcx, did).clean(cx),
|
stability: stability::lookup_stability(tcx, did).clean(cx),
|
||||||
def_id: did,
|
def_id: did,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ mod simplify;
|
||||||
|
|
||||||
// extract the stability index for a node from tcx, if possible
|
// extract the stability index for a node from tcx, if possible
|
||||||
fn get_stability(cx: &DocContext, def_id: DefId) -> Option<Stability> {
|
fn get_stability(cx: &DocContext, def_id: DefId) -> Option<Stability> {
|
||||||
cx.tcx_opt().and_then(|tcx| stability::lookup(tcx, def_id)).clean(cx)
|
cx.tcx_opt().and_then(|tcx| stability::lookup_stability(tcx, def_id)).clean(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Clean<T> {
|
pub trait Clean<T> {
|
||||||
|
@ -2689,12 +2689,12 @@ impl Clean<Stability> for attr::Stability {
|
||||||
attr::Stable {ref since} => since.to_string(),
|
attr::Stable {ref since} => since.to_string(),
|
||||||
_ => "".to_string(),
|
_ => "".to_string(),
|
||||||
},
|
},
|
||||||
deprecated_since: match self.depr {
|
deprecated_since: match self.rustc_depr {
|
||||||
Some(attr::Deprecation {ref since, ..}) => since.to_string(),
|
Some(attr::RustcDeprecation {ref since, ..}) => since.to_string(),
|
||||||
_=> "".to_string(),
|
_=> "".to_string(),
|
||||||
},
|
},
|
||||||
reason: {
|
reason: {
|
||||||
if let Some(ref depr) = self.depr {
|
if let Some(ref depr) = self.rustc_depr {
|
||||||
depr.reason.to_string()
|
depr.reason.to_string()
|
||||||
} else if let attr::Unstable {reason: Some(ref reason), ..} = self.level {
|
} else if let attr::Unstable {reason: Some(ref reason), ..} = self.level {
|
||||||
reason.to_string()
|
reason.to_string()
|
||||||
|
@ -2782,7 +2782,7 @@ impl<'tcx> Clean<Item> for ty::AssociatedType<'tcx> {
|
||||||
inner: AssociatedTypeItem(bounds, self.ty.clean(cx)),
|
inner: AssociatedTypeItem(bounds, self.ty.clean(cx)),
|
||||||
visibility: self.vis.clean(cx),
|
visibility: self.vis.clean(cx),
|
||||||
def_id: self.def_id,
|
def_id: self.def_id,
|
||||||
stability: stability::lookup(cx.tcx(), self.def_id).clean(cx),
|
stability: stability::lookup_stability(cx.tcx(), self.def_id).clean(cx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||||
fn stability(&self, id: ast::NodeId) -> Option<attr::Stability> {
|
fn stability(&self, id: ast::NodeId) -> Option<attr::Stability> {
|
||||||
self.cx.tcx_opt().and_then(|tcx| {
|
self.cx.tcx_opt().and_then(|tcx| {
|
||||||
self.cx.map.opt_local_def_id(id)
|
self.cx.map.opt_local_def_id(id)
|
||||||
.and_then(|def_id| stability::lookup(tcx, def_id))
|
.and_then(|def_id| stability::lookup_stability(tcx, def_id))
|
||||||
.cloned()
|
.cloned()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -398,7 +398,7 @@ pub fn cfg_matches<T: CfgDiag>(cfgs: &[P<MetaItem>],
|
||||||
pub struct Stability {
|
pub struct Stability {
|
||||||
pub level: StabilityLevel,
|
pub level: StabilityLevel,
|
||||||
pub feature: InternedString,
|
pub feature: InternedString,
|
||||||
pub depr: Option<Deprecation>,
|
pub rustc_depr: Option<RustcDeprecation>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The available stability levels.
|
/// The available stability levels.
|
||||||
|
@ -410,11 +410,17 @@ pub enum StabilityLevel {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
|
#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
|
||||||
pub struct Deprecation {
|
pub struct RustcDeprecation {
|
||||||
pub since: InternedString,
|
pub since: InternedString,
|
||||||
pub reason: InternedString,
|
pub reason: InternedString,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
|
||||||
|
pub struct Deprecation {
|
||||||
|
pub since: Option<InternedString>,
|
||||||
|
pub note: Option<InternedString>,
|
||||||
|
}
|
||||||
|
|
||||||
impl StabilityLevel {
|
impl StabilityLevel {
|
||||||
pub fn is_unstable(&self) -> bool { if let Unstable {..} = *self { true } else { false }}
|
pub fn is_unstable(&self) -> bool { if let Unstable {..} = *self { true } else { false }}
|
||||||
pub fn is_stable(&self) -> bool { if let Stable {..} = *self { true } else { false }}
|
pub fn is_stable(&self) -> bool { if let Stable {..} = *self { true } else { false }}
|
||||||
|
@ -427,7 +433,7 @@ fn find_stability_generic<'a, I>(diagnostic: &SpanHandler,
|
||||||
where I: Iterator<Item = &'a Attribute>
|
where I: Iterator<Item = &'a Attribute>
|
||||||
{
|
{
|
||||||
let mut stab: Option<Stability> = None;
|
let mut stab: Option<Stability> = None;
|
||||||
let mut depr: Option<Deprecation> = None;
|
let mut rustc_depr: Option<RustcDeprecation> = None;
|
||||||
|
|
||||||
'outer: for attr in attrs_iter {
|
'outer: for attr in attrs_iter {
|
||||||
let tag = attr.name();
|
let tag = attr.name();
|
||||||
|
@ -456,7 +462,7 @@ fn find_stability_generic<'a, I>(diagnostic: &SpanHandler,
|
||||||
|
|
||||||
match tag {
|
match tag {
|
||||||
"rustc_deprecated" => {
|
"rustc_deprecated" => {
|
||||||
if depr.is_some() {
|
if rustc_depr.is_some() {
|
||||||
diagnostic.span_err(item_sp, "multiple rustc_deprecated attributes");
|
diagnostic.span_err(item_sp, "multiple rustc_deprecated attributes");
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -477,7 +483,7 @@ fn find_stability_generic<'a, I>(diagnostic: &SpanHandler,
|
||||||
|
|
||||||
match (since, reason) {
|
match (since, reason) {
|
||||||
(Some(since), Some(reason)) => {
|
(Some(since), Some(reason)) => {
|
||||||
depr = Some(Deprecation {
|
rustc_depr = Some(RustcDeprecation {
|
||||||
since: since,
|
since: since,
|
||||||
reason: reason,
|
reason: reason,
|
||||||
})
|
})
|
||||||
|
@ -529,7 +535,7 @@ fn find_stability_generic<'a, I>(diagnostic: &SpanHandler,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
feature: feature,
|
feature: feature,
|
||||||
depr: None,
|
rustc_depr: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
(None, _, _) => {
|
(None, _, _) => {
|
||||||
|
@ -569,7 +575,7 @@ fn find_stability_generic<'a, I>(diagnostic: &SpanHandler,
|
||||||
since: since,
|
since: since,
|
||||||
},
|
},
|
||||||
feature: feature,
|
feature: feature,
|
||||||
depr: None,
|
rustc_depr: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
(None, _) => {
|
(None, _) => {
|
||||||
|
@ -591,12 +597,12 @@ fn find_stability_generic<'a, I>(diagnostic: &SpanHandler,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge the deprecation info into the stability info
|
// Merge the deprecation info into the stability info
|
||||||
if let Some(depr) = depr {
|
if let Some(rustc_depr) = rustc_depr {
|
||||||
if let Some(ref mut stab) = stab {
|
if let Some(ref mut stab) = stab {
|
||||||
if let Unstable {reason: ref mut reason @ None, ..} = stab.level {
|
if let Unstable {reason: ref mut reason @ None, ..} = stab.level {
|
||||||
*reason = Some(depr.reason.clone())
|
*reason = Some(rustc_depr.reason.clone())
|
||||||
}
|
}
|
||||||
stab.depr = Some(depr);
|
stab.rustc_depr = Some(rustc_depr);
|
||||||
} else {
|
} else {
|
||||||
diagnostic.span_err(item_sp, "rustc_deprecated attribute must be paired with \
|
diagnostic.span_err(item_sp, "rustc_deprecated attribute must be paired with \
|
||||||
either stable or unstable attribute");
|
either stable or unstable attribute");
|
||||||
|
@ -606,12 +612,77 @@ fn find_stability_generic<'a, I>(diagnostic: &SpanHandler,
|
||||||
stab
|
stab
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn find_deprecation_generic<'a, I>(diagnostic: &SpanHandler,
|
||||||
|
attrs_iter: I,
|
||||||
|
item_sp: Span)
|
||||||
|
-> Option<Deprecation>
|
||||||
|
where I: Iterator<Item = &'a Attribute>
|
||||||
|
{
|
||||||
|
let mut depr: Option<Deprecation> = None;
|
||||||
|
|
||||||
|
'outer: for attr in attrs_iter {
|
||||||
|
if attr.name() != "deprecated" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
mark_used(attr);
|
||||||
|
|
||||||
|
if depr.is_some() {
|
||||||
|
diagnostic.span_err(item_sp, "multiple deprecated attributes");
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
depr = if let Some(metas) = attr.meta_item_list() {
|
||||||
|
let get = |meta: &MetaItem, item: &mut Option<InternedString>| {
|
||||||
|
if item.is_some() {
|
||||||
|
diagnostic.span_err(meta.span, &format!("multiple '{}' items",
|
||||||
|
meta.name()));
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if let Some(v) = meta.value_str() {
|
||||||
|
*item = Some(v);
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
diagnostic.span_err(meta.span, "incorrect meta item");
|
||||||
|
false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut since = None;
|
||||||
|
let mut note = None;
|
||||||
|
for meta in metas {
|
||||||
|
match &*meta.name() {
|
||||||
|
"since" => if !get(meta, &mut since) { continue 'outer },
|
||||||
|
"note" => if !get(meta, &mut note) { continue 'outer },
|
||||||
|
_ => {
|
||||||
|
diagnostic.span_err(meta.span, &format!("unknown meta item '{}'",
|
||||||
|
meta.name()));
|
||||||
|
continue 'outer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(Deprecation {since: since, note: note})
|
||||||
|
} else {
|
||||||
|
Some(Deprecation{since: None, note: None})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
depr
|
||||||
|
}
|
||||||
|
|
||||||
/// Find the first stability attribute. `None` if none exists.
|
/// Find the first stability attribute. `None` if none exists.
|
||||||
pub fn find_stability(diagnostic: &SpanHandler, attrs: &[Attribute],
|
pub fn find_stability(diagnostic: &SpanHandler, attrs: &[Attribute],
|
||||||
item_sp: Span) -> Option<Stability> {
|
item_sp: Span) -> Option<Stability> {
|
||||||
find_stability_generic(diagnostic, attrs.iter(), item_sp)
|
find_stability_generic(diagnostic, attrs.iter(), item_sp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Find the deprecation attribute. `None` if none exists.
|
||||||
|
pub fn find_deprecation(diagnostic: &SpanHandler, attrs: &[Attribute],
|
||||||
|
item_sp: Span) -> Option<Deprecation> {
|
||||||
|
find_deprecation_generic(diagnostic, attrs.iter(), item_sp)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn require_unique_names(diagnostic: &SpanHandler, metas: &[P<MetaItem>]) {
|
pub fn require_unique_names(diagnostic: &SpanHandler, metas: &[P<MetaItem>]) {
|
||||||
let mut set = HashSet::new();
|
let mut set = HashSet::new();
|
||||||
for meta in metas {
|
for meta in metas {
|
||||||
|
|
|
@ -230,6 +230,9 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option<u32>, Status
|
||||||
|
|
||||||
// Allow attributes on expressions and non-item statements
|
// Allow attributes on expressions and non-item statements
|
||||||
("stmt_expr_attributes", "1.6.0", Some(15701), Active),
|
("stmt_expr_attributes", "1.6.0", Some(15701), Active),
|
||||||
|
|
||||||
|
// Allows `#[deprecated]` attribute
|
||||||
|
("deprecated", "1.6.0", Some(29935), Active),
|
||||||
];
|
];
|
||||||
// (changing above list without updating src/doc/reference.md makes @cmr sad)
|
// (changing above list without updating src/doc/reference.md makes @cmr sad)
|
||||||
|
|
||||||
|
@ -377,6 +380,7 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGat
|
||||||
("must_use", Whitelisted, Ungated),
|
("must_use", Whitelisted, Ungated),
|
||||||
("stable", Whitelisted, Ungated),
|
("stable", Whitelisted, Ungated),
|
||||||
("unstable", Whitelisted, Ungated),
|
("unstable", Whitelisted, Ungated),
|
||||||
|
("deprecated", Whitelisted, Ungated),
|
||||||
|
|
||||||
("rustc_paren_sugar", Normal, Gated("unboxed_closures",
|
("rustc_paren_sugar", Normal, Gated("unboxed_closures",
|
||||||
"unboxed_closures are still evolving")),
|
"unboxed_closures are still evolving")),
|
||||||
|
@ -539,6 +543,7 @@ pub struct Features {
|
||||||
pub braced_empty_structs: bool,
|
pub braced_empty_structs: bool,
|
||||||
pub staged_api: bool,
|
pub staged_api: bool,
|
||||||
pub stmt_expr_attributes: bool,
|
pub stmt_expr_attributes: bool,
|
||||||
|
pub deprecated: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Features {
|
impl Features {
|
||||||
|
@ -573,6 +578,7 @@ impl Features {
|
||||||
braced_empty_structs: false,
|
braced_empty_structs: false,
|
||||||
staged_api: false,
|
staged_api: false,
|
||||||
stmt_expr_attributes: false,
|
stmt_expr_attributes: false,
|
||||||
|
deprecated: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1151,6 +1157,7 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler,
|
||||||
braced_empty_structs: cx.has_feature("braced_empty_structs"),
|
braced_empty_structs: cx.has_feature("braced_empty_structs"),
|
||||||
staged_api: cx.has_feature("staged_api"),
|
staged_api: cx.has_feature("staged_api"),
|
||||||
stmt_expr_attributes: cx.has_feature("stmt_expr_attributes"),
|
stmt_expr_attributes: cx.has_feature("stmt_expr_attributes"),
|
||||||
|
deprecated: cx.has_feature("deprecated"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
87
src/test/auxiliary/deprecation-lint.rs
Normal file
87
src/test/auxiliary/deprecation-lint.rs
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![feature(deprecated)]
|
||||||
|
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
pub fn deprecated() {}
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
pub fn deprecated_text() {}
|
||||||
|
|
||||||
|
pub struct MethodTester;
|
||||||
|
|
||||||
|
impl MethodTester {
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
pub fn method_deprecated(&self) {}
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
pub fn method_deprecated_text(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Trait {
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
fn trait_deprecated(&self) {}
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
fn trait_deprecated_text(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Trait for MethodTester {}
|
||||||
|
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
pub struct DeprecatedStruct {
|
||||||
|
pub i: isize
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
pub struct DeprecatedUnitStruct;
|
||||||
|
|
||||||
|
pub enum Enum {
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
DeprecatedVariant,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
pub struct DeprecatedTupleStruct(pub isize);
|
||||||
|
|
||||||
|
pub struct Stable {
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
pub override2: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Stable2(pub u8, pub u8, #[deprecated(since = "1.0.0", note = "text")] pub u8);
|
||||||
|
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
pub struct Deprecated {
|
||||||
|
pub inherit: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
pub struct Deprecated2(pub u8,
|
||||||
|
pub u8,
|
||||||
|
pub u8);
|
||||||
|
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
pub mod deprecated_mod {
|
||||||
|
pub fn deprecated() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! macro_test {
|
||||||
|
() => (deprecated());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! macro_test_arg {
|
||||||
|
($func:expr) => ($func);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! macro_test_arg_nested {
|
||||||
|
($func:ident) => (macro_test_arg!($func()));
|
||||||
|
}
|
18
src/test/compile-fail/deprecation-in-staged-api.rs
Normal file
18
src/test/compile-fail/deprecation-in-staged-api.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// #[deprecated] can't be used in staged api
|
||||||
|
|
||||||
|
#![feature(deprecated, staged_api)]
|
||||||
|
|
||||||
|
#![stable(feature = "test_feature", since = "1.0.0")]
|
||||||
|
|
||||||
|
#[deprecated]
|
||||||
|
fn main() { } //~ERROR `#[deprecated]` cannot be used in staged api
|
23
src/test/compile-fail/deprecation-lint-2.rs
Normal file
23
src/test/compile-fail/deprecation-lint-2.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// aux-build:deprecation-lint.rs
|
||||||
|
// error-pattern: use of deprecated item
|
||||||
|
|
||||||
|
#![deny(deprecated)]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate deprecation_lint;
|
||||||
|
|
||||||
|
use deprecation_lint::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
macro_test!();
|
||||||
|
}
|
24
src/test/compile-fail/deprecation-lint-3.rs
Normal file
24
src/test/compile-fail/deprecation-lint-3.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// aux-build:deprecation-lint.rs
|
||||||
|
// error-pattern: use of deprecated item
|
||||||
|
|
||||||
|
#![deny(deprecated)]
|
||||||
|
#![allow(warnings)]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate deprecation_lint;
|
||||||
|
|
||||||
|
use deprecation_lint::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
macro_test_arg_nested!(deprecated_text);
|
||||||
|
}
|
384
src/test/compile-fail/deprecation-lint.rs
Normal file
384
src/test/compile-fail/deprecation-lint.rs
Normal file
|
@ -0,0 +1,384 @@
|
||||||
|
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// aux-build:deprecation-lint.rs
|
||||||
|
|
||||||
|
#![feature(deprecated)]
|
||||||
|
|
||||||
|
#![deny(deprecated)]
|
||||||
|
#![allow(warnings)]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate deprecation_lint;
|
||||||
|
|
||||||
|
mod cross_crate {
|
||||||
|
use deprecation_lint::*;
|
||||||
|
|
||||||
|
fn test() {
|
||||||
|
type Foo = MethodTester;
|
||||||
|
let foo = MethodTester;
|
||||||
|
|
||||||
|
deprecated(); //~ ERROR use of deprecated item
|
||||||
|
foo.method_deprecated(); //~ ERROR use of deprecated item
|
||||||
|
Foo::method_deprecated(&foo); //~ ERROR use of deprecated item
|
||||||
|
<Foo>::method_deprecated(&foo); //~ ERROR use of deprecated item
|
||||||
|
foo.trait_deprecated(); //~ ERROR use of deprecated item
|
||||||
|
Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
|
||||||
|
<Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
|
||||||
|
<Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item
|
||||||
|
|
||||||
|
deprecated_text(); //~ ERROR use of deprecated item: text
|
||||||
|
foo.method_deprecated_text(); //~ ERROR use of deprecated item: text
|
||||||
|
Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text
|
||||||
|
<Foo>::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text
|
||||||
|
foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
|
||||||
|
Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
|
||||||
|
<Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
|
||||||
|
<Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
|
||||||
|
|
||||||
|
let _ = DeprecatedStruct { //~ ERROR use of deprecated item
|
||||||
|
i: 0 //~ ERROR use of deprecated item
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated item
|
||||||
|
|
||||||
|
let _ = Enum::DeprecatedVariant; //~ ERROR use of deprecated item
|
||||||
|
|
||||||
|
let _ = DeprecatedTupleStruct (1); //~ ERROR use of deprecated item
|
||||||
|
|
||||||
|
// At the moment, the lint checker only checks stability in
|
||||||
|
// in the arguments of macros.
|
||||||
|
// Eventually, we will want to lint the contents of the
|
||||||
|
// macro in the module *defining* it. Also, stability levels
|
||||||
|
// on macros themselves are not yet linted.
|
||||||
|
macro_test_arg!(deprecated_text()); //~ ERROR use of deprecated item: text
|
||||||
|
macro_test_arg!(macro_test_arg!(deprecated_text())); //~ ERROR use of deprecated item: text
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_method_param<Foo: Trait>(foo: Foo) {
|
||||||
|
foo.trait_deprecated(); //~ ERROR use of deprecated item
|
||||||
|
Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
|
||||||
|
<Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
|
||||||
|
<Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item
|
||||||
|
foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
|
||||||
|
Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
|
||||||
|
<Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
|
||||||
|
<Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_method_object(foo: &Trait) {
|
||||||
|
foo.trait_deprecated(); //~ ERROR use of deprecated item
|
||||||
|
foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn foo() {
|
||||||
|
let x = Stable {
|
||||||
|
override2: 3,
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = x.override2;
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
|
||||||
|
let Stable {
|
||||||
|
override2: _
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
} = x;
|
||||||
|
// all fine
|
||||||
|
let Stable { .. } = x;
|
||||||
|
|
||||||
|
let x = Stable2(1, 2, 3);
|
||||||
|
|
||||||
|
let _ = x.2;
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
|
||||||
|
let Stable2(_,
|
||||||
|
_,
|
||||||
|
_)
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
= x;
|
||||||
|
// all fine
|
||||||
|
let Stable2(..) = x;
|
||||||
|
|
||||||
|
let x = Deprecated {
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
inherit: 1,
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = x.inherit;
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
|
||||||
|
let Deprecated {
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
inherit: _,
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
} = x;
|
||||||
|
|
||||||
|
let Deprecated
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
{ .. } = x;
|
||||||
|
|
||||||
|
let x = Deprecated2(1, 2, 3);
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
|
||||||
|
let _ = x.0;
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
let _ = x.1;
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
let _ = x.2;
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
|
||||||
|
let Deprecated2
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
(_,
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
_,
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
_)
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
= x;
|
||||||
|
let Deprecated2
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
// the patterns are all fine:
|
||||||
|
(..) = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod inheritance {
|
||||||
|
use deprecation_lint::*;
|
||||||
|
|
||||||
|
fn test_inheritance() {
|
||||||
|
deprecated_mod::deprecated(); //~ ERROR use of deprecated item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod this_crate {
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
pub fn deprecated() {}
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
pub fn deprecated_text() {}
|
||||||
|
|
||||||
|
pub struct MethodTester;
|
||||||
|
|
||||||
|
impl MethodTester {
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
pub fn method_deprecated(&self) {}
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
pub fn method_deprecated_text(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Trait {
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
fn trait_deprecated(&self) {}
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
fn trait_deprecated_text(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Trait for MethodTester {}
|
||||||
|
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
pub struct DeprecatedStruct {
|
||||||
|
i: isize
|
||||||
|
}
|
||||||
|
pub struct UnstableStruct {
|
||||||
|
i: isize
|
||||||
|
}
|
||||||
|
pub struct StableStruct {
|
||||||
|
i: isize
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
pub struct DeprecatedUnitStruct;
|
||||||
|
|
||||||
|
pub enum Enum {
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
DeprecatedVariant,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
pub struct DeprecatedTupleStruct(isize);
|
||||||
|
|
||||||
|
fn test() {
|
||||||
|
// Only the deprecated cases of the following should generate
|
||||||
|
// errors, because other stability attributes now have meaning
|
||||||
|
// only *across* crates, not within a single crate.
|
||||||
|
|
||||||
|
type Foo = MethodTester;
|
||||||
|
let foo = MethodTester;
|
||||||
|
|
||||||
|
deprecated(); //~ ERROR use of deprecated item
|
||||||
|
foo.method_deprecated(); //~ ERROR use of deprecated item
|
||||||
|
Foo::method_deprecated(&foo); //~ ERROR use of deprecated item
|
||||||
|
<Foo>::method_deprecated(&foo); //~ ERROR use of deprecated item
|
||||||
|
foo.trait_deprecated(); //~ ERROR use of deprecated item
|
||||||
|
Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
|
||||||
|
<Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
|
||||||
|
<Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item
|
||||||
|
|
||||||
|
deprecated_text(); //~ ERROR use of deprecated item: text
|
||||||
|
foo.method_deprecated_text(); //~ ERROR use of deprecated item: text
|
||||||
|
Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text
|
||||||
|
<Foo>::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text
|
||||||
|
foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
|
||||||
|
Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
|
||||||
|
<Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
|
||||||
|
<Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
|
||||||
|
|
||||||
|
let _ = DeprecatedStruct {
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
i: 0 //~ ERROR use of deprecated item
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated item
|
||||||
|
|
||||||
|
let _ = Enum::DeprecatedVariant; //~ ERROR use of deprecated item
|
||||||
|
|
||||||
|
let _ = DeprecatedTupleStruct (1); //~ ERROR use of deprecated item
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_method_param<Foo: Trait>(foo: Foo) {
|
||||||
|
foo.trait_deprecated(); //~ ERROR use of deprecated item
|
||||||
|
Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
|
||||||
|
<Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
|
||||||
|
<Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item
|
||||||
|
foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
|
||||||
|
Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
|
||||||
|
<Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
|
||||||
|
<Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_method_object(foo: &Trait) {
|
||||||
|
foo.trait_deprecated(); //~ ERROR use of deprecated item
|
||||||
|
foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
fn test_fn_body() {
|
||||||
|
fn fn_in_body() {}
|
||||||
|
fn_in_body(); //~ ERROR use of deprecated item: text
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MethodTester {
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
fn test_method_body(&self) {
|
||||||
|
fn fn_in_body() {}
|
||||||
|
fn_in_body(); //~ ERROR use of deprecated item: text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
pub trait DeprecatedTrait {
|
||||||
|
fn dummy(&self) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S;
|
||||||
|
|
||||||
|
impl DeprecatedTrait for S { } //~ ERROR use of deprecated item
|
||||||
|
|
||||||
|
trait LocalTrait : DeprecatedTrait { } //~ ERROR use of deprecated item
|
||||||
|
}
|
||||||
|
|
||||||
|
mod this_crate2 {
|
||||||
|
struct Stable {
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
override2: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Stable2(u8,
|
||||||
|
u8,
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")] u8);
|
||||||
|
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
struct Deprecated {
|
||||||
|
inherit: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deprecated(since = "1.0.0", note = "text")]
|
||||||
|
struct Deprecated2(u8,
|
||||||
|
u8,
|
||||||
|
u8);
|
||||||
|
|
||||||
|
pub fn foo() {
|
||||||
|
let x = Stable {
|
||||||
|
override2: 3,
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = x.override2;
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
|
||||||
|
let Stable {
|
||||||
|
override2: _
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
} = x;
|
||||||
|
// all fine
|
||||||
|
let Stable { .. } = x;
|
||||||
|
|
||||||
|
let x = Stable2(1, 2, 3);
|
||||||
|
|
||||||
|
let _ = x.2;
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
|
||||||
|
let Stable2(_,
|
||||||
|
_,
|
||||||
|
_)
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
= x;
|
||||||
|
// all fine
|
||||||
|
let Stable2(..) = x;
|
||||||
|
|
||||||
|
let x = Deprecated {
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
inherit: 1,
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = x.inherit;
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
|
||||||
|
let Deprecated {
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
inherit: _,
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
} = x;
|
||||||
|
|
||||||
|
let Deprecated
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
// the patterns are all fine:
|
||||||
|
{ .. } = x;
|
||||||
|
|
||||||
|
let x = Deprecated2(1, 2, 3);
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
|
||||||
|
let _ = x.0;
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
let _ = x.1;
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
let _ = x.2;
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
|
||||||
|
let Deprecated2
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
(_,
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
_,
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
_)
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
= x;
|
||||||
|
let Deprecated2
|
||||||
|
//~^ ERROR use of deprecated item
|
||||||
|
// the patterns are all fine:
|
||||||
|
(..) = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
39
src/test/compile-fail/deprecation-sanity.rs
Normal file
39
src/test/compile-fail/deprecation-sanity.rs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// Various checks that deprecation attributes are used correctly
|
||||||
|
|
||||||
|
#![feature(deprecated)]
|
||||||
|
|
||||||
|
mod bogus_attribute_types_1 {
|
||||||
|
#[deprecated(since = "a", note = "a", reason)] //~ ERROR unknown meta item 'reason'
|
||||||
|
fn f1() { }
|
||||||
|
|
||||||
|
#[deprecated(since = "a", note)] //~ ERROR incorrect meta item
|
||||||
|
fn f2() { }
|
||||||
|
|
||||||
|
#[deprecated(since, note = "a")] //~ ERROR incorrect meta item
|
||||||
|
fn f3() { }
|
||||||
|
|
||||||
|
#[deprecated(since = "a", note(b))] //~ ERROR incorrect meta item
|
||||||
|
fn f5() { }
|
||||||
|
|
||||||
|
#[deprecated(since(b), note = "a")] //~ ERROR incorrect meta item
|
||||||
|
fn f6() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deprecated(since = "a", note = "b")]
|
||||||
|
#[deprecated(since = "a", note = "b")]
|
||||||
|
fn multiple1() { } //~ ERROR multiple deprecated attributes
|
||||||
|
|
||||||
|
#[deprecated(since = "a", since = "b", note = "c")] //~ ERROR multiple 'since' items
|
||||||
|
fn f1() { }
|
||||||
|
|
||||||
|
fn main() { }
|
Loading…
Add table
Add a link
Reference in a new issue