Implement #[deprecated]
attribute (RFC 1270)
This commit is contained in:
parent
45a73c8c0c
commit
e3ed7b0501
@ -2390,6 +2390,8 @@ The currently implemented features of the reference compiler are:
|
||||
* - `stmt_expr_attributes` - Allows attributes on expressions and
|
||||
non-item statements.
|
||||
|
||||
* - `deprecated` - Allows using the `#[deprecated]` attribute.
|
||||
|
||||
If a feature is promoted to a language feature, then all existing programs will
|
||||
start to receive compilation warnings about `#![feature]` directives which enabled
|
||||
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 {
|
||||
// item info
|
||||
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)
|
||||
-> ty::ClosureKind;
|
||||
fn closure_ty(&self, tcx: &ty::ctxt<'tcx>, def_id: DefId)
|
||||
@ -292,6 +293,7 @@ pub struct DummyCrateStore;
|
||||
impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
|
||||
// item info
|
||||
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)
|
||||
-> ty::ClosureKind { unimplemented!() }
|
||||
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::{NodeId, Attribute};
|
||||
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 rustc_front::hir;
|
||||
@ -61,7 +61,8 @@ enum AnnotationKind {
|
||||
pub struct Index<'tcx> {
|
||||
/// This is mostly a cache, except the stabilities of local items
|
||||
/// 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.
|
||||
staged_api: FnvHashMap<ast::CrateNum, bool>
|
||||
@ -71,7 +72,8 @@ pub struct Index<'tcx> {
|
||||
struct Annotator<'a, 'tcx: 'a> {
|
||||
tcx: &'a ty::ctxt<'tcx>,
|
||||
index: &'a mut Index<'tcx>,
|
||||
parent: Option<&'tcx Stability>,
|
||||
parent_stab: Option<&'tcx Stability>,
|
||||
parent_depr: Option<Deprecation>,
|
||||
access_levels: &'a AccessLevels,
|
||||
in_trait_impl: 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 {
|
||||
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(),
|
||||
attrs, item_sp) {
|
||||
// Error if prohibited, or can't inherit anything from a container
|
||||
if kind == AnnotationKind::Prohibited ||
|
||||
(kind == AnnotationKind::Container &&
|
||||
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");
|
||||
}
|
||||
|
||||
debug!("annotate: found {:?}", stab);
|
||||
// If parent is deprecated and we're not, inherit this by merging
|
||||
// deprecated_since and its reason.
|
||||
if let Some(parent_stab) = self.parent {
|
||||
if parent_stab.depr.is_some() && stab.depr.is_none() {
|
||||
stab.depr = parent_stab.depr.clone()
|
||||
if let Some(parent_stab) = self.parent_stab {
|
||||
if parent_stab.rustc_depr.is_some() && stab.rustc_depr.is_none() {
|
||||
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,
|
||||
// this is *almost surely* an accident.
|
||||
if let (&Some(attr::Deprecation {since: ref dep_since, ..}),
|
||||
&attr::Stable {since: ref stab_since}) = (&stab.depr, &stab.level) {
|
||||
if let (&Some(attr::RustcDeprecation {since: ref dep_since, ..}),
|
||||
&attr::Stable {since: ref stab_since}) = (&stab.rustc_depr, &stab.level) {
|
||||
// Explicit version of iter::order::lt to handle parse errors properly
|
||||
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()) {
|
||||
@ -134,20 +140,20 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
|
||||
}
|
||||
|
||||
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);
|
||||
self.parent = parent;
|
||||
self.parent_stab = orig_parent_stab;
|
||||
} else {
|
||||
debug!("annotate: not found, parent = {:?}", self.parent);
|
||||
debug!("annotate: not found, parent = {:?}", self.parent_stab);
|
||||
let mut is_error = kind == AnnotationKind::Required &&
|
||||
self.access_levels.is_reachable(id) &&
|
||||
!self.tcx.sess.opts.test;
|
||||
if let Some(stab) = self.parent {
|
||||
if let Some(stab) = self.parent_stab {
|
||||
if stab.level.is_unstable() {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -165,9 +171,35 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
|
||||
attr::mark_used(attr);
|
||||
self.tcx.sess.span_err(attr.span(), "stability attributes may not be used \
|
||||
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 {
|
||||
tcx: tcx,
|
||||
index: self,
|
||||
parent: None,
|
||||
parent_stab: None,
|
||||
parent_depr: None,
|
||||
access_levels: access_levels,
|
||||
in_trait_impl: false,
|
||||
in_enum: false,
|
||||
@ -291,7 +324,8 @@ impl<'tcx> Index<'tcx> {
|
||||
staged_api.insert(LOCAL_CRATE, is_staged_api);
|
||||
Index {
|
||||
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> {
|
||||
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
|
||||
let cross_crate = !id.is_local();
|
||||
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 }
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, ex: &hir::Expr) {
|
||||
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);
|
||||
}
|
||||
|
||||
fn visit_path(&mut self, path: &hir::Path, id: ast::NodeId) {
|
||||
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)
|
||||
}
|
||||
|
||||
fn visit_path_list_item(&mut self, prefix: &hir::Path, item: &hir::PathListItem) {
|
||||
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)
|
||||
}
|
||||
|
||||
fn visit_pat(&mut self, pat: &hir::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)
|
||||
}
|
||||
|
||||
@ -441,7 +479,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> {
|
||||
|
||||
/// Helper for discovering nodes to check for stability
|
||||
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 {
|
||||
hir::ItemExternCrate(_) => {
|
||||
// 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
|
||||
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 id = match e.node {
|
||||
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,
|
||||
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()) {
|
||||
Some(def::DefPrimTy(..)) => {}
|
||||
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,
|
||||
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()) {
|
||||
Some(def::DefPrimTy(..)) => {}
|
||||
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,
|
||||
cb: &mut FnMut(DefId, Span, &Option<&Stability>)) {
|
||||
cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option<Deprecation>)) {
|
||||
debug!("check_pat(pat = {:?})", pat);
|
||||
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,
|
||||
cb: &mut FnMut(DefId, Span, &Option<&Stability>)) {
|
||||
if !is_staged_api(tcx, id) {
|
||||
debug!("maybe_do_stability_check: \
|
||||
skipping id={:?} since it is not staged_api", id);
|
||||
return;
|
||||
}
|
||||
cb: &mut FnMut(DefId, Span,
|
||||
&Option<&Stability>, &Option<Deprecation>)) {
|
||||
if is_internal(tcx, span) {
|
||||
debug!("maybe_do_stability_check: \
|
||||
skipping span={:?} since it is internal", span);
|
||||
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: \
|
||||
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 {
|
||||
@ -627,24 +665,34 @@ fn is_staged_api(tcx: &ty::ctxt, id: DefId) -> bool {
|
||||
|
||||
/// Lookup the stability for a node, loading external crate
|
||||
/// metadata as necessary.
|
||||
pub fn lookup<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<&'tcx Stability> {
|
||||
if let Some(st) = tcx.stability.borrow().map.get(&id) {
|
||||
pub fn lookup_stability<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<&'tcx Stability> {
|
||||
if let Some(st) = tcx.stability.borrow().stab_map.get(&id) {
|
||||
return *st;
|
||||
}
|
||||
|
||||
let st = lookup_uncached(tcx, id);
|
||||
tcx.stability.borrow_mut().map.insert(id, st);
|
||||
let st = lookup_stability_uncached(tcx, id);
|
||||
tcx.stability.borrow_mut().stab_map.insert(id, 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);
|
||||
|
||||
// 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(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.
|
||||
|
||||
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
|
||||
|
@ -575,74 +575,71 @@ impl LateLintPass for MissingDebugImplementations {
|
||||
declare_lint! {
|
||||
DEPRECATED,
|
||||
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)]
|
||||
pub struct Stability;
|
||||
pub struct Deprecated;
|
||||
|
||||
impl Stability {
|
||||
fn lint(&self, cx: &LateContext, _id: DefId,
|
||||
span: Span, stability: &Option<&attr::Stability>) {
|
||||
impl Deprecated {
|
||||
fn lint(&self, cx: &LateContext, _id: DefId, span: Span,
|
||||
stability: &Option<&attr::Stability>, deprecation: &Option<attr::Deprecation>) {
|
||||
// Deprecated attributes apply in-crate and cross-crate.
|
||||
let (lint, label) = match *stability {
|
||||
Some(&attr::Stability { depr: Some(_), .. }) =>
|
||||
(DEPRECATED, "deprecated"),
|
||||
_ => return
|
||||
};
|
||||
if let Some(&attr::Stability{rustc_depr: Some(attr::RustcDeprecation{ref reason, ..}), ..})
|
||||
= *stability {
|
||||
output(cx, DEPRECATED, span, Some(&reason))
|
||||
} 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, span: Span, stability: &Option<&attr::Stability>,
|
||||
lint: &'static Lint, label: &'static str) {
|
||||
let msg = match *stability {
|
||||
Some(&attr::Stability {depr: Some(attr::Deprecation {ref reason, ..}), ..}) => {
|
||||
format!("use of {} item: {}", label, reason)
|
||||
}
|
||||
_ => format!("use of {} item", label)
|
||||
fn output(cx: &LateContext, lint: &'static Lint, span: Span, note: Option<&str>) {
|
||||
let msg = if let Some(note) = note {
|
||||
format!("use of deprecated item: {}", note)
|
||||
} else {
|
||||
format!("use of deprecated item")
|
||||
};
|
||||
|
||||
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 {
|
||||
lint_array!(DEPRECATED)
|
||||
}
|
||||
}
|
||||
|
||||
impl LateLintPass for Stability {
|
||||
impl LateLintPass for Deprecated {
|
||||
fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
|
||||
stability::check_item(cx.tcx, item, false,
|
||||
&mut |id, sp, stab|
|
||||
self.lint(cx, id, sp, &stab));
|
||||
&mut |id, sp, stab, depr|
|
||||
self.lint(cx, id, sp, &stab, &depr));
|
||||
}
|
||||
|
||||
fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
|
||||
stability::check_expr(cx.tcx, e,
|
||||
&mut |id, sp, stab|
|
||||
self.lint(cx, id, sp, &stab));
|
||||
&mut |id, sp, stab, depr|
|
||||
self.lint(cx, id, sp, &stab, &depr));
|
||||
}
|
||||
|
||||
fn check_path(&mut self, cx: &LateContext, path: &hir::Path, id: ast::NodeId) {
|
||||
stability::check_path(cx.tcx, path, id,
|
||||
&mut |id, sp, stab|
|
||||
self.lint(cx, id, sp, &stab));
|
||||
&mut |id, sp, stab, depr|
|
||||
self.lint(cx, id, sp, &stab, &depr));
|
||||
}
|
||||
|
||||
fn check_path_list_item(&mut self, cx: &LateContext, item: &hir::PathListItem) {
|
||||
stability::check_path_list_item(cx.tcx, item,
|
||||
&mut |id, sp, stab|
|
||||
self.lint(cx, id, sp, &stab));
|
||||
&mut |id, sp, stab, depr|
|
||||
self.lint(cx, id, sp, &stab, &depr));
|
||||
}
|
||||
|
||||
fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) {
|
||||
stability::check_pat(cx.tcx, pat,
|
||||
&mut |id, sp, stab|
|
||||
self.lint(cx, id, sp, &stab));
|
||||
&mut |id, sp, stab, depr|
|
||||
self.lint(cx, id, sp, &stab, &depr));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,7 +124,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
|
||||
UnusedAllocation,
|
||||
MissingCopyImplementations,
|
||||
UnstableFeatures,
|
||||
Stability,
|
||||
Deprecated,
|
||||
UnconditionalRecursion,
|
||||
InvalidNoMangleItems,
|
||||
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_deprecation: usize = 0xa7;
|
||||
|
||||
pub const tag_rustc_version: usize = 0x10f;
|
||||
pub fn rustc_version() -> String {
|
||||
format!(
|
||||
|
@ -42,6 +42,12 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
|
||||
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
|
||||
{
|
||||
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> {
|
||||
let item = cdata.lookup_item(id);
|
||||
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_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_deprecation(rbml_w, depr);
|
||||
|
||||
encode_struct_fields(rbml_w, variant);
|
||||
|
||||
@ -450,8 +452,10 @@ fn encode_info_for_mod(ecx: &EncodeContext,
|
||||
encode_path(rbml_w, path.clone());
|
||||
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_deprecation(rbml_w, depr);
|
||||
|
||||
// Encode the reexports of this module, if this module is 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_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_deprecation(rbml_w, depr);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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_deprecation(rbml_w, depr);
|
||||
|
||||
// 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
|
||||
@ -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,
|
||||
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_deprecation(rbml_w, depr);
|
||||
|
||||
let elem = ast_map::PathName(associated_const.name);
|
||||
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_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_deprecation(rbml_w, depr);
|
||||
|
||||
let m_node_id = ecx.local_id(m.def_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_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_deprecation(rbml_w, depr);
|
||||
|
||||
let elem = ast_map::PathName(associated_type.name);
|
||||
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>,
|
||||
rbml_w: &mut Encoder,
|
||||
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));
|
||||
|
||||
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 {
|
||||
hir::ItemStatic(_, m, _) => {
|
||||
@ -949,6 +972,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||
encode_path(rbml_w, path);
|
||||
encode_visibility(rbml_w, vis);
|
||||
encode_stability(rbml_w, stab);
|
||||
encode_deprecation(rbml_w, depr);
|
||||
encode_attributes(rbml_w, &item.attrs);
|
||||
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_visibility(rbml_w, vis);
|
||||
encode_stability(rbml_w, stab);
|
||||
encode_deprecation(rbml_w, depr);
|
||||
rbml_w.end_tag();
|
||||
}
|
||||
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_visibility(rbml_w, vis);
|
||||
encode_stability(rbml_w, stab);
|
||||
encode_deprecation(rbml_w, depr);
|
||||
encode_method_argument_names(rbml_w, &**decl);
|
||||
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_stability(rbml_w, stab);
|
||||
encode_deprecation(rbml_w, depr);
|
||||
rbml_w.end_tag();
|
||||
}
|
||||
hir::ItemTy(..) => {
|
||||
@ -1027,6 +1054,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||
encode_path(rbml_w, path);
|
||||
encode_visibility(rbml_w, vis);
|
||||
encode_stability(rbml_w, stab);
|
||||
encode_deprecation(rbml_w, depr);
|
||||
rbml_w.end_tag();
|
||||
}
|
||||
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_stability(rbml_w, stab);
|
||||
encode_deprecation(rbml_w, depr);
|
||||
rbml_w.end_tag();
|
||||
|
||||
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_path(rbml_w, path.clone());
|
||||
encode_stability(rbml_w, stab);
|
||||
encode_deprecation(rbml_w, depr);
|
||||
encode_visibility(rbml_w, vis);
|
||||
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_stability(rbml_w, stab);
|
||||
encode_deprecation(rbml_w, depr);
|
||||
rbml_w.end_tag();
|
||||
|
||||
// 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_visibility(rbml_w, vis);
|
||||
encode_stability(rbml_w, stab);
|
||||
encode_deprecation(rbml_w, depr);
|
||||
for &method_def_id in tcx.trait_item_def_ids(def_id).iter() {
|
||||
rbml_w.start_tag(tag_item_trait_item);
|
||||
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);
|
||||
|
||||
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_deprecation(rbml_w, depr);
|
||||
|
||||
let trait_item_type =
|
||||
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_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_deprecation(rbml_w, depr);
|
||||
encode_symbol(ecx, rbml_w, nitem.id);
|
||||
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_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_deprecation(rbml_w, depr);
|
||||
encode_symbol(ecx, rbml_w, nitem.id);
|
||||
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),
|
||||
inner: inner,
|
||||
visibility: Some(hir::Public),
|
||||
stability: stability::lookup(tcx, did).clean(cx),
|
||||
stability: stability::lookup_stability(tcx, did).clean(cx),
|
||||
def_id: did,
|
||||
});
|
||||
Some(ret)
|
||||
@ -303,7 +303,7 @@ pub fn build_impl(cx: &DocContext,
|
||||
name: None,
|
||||
attrs: attrs,
|
||||
visibility: Some(hir::Inherited),
|
||||
stability: stability::lookup(tcx, did).clean(cx),
|
||||
stability: stability::lookup_stability(tcx, did).clean(cx),
|
||||
def_id: did,
|
||||
});
|
||||
}
|
||||
@ -333,7 +333,7 @@ pub fn build_impl(cx: &DocContext,
|
||||
source: clean::Span::empty(),
|
||||
attrs: vec![],
|
||||
visibility: None,
|
||||
stability: stability::lookup(tcx, did).clean(cx),
|
||||
stability: stability::lookup_stability(tcx, did).clean(cx),
|
||||
def_id: did
|
||||
})
|
||||
}
|
||||
@ -381,7 +381,7 @@ pub fn build_impl(cx: &DocContext,
|
||||
source: clean::Span::empty(),
|
||||
attrs: vec![],
|
||||
visibility: None,
|
||||
stability: stability::lookup(tcx, did).clean(cx),
|
||||
stability: stability::lookup_stability(tcx, did).clean(cx),
|
||||
def_id: did
|
||||
})
|
||||
}
|
||||
@ -414,7 +414,7 @@ pub fn build_impl(cx: &DocContext,
|
||||
name: None,
|
||||
attrs: attrs,
|
||||
visibility: Some(hir::Inherited),
|
||||
stability: stability::lookup(tcx, did).clean(cx),
|
||||
stability: stability::lookup_stability(tcx, did).clean(cx),
|
||||
def_id: did,
|
||||
});
|
||||
|
||||
|
@ -62,7 +62,7 @@ mod simplify;
|
||||
|
||||
// extract the stability index for a node from tcx, if possible
|
||||
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> {
|
||||
@ -2689,12 +2689,12 @@ impl Clean<Stability> for attr::Stability {
|
||||
attr::Stable {ref since} => since.to_string(),
|
||||
_ => "".to_string(),
|
||||
},
|
||||
deprecated_since: match self.depr {
|
||||
Some(attr::Deprecation {ref since, ..}) => since.to_string(),
|
||||
deprecated_since: match self.rustc_depr {
|
||||
Some(attr::RustcDeprecation {ref since, ..}) => since.to_string(),
|
||||
_=> "".to_string(),
|
||||
},
|
||||
reason: {
|
||||
if let Some(ref depr) = self.depr {
|
||||
if let Some(ref depr) = self.rustc_depr {
|
||||
depr.reason.to_string()
|
||||
} else if let attr::Unstable {reason: Some(ref reason), ..} = self.level {
|
||||
reason.to_string()
|
||||
@ -2782,7 +2782,7 @@ impl<'tcx> Clean<Item> for ty::AssociatedType<'tcx> {
|
||||
inner: AssociatedTypeItem(bounds, self.ty.clean(cx)),
|
||||
visibility: self.vis.clean(cx),
|
||||
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> {
|
||||
self.cx.tcx_opt().and_then(|tcx| {
|
||||
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()
|
||||
})
|
||||
}
|
||||
|
@ -398,7 +398,7 @@ pub fn cfg_matches<T: CfgDiag>(cfgs: &[P<MetaItem>],
|
||||
pub struct Stability {
|
||||
pub level: StabilityLevel,
|
||||
pub feature: InternedString,
|
||||
pub depr: Option<Deprecation>,
|
||||
pub rustc_depr: Option<RustcDeprecation>,
|
||||
}
|
||||
|
||||
/// The available stability levels.
|
||||
@ -410,11 +410,17 @@ pub enum StabilityLevel {
|
||||
}
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
|
||||
pub struct Deprecation {
|
||||
pub struct RustcDeprecation {
|
||||
pub since: 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 {
|
||||
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 }}
|
||||
@ -427,7 +433,7 @@ fn find_stability_generic<'a, I>(diagnostic: &SpanHandler,
|
||||
where I: Iterator<Item = &'a Attribute>
|
||||
{
|
||||
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 {
|
||||
let tag = attr.name();
|
||||
@ -456,7 +462,7 @@ fn find_stability_generic<'a, I>(diagnostic: &SpanHandler,
|
||||
|
||||
match tag {
|
||||
"rustc_deprecated" => {
|
||||
if depr.is_some() {
|
||||
if rustc_depr.is_some() {
|
||||
diagnostic.span_err(item_sp, "multiple rustc_deprecated attributes");
|
||||
break
|
||||
}
|
||||
@ -477,7 +483,7 @@ fn find_stability_generic<'a, I>(diagnostic: &SpanHandler,
|
||||
|
||||
match (since, reason) {
|
||||
(Some(since), Some(reason)) => {
|
||||
depr = Some(Deprecation {
|
||||
rustc_depr = Some(RustcDeprecation {
|
||||
since: since,
|
||||
reason: reason,
|
||||
})
|
||||
@ -529,7 +535,7 @@ fn find_stability_generic<'a, I>(diagnostic: &SpanHandler,
|
||||
}
|
||||
},
|
||||
feature: feature,
|
||||
depr: None,
|
||||
rustc_depr: None,
|
||||
})
|
||||
}
|
||||
(None, _, _) => {
|
||||
@ -569,7 +575,7 @@ fn find_stability_generic<'a, I>(diagnostic: &SpanHandler,
|
||||
since: since,
|
||||
},
|
||||
feature: feature,
|
||||
depr: None,
|
||||
rustc_depr: None,
|
||||
})
|
||||
}
|
||||
(None, _) => {
|
||||
@ -591,12 +597,12 @@ fn find_stability_generic<'a, I>(diagnostic: &SpanHandler,
|
||||
}
|
||||
|
||||
// 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 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 {
|
||||
diagnostic.span_err(item_sp, "rustc_deprecated attribute must be paired with \
|
||||
either stable or unstable attribute");
|
||||
@ -606,12 +612,77 @@ fn find_stability_generic<'a, I>(diagnostic: &SpanHandler,
|
||||
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.
|
||||
pub fn find_stability(diagnostic: &SpanHandler, attrs: &[Attribute],
|
||||
item_sp: Span) -> Option<Stability> {
|
||||
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>]) {
|
||||
let mut set = HashSet::new();
|
||||
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
|
||||
("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)
|
||||
|
||||
@ -377,6 +380,7 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGat
|
||||
("must_use", Whitelisted, Ungated),
|
||||
("stable", Whitelisted, Ungated),
|
||||
("unstable", Whitelisted, Ungated),
|
||||
("deprecated", Whitelisted, Ungated),
|
||||
|
||||
("rustc_paren_sugar", Normal, Gated("unboxed_closures",
|
||||
"unboxed_closures are still evolving")),
|
||||
@ -539,6 +543,7 @@ pub struct Features {
|
||||
pub braced_empty_structs: bool,
|
||||
pub staged_api: bool,
|
||||
pub stmt_expr_attributes: bool,
|
||||
pub deprecated: bool,
|
||||
}
|
||||
|
||||
impl Features {
|
||||
@ -573,6 +578,7 @@ impl Features {
|
||||
braced_empty_structs: false,
|
||||
staged_api: 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"),
|
||||
staged_api: cx.has_feature("staged_api"),
|
||||
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…
x
Reference in New Issue
Block a user