Auto merge of #30206 - petrochenkov:newdepr, r=brson

Closes https://github.com/rust-lang/rust/issues/29935

The attributes `deprecated` and `rustc_deprecated` are completely independent in this implementation and it leads to some noticeable code duplication. Representing `deprecated` as
```
Stability {
    level: Stable { since: "" },
    feature: "",
    depr: Some(Deprecation),
}
```
or, contrariwise, splitting rustc_deprecation from stability makes most of the duplication go away.
I can do this refactoring, but before doing it I must be sure, that further divergence of `deprecated` and `rustc_deprecated` is certainly not a goal.

cc @llogiq
This commit is contained in:
bors 2015-12-16 08:15:23 +00:00
commit ac2c5ff024
26 changed files with 1003 additions and 137 deletions

View File

@ -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

View File

@ -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)

View File

@ -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;
}
}
@ -167,7 +173,26 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
outside of the standard library");
}
}
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 +294,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 +317,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 +354,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 +426,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 +472,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 +509,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 +570,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 +582,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 +593,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 +622,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,47 +658,42 @@ 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> {
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)
}
_ => {}
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 item_stab = if id.is_local() {
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);
if id.is_local() {
None // The stability cache is filled partially lazily
} else {
tcx.sess.cstore.stability(id).map(|st| tcx.intern_stability(st))
};
}
}
item_stab.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(tcx, trait_id);
}
}
None
})
fn lookup_deprecation_uncached<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<Deprecation> {
debug!("lookup(id={:?})", id);
if id.is_local() {
None // The stability cache is filled partially lazily
} else {
tcx.sess.cstore.deprecation(id)
}
}
/// Given the list of enabled features that were not language features (i.e. that

View File

@ -575,74 +575,71 @@ impl LateLintPass for MissingDebugImplementations {
declare_lint! {
DEPRECATED,
Warn,
"detects use of #[rustc_deprecated] items"
"detects use of 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));
}
}

View File

@ -124,7 +124,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
UnusedAllocation,
MissingCopyImplementations,
UnstableFeatures,
Stability,
Deprecated,
UnconditionalRecursion,
InvalidNoMangleItems,
PluginAsLibrary,

View File

@ -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!(

View File

@ -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());

View File

@ -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| {

View File

@ -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);
}

View File

@ -120,7 +120,8 @@ 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),
deprecation: stability::lookup_deprecation(tcx, did).clean(cx),
def_id: did,
});
Some(ret)
@ -303,7 +304,8 @@ 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),
deprecation: stability::lookup_deprecation(tcx, did).clean(cx),
def_id: did,
});
}
@ -333,7 +335,8 @@ 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),
deprecation: stability::lookup_deprecation(tcx, did).clean(cx),
def_id: did
})
}
@ -381,7 +384,8 @@ 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),
deprecation: stability::lookup_deprecation(tcx, did).clean(cx),
def_id: did
})
}
@ -414,7 +418,8 @@ 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),
deprecation: stability::lookup_deprecation(tcx, did).clean(cx),
def_id: did,
});

View File

@ -62,7 +62,11 @@ 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)
}
fn get_deprecation(cx: &DocContext, def_id: DefId) -> Option<Deprecation> {
cx.tcx_opt().and_then(|tcx| stability::lookup_deprecation(tcx, def_id)).clean(cx)
}
pub trait Clean<T> {
@ -188,6 +192,7 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
attrs: child.attrs.clone(),
visibility: Some(hir::Public),
stability: None,
deprecation: None,
def_id: DefId::local(prim.to_def_index()),
inner: PrimitiveItem(prim),
});
@ -254,6 +259,7 @@ pub struct Item {
pub visibility: Option<Visibility>,
pub def_id: DefId,
pub stability: Option<Stability>,
pub deprecation: Option<Deprecation>,
}
impl Item {
@ -417,6 +423,7 @@ impl Clean<Item> for doctree::Module {
source: whence.clean(cx),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
def_id: cx.map.local_def_id(self.id),
inner: ModuleItem(Module {
is_crate: self.is_crate,
@ -1078,6 +1085,7 @@ impl Clean<Item> for doctree::Function {
source: self.whence.clean(cx),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
def_id: cx.map.local_def_id(self.id),
inner: FunctionItem(Function {
decl: self.decl.clean(cx),
@ -1204,6 +1212,7 @@ impl Clean<Item> for doctree::Trait {
def_id: cx.map.local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
inner: TraitItem(Trait {
unsafety: self.unsafety,
items: self.items.clean(cx),
@ -1254,6 +1263,7 @@ impl Clean<Item> for hir::TraitItem {
def_id: cx.map.local_def_id(self.id),
visibility: None,
stability: get_stability(cx, cx.map.local_def_id(self.id)),
deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)),
inner: inner
}
}
@ -1287,6 +1297,7 @@ impl Clean<Item> for hir::ImplItem {
def_id: cx.map.local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: get_stability(cx, cx.map.local_def_id(self.id)),
deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)),
inner: inner
}
}
@ -1357,6 +1368,7 @@ impl<'tcx> Clean<Item> for ty::Method<'tcx> {
name: Some(self.name.clean(cx)),
visibility: Some(hir::Inherited),
stability: get_stability(cx, self.def_id),
deprecation: get_deprecation(cx, self.def_id),
def_id: self.def_id,
attrs: inline::load_attrs(cx, cx.tcx(), self.def_id),
source: Span::empty(),
@ -1715,6 +1727,7 @@ impl Clean<Item> for hir::StructField {
source: self.span.clean(cx),
visibility: Some(vis),
stability: get_stability(cx, cx.map.local_def_id(self.node.id)),
deprecation: get_deprecation(cx, cx.map.local_def_id(self.node.id)),
def_id: cx.map.local_def_id(self.node.id),
inner: StructFieldItem(TypedStructField(self.node.ty.clean(cx))),
}
@ -1740,6 +1753,7 @@ impl<'tcx> Clean<Item> for ty::FieldDefData<'tcx, 'static> {
source: Span::empty(),
visibility: Some(self.vis),
stability: get_stability(cx, self.did),
deprecation: get_deprecation(cx, self.did),
def_id: self.did,
inner: StructFieldItem(TypedStructField(self.unsubst_ty().clean(cx))),
}
@ -1771,6 +1785,7 @@ impl Clean<Item> for doctree::Struct {
def_id: cx.map.local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
inner: StructItem(Struct {
struct_type: self.struct_type,
generics: self.generics.clean(cx),
@ -1817,6 +1832,7 @@ impl Clean<Item> for doctree::Enum {
def_id: cx.map.local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
inner: EnumItem(Enum {
variants: self.variants.clean(cx),
generics: self.generics.clean(cx),
@ -1839,6 +1855,7 @@ impl Clean<Item> for doctree::Variant {
source: self.whence.clean(cx),
visibility: None,
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
def_id: cx.map.local_def_id(self.def.id()),
inner: VariantItem(Variant {
kind: struct_def_to_variant_kind(&self.def, cx),
@ -1876,6 +1893,7 @@ impl<'tcx> Clean<Item> for ty::VariantDefData<'tcx, 'static> {
// at the needed information here.
def_id: self.did,
stability: get_stability(cx, self.did),
deprecation: get_deprecation(cx, self.did),
inner: StructFieldItem(
TypedStructField(field.unsubst_ty().clean(cx))
)
@ -1892,6 +1910,7 @@ impl<'tcx> Clean<Item> for ty::VariantDefData<'tcx, 'static> {
def_id: self.did,
inner: VariantItem(Variant { kind: kind }),
stability: get_stability(cx, self.did),
deprecation: get_deprecation(cx, self.did),
}
}
}
@ -2067,6 +2086,7 @@ impl Clean<Item> for doctree::Typedef {
def_id: cx.map.local_def_id(self.id.clone()),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
inner: TypedefItem(Typedef {
type_: self.ty.clean(cx),
generics: self.gen.clean(cx),
@ -2118,6 +2138,7 @@ impl Clean<Item> for doctree::Static {
def_id: cx.map.local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
inner: StaticItem(Static {
type_: self.type_.clean(cx),
mutability: self.mutability.clean(cx),
@ -2142,6 +2163,7 @@ impl Clean<Item> for doctree::Constant {
def_id: cx.map.local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
inner: ConstantItem(Constant {
type_: self.type_.clean(cx),
expr: self.expr.span.to_src(cx),
@ -2216,6 +2238,7 @@ impl Clean<Vec<Item>> for doctree::Impl {
def_id: cx.map.local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
inner: ImplItem(Impl {
unsafety: self.unsafety,
generics: self.generics.clean(cx),
@ -2298,6 +2321,7 @@ impl Clean<Item> for doctree::DefaultImpl {
def_id: cx.map.local_def_id(self.id),
visibility: Some(hir::Public),
stability: None,
deprecation: None,
inner: DefaultImplItem(DefaultImpl {
unsafety: self.unsafety,
trait_: self.trait_.clean(cx),
@ -2315,6 +2339,7 @@ impl Clean<Item> for doctree::ExternCrate {
def_id: cx.map.local_def_id(0),
visibility: self.vis.clean(cx),
stability: None,
deprecation: None,
inner: ExternCrateItem(self.name.clean(cx), self.path.clone())
}
}
@ -2380,6 +2405,7 @@ impl Clean<Vec<Item>> for doctree::Import {
def_id: cx.map.local_def_id(0),
visibility: self.vis.clean(cx),
stability: None,
deprecation: None,
inner: ImportItem(inner)
});
ret
@ -2466,6 +2492,7 @@ impl Clean<Item> for hir::ForeignItem {
def_id: cx.map.local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: get_stability(cx, cx.map.local_def_id(self.id)),
deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)),
inner: inner,
}
}
@ -2659,6 +2686,7 @@ impl Clean<Item> for doctree::Macro {
source: self.whence.clean(cx),
visibility: hir::Public.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
def_id: cx.map.local_def_id(self.id),
inner: MacroItem(Macro {
source: format!("macro_rules! {} {{\n{}}}",
@ -2680,6 +2708,12 @@ pub struct Stability {
pub issue: Option<u32>
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Deprecation {
pub since: String,
pub note: String,
}
impl Clean<Stability> for attr::Stability {
fn clean(&self, _: &DocContext) -> Stability {
Stability {
@ -2689,12 +2723,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()
@ -2716,6 +2750,15 @@ impl<'a> Clean<Stability> for &'a attr::Stability {
}
}
impl Clean<Deprecation> for attr::Deprecation {
fn clean(&self, _: &DocContext) -> Deprecation {
Deprecation {
since: self.since.as_ref().map_or("".to_string(), |s| s.to_string()),
note: self.note.as_ref().map_or("".to_string(), |s| s.to_string()),
}
}
}
impl<'tcx> Clean<Item> for ty::AssociatedConst<'tcx> {
fn clean(&self, cx: &DocContext) -> Item {
Item {
@ -2726,6 +2769,7 @@ impl<'tcx> Clean<Item> for ty::AssociatedConst<'tcx> {
visibility: None,
def_id: self.def_id,
stability: None,
deprecation: None,
}
}
}
@ -2782,7 +2826,8 @@ 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),
deprecation: stability::lookup_deprecation(cx.tcx(), self.def_id).clean(cx),
}
}
}

View File

@ -40,6 +40,7 @@ pub struct Module {
pub traits: Vec<Trait>,
pub vis: hir::Visibility,
pub stab: Option<attr::Stability>,
pub depr: Option<attr::Deprecation>,
pub impls: Vec<Impl>,
pub def_traits: Vec<DefaultImpl>,
pub foreigns: Vec<hir::ForeignMod>,
@ -54,6 +55,7 @@ impl Module {
id: 0,
vis: hir::Inherited,
stab: None,
depr: None,
where_outer: syntax::codemap::DUMMY_SP,
where_inner: syntax::codemap::DUMMY_SP,
attrs : Vec::new(),
@ -96,6 +98,7 @@ pub enum TypeBound {
pub struct Struct {
pub vis: hir::Visibility,
pub stab: Option<attr::Stability>,
pub depr: Option<attr::Deprecation>,
pub id: NodeId,
pub struct_type: StructType,
pub name: Name,
@ -108,6 +111,7 @@ pub struct Struct {
pub struct Enum {
pub vis: hir::Visibility,
pub stab: Option<attr::Stability>,
pub depr: Option<attr::Deprecation>,
pub variants: Vec<Variant>,
pub generics: hir::Generics,
pub attrs: Vec<ast::Attribute>,
@ -121,6 +125,7 @@ pub struct Variant {
pub attrs: Vec<ast::Attribute>,
pub def: hir::VariantData,
pub stab: Option<attr::Stability>,
pub depr: Option<attr::Deprecation>,
pub whence: Span,
}
@ -131,6 +136,7 @@ pub struct Function {
pub name: Name,
pub vis: hir::Visibility,
pub stab: Option<attr::Stability>,
pub depr: Option<attr::Deprecation>,
pub unsafety: hir::Unsafety,
pub constness: hir::Constness,
pub whence: Span,
@ -147,6 +153,7 @@ pub struct Typedef {
pub whence: Span,
pub vis: hir::Visibility,
pub stab: Option<attr::Stability>,
pub depr: Option<attr::Deprecation>,
}
#[derive(Debug)]
@ -158,6 +165,7 @@ pub struct Static {
pub attrs: Vec<ast::Attribute>,
pub vis: hir::Visibility,
pub stab: Option<attr::Stability>,
pub depr: Option<attr::Deprecation>,
pub id: ast::NodeId,
pub whence: Span,
}
@ -169,6 +177,7 @@ pub struct Constant {
pub attrs: Vec<ast::Attribute>,
pub vis: hir::Visibility,
pub stab: Option<attr::Stability>,
pub depr: Option<attr::Deprecation>,
pub id: ast::NodeId,
pub whence: Span,
}
@ -184,6 +193,7 @@ pub struct Trait {
pub whence: Span,
pub vis: hir::Visibility,
pub stab: Option<attr::Stability>,
pub depr: Option<attr::Deprecation>,
}
pub struct Impl {
@ -197,6 +207,7 @@ pub struct Impl {
pub whence: Span,
pub vis: hir::Visibility,
pub stab: Option<attr::Stability>,
pub depr: Option<attr::Deprecation>,
pub id: ast::NodeId,
}
@ -215,6 +226,7 @@ pub struct Macro {
pub whence: Span,
pub matchers: Vec<Span>,
pub stab: Option<attr::Stability>,
pub depr: Option<attr::Deprecation>,
pub imported_from: Option<Name>,
}

View File

@ -19,7 +19,7 @@ pub trait DocFolder : Sized {
/// don't override!
fn fold_item_recur(&mut self, item: Item) -> Option<Item> {
let Item { attrs, name, source, visibility, def_id, inner, stability } = item;
let Item { attrs, name, source, visibility, def_id, inner, stability, deprecation } = item;
let inner = inner;
let inner = match inner {
StructItem(mut i) => {
@ -66,7 +66,8 @@ pub trait DocFolder : Sized {
};
Some(Item { attrs: attrs, name: name, source: source, inner: inner,
visibility: visibility, stability: stability, def_id: def_id })
visibility: visibility, stability: stability, deprecation: deprecation,
def_id: def_id })
}
fn fold_mod(&mut self, m: Module) -> Module {

View File

@ -1801,7 +1801,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
}
fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Option<String> {
item.stability.as_ref().and_then(|stab| {
let mut result = item.stability.as_ref().and_then(|stab| {
let reason = if show_reason && !stab.reason.is_empty() {
format!(": {}", stab.reason)
} else {
@ -1836,7 +1836,27 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Optio
};
Some(format!("<em class='stab {}'>{}</em>",
item.stability_class(), text))
})
});
if result.is_none() {
result = item.deprecation.as_ref().and_then(|depr| {
let note = if show_reason && !depr.note.is_empty() {
format!(": {}", depr.note)
} else {
String::new()
};
let since = if show_reason && !depr.since.is_empty() {
format!(" since {}", Escape(&depr.since))
} else {
String::new()
};
let text = format!("Deprecated{}{}", since, Markdown(&note));
Some(format!("<em class='stab deprecated'>{}</em>", text))
});
}
result
}
struct Initializer<'a>(&'a str);

View File

@ -64,11 +64,18 @@ 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()
})
}
fn deprecation(&self, id: ast::NodeId) -> Option<attr::Deprecation> {
self.cx.tcx_opt().and_then(|tcx| {
self.cx.map.opt_local_def_id(id)
.and_then(|def_id| stability::lookup_deprecation(tcx, def_id))
})
}
pub fn visit(&mut self, krate: &hir::Crate) {
self.attrs = krate.attrs.clone();
@ -95,6 +102,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
name: name,
vis: item.vis,
stab: self.stability(item.id),
depr: self.deprecation(item.id),
attrs: item.attrs.clone(),
generics: generics.clone(),
fields: sd.fields().iter().cloned().collect(),
@ -112,11 +120,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
name: v.node.name,
attrs: v.node.attrs.clone(),
stab: self.stability(v.node.data.id()),
depr: self.deprecation(v.node.data.id()),
def: v.node.data.clone(),
whence: v.span,
}).collect(),
vis: it.vis,
stab: self.stability(it.id),
depr: self.deprecation(it.id),
generics: params.clone(),
attrs: it.attrs.clone(),
id: it.id,
@ -135,6 +145,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
id: item.id,
vis: item.vis,
stab: self.stability(item.id),
depr: self.deprecation(item.id),
attrs: item.attrs.clone(),
decl: fd.clone(),
name: name,
@ -156,6 +167,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
om.attrs = attrs;
om.vis = vis;
om.stab = self.stability(id);
om.depr = self.deprecation(id);
om.id = id;
for i in &m.item_ids {
let item = self.cx.map.expect_item(i.id);
@ -314,6 +326,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
whence: item.span,
vis: item.vis,
stab: self.stability(item.id),
depr: self.deprecation(item.id),
};
om.typedefs.push(t);
},
@ -328,6 +341,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
whence: item.span,
vis: item.vis,
stab: self.stability(item.id),
depr: self.deprecation(item.id),
};
om.statics.push(s);
},
@ -341,6 +355,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
whence: item.span,
vis: item.vis,
stab: self.stability(item.id),
depr: self.deprecation(item.id),
};
om.constants.push(s);
},
@ -356,6 +371,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
whence: item.span,
vis: item.vis,
stab: self.stability(item.id),
depr: self.deprecation(item.id),
};
om.traits.push(t);
},
@ -372,6 +388,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
whence: item.span,
vis: item.vis,
stab: self.stability(item.id),
depr: self.deprecation(item.id),
};
// Don't duplicate impls when inlining glob imports, we'll pick
// them up regardless of where they're located.
@ -410,6 +427,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
whence: def.span,
matchers: matchers,
stab: self.stability(def.id),
depr: self.deprecation(def.id),
imported_from: def.imported_from,
}
}

View File

@ -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 {

View File

@ -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", Normal, Gated("deprecated", "`#[deprecated]` attribute is unstable")),
("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"),
}
}

View File

@ -0,0 +1,90 @@
// 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) {}
}
#[deprecated(since = "1.0.0", note = "text")]
pub trait DeprecatedTrait { fn dummy(&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()));
}

View File

@ -98,6 +98,12 @@ impl Trait for MethodTester {}
#[unstable(feature = "test_feature", issue = "0")]
pub trait UnstableTrait { fn dummy(&self) { } }
#[stable(feature = "test_feature", since = "1.0.0")]
#[rustc_deprecated(since = "1.0.0", reason = "text")]
pub trait DeprecatedTrait {
#[stable(feature = "test_feature", since = "1.0.0")] fn dummy(&self) { }
}
#[stable(feature = "test_feature", since = "1.0.0")]
#[rustc_deprecated(since = "1.0.0", reason = "text")]
pub struct DeprecatedStruct {

View 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

View 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!();
}

View 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);
}

View File

@ -0,0 +1,389 @@
// 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
}
struct S;
impl DeprecatedTrait for S {} //~ ERROR use of deprecated item: text
trait LocalTrait : DeprecatedTrait { } //~ 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() {}

View 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() { }

View File

@ -227,8 +227,9 @@ mod cross_crate {
struct S;
impl UnstableTrait for S { } //~ ERROR use of unstable library feature
impl DeprecatedTrait for S {} //~ ERROR use of deprecated item: text
trait LocalTrait : UnstableTrait { } //~ ERROR use of unstable library feature
trait LocalTrait2 : DeprecatedTrait { } //~ ERROR use of deprecated item: text
impl Trait for S {
fn trait_stable(&self) {}

View File

@ -0,0 +1,16 @@
// 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)]
// @has deprecated/struct.S.html '//*[@class="stab deprecated"]' \
// 'Deprecated since 1.0.0: text'
#[deprecated(since = "1.0.0", note = "text")]
pub struct S;