Skip to content

Commit b4ff0bc

Browse files
committedSep 3, 2013
auto merge of #8921 : huonw/rust/stability, r=brson
Significant progress on #6875, enough that I'll open new bugs and turn that into a metabug when this lands. Description & example in the commit message.
2 parents 7ee90a0 + 506f69a commit b4ff0bc

File tree

8 files changed

+745
-3
lines changed

8 files changed

+745
-3
lines changed
 

‎doc/rust.md

+57-1
Original file line numberDiff line numberDiff line change
@@ -1038,7 +1038,7 @@ code_. They are defined in the same way as any other Rust function,
10381038
except that they have the `extern` modifier.
10391039

10401040
~~~
1041-
// Declares an extern fn, the ABI defaults to "C"
1041+
// Declares an extern fn, the ABI defaults to "C"
10421042
extern fn new_vec() -> ~[int] { ~[] }
10431043
10441044
// Declares an extern fn with "stdcall" ABI
@@ -1723,6 +1723,62 @@ Supported traits for `deriving` are:
17231723
each constituent field of the type must also implement `ToStr` and will have
17241724
`field.to_str()` invoked to build up the result.
17251725

1726+
### Stability
1727+
One can indicate the stability of an API using the following attributes:
1728+
1729+
* `deprecated`: This item should no longer be used, e.g. it has been
1730+
replaced. No guarantee of backwards-compatibility.
1731+
* `experimental`: This item was only recently introduced or is
1732+
otherwise in a state of flux. It may change significantly, or even
1733+
be removed. No guarantee of backwards-compatibility.
1734+
* `unstable`: This item is still under development, but requires more
1735+
testing to be considered stable. No guarantee of backwards-compatibility.
1736+
* `stable`: This item is considered stable, and will not change
1737+
significantly. Guarantee of backwards-compatibility.
1738+
* `frozen`: This item is very stable, and is unlikely to
1739+
change. Guarantee of backwards-compatibility.
1740+
* `locked`: This item will never change unless a serious bug is
1741+
found. Guarantee of backwards-compatibility.
1742+
1743+
These levels are directly inspired by
1744+
[Node.js' "stability index"](http://nodejs.org/api/documentation.html).
1745+
1746+
There are lints for disallowing items marked with certain levels:
1747+
`deprecated`, `experimental` and `unstable`; the first two will warn
1748+
by default. Items with not marked with a stability are considered to
1749+
be unstable for the purposes of the lint. One can give an optional
1750+
string that will be displayed when the lint flags the use of an item.
1751+
1752+
~~~ {.xfail-test}
1753+
#[warn(unstable)];
1754+
1755+
#[deprecated="replaced by `best`"]
1756+
fn bad() {
1757+
// delete everything
1758+
}
1759+
1760+
fn better() {
1761+
// delete fewer things
1762+
}
1763+
1764+
#[stable]
1765+
fn best() {
1766+
// delete nothing
1767+
}
1768+
1769+
fn main() {
1770+
bad(); // "warning: use of deprecated item: replaced by `best`"
1771+
1772+
better(); // "warning: use of unmarked item"
1773+
1774+
best(); // no warning
1775+
}
1776+
~~~
1777+
1778+
> **Note:** Currently these are only checked when applied to
1779+
> individual functions, structs, methods and enum variants, *not* to
1780+
> entire modules, traits, impls or enums themselves.
1781+
17261782
# Statements and expressions
17271783

17281784
Rust is _primarily_ an expression language. This means that most forms of

‎src/librustc/metadata/encoder.rs

+1
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
330330
encode_name(ecx, ebml_w, variant.node.name);
331331
encode_parent_item(ebml_w, local_def(id));
332332
encode_visibility(ebml_w, variant.node.vis);
333+
encode_attributes(ebml_w, variant.node.attrs);
333334
match variant.node.kind {
334335
ast::tuple_variant_kind(ref args)
335336
if args.len() > 0 && generics.ty_params.len() == 0 => {

‎src/librustc/middle/lint.rs

+129-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use driver::session;
1313
use middle::ty;
1414
use middle::pat_util;
15+
use metadata::csearch;
1516
use util::ppaux::{ty_to_str};
1617

1718
use std::cmp;
@@ -27,7 +28,7 @@ use std::u8;
2728
use extra::smallintmap::SmallIntMap;
2829
use syntax::ast_map;
2930
use syntax::attr;
30-
use syntax::attr::AttrMetaMethods;
31+
use syntax::attr::{AttrMetaMethods, AttributeMethods};
3132
use syntax::codemap::Span;
3233
use syntax::codemap;
3334
use syntax::parse::token;
@@ -97,6 +98,10 @@ pub enum lint {
9798
missing_doc,
9899
unreachable_code,
99100

101+
deprecated,
102+
experimental,
103+
unstable,
104+
100105
warnings,
101106
}
102107

@@ -281,6 +286,27 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[
281286
default: warn
282287
}),
283288

289+
("deprecated",
290+
LintSpec {
291+
lint: deprecated,
292+
desc: "detects use of #[deprecated] items",
293+
default: warn
294+
}),
295+
296+
("experimental",
297+
LintSpec {
298+
lint: experimental,
299+
desc: "detects use of #[experimental] items",
300+
default: warn
301+
}),
302+
303+
("unstable",
304+
LintSpec {
305+
lint: unstable,
306+
desc: "detects use of #[unstable] items (incl. items with no stability attribute)",
307+
default: allow
308+
}),
309+
284310
("warnings",
285311
LintSpec {
286312
lint: warnings,
@@ -1375,6 +1401,107 @@ fn lint_missing_doc() -> @mut OuterLint {
13751401
@mut MissingDocLintVisitor { stopping_on_items: false } as @mut OuterLint
13761402
}
13771403

1404+
/// Checks for use of items with #[deprecated], #[experimental] and
1405+
/// #[unstable] (or none of them) attributes.
1406+
struct StabilityLintVisitor { stopping_on_items: bool }
1407+
1408+
impl StabilityLintVisitor {
1409+
fn handle_def(&mut self, sp: Span, def: &ast::Def, cx: @mut Context) {
1410+
let id = ast_util::def_id_of_def(*def);
1411+
1412+
let stability = if ast_util::is_local(id) {
1413+
// this crate
1414+
match cx.tcx.items.find(&id.node) {
1415+
Some(ast_node) => {
1416+
let s = do ast_node.with_attrs |attrs| {
1417+
do attrs.map_move |a| {
1418+
attr::find_stability(a.iter().map(|a| a.meta()))
1419+
}
1420+
};
1421+
match s {
1422+
Some(s) => s,
1423+
1424+
// no possibility of having attributes
1425+
// (e.g. it's a local variable), so just
1426+
// ignore it.
1427+
None => return
1428+
}
1429+
}
1430+
_ => cx.tcx.sess.bug(fmt!("handle_def: %? not found", id))
1431+
}
1432+
} else {
1433+
// cross-crate
1434+
1435+
let mut s = None;
1436+
// run through all the attributes and take the first
1437+
// stability one.
1438+
do csearch::get_item_attrs(cx.tcx.cstore, id) |meta_items| {
1439+
if s.is_none() {
1440+
s = attr::find_stability(meta_items.move_iter())
1441+
}
1442+
}
1443+
s
1444+
};
1445+
1446+
let (lint, label) = match stability {
1447+
// no stability attributes == Unstable
1448+
None => (unstable, "unmarked"),
1449+
Some(attr::Stability { level: attr::Unstable, _ }) => (unstable, "unstable"),
1450+
Some(attr::Stability { level: attr::Experimental, _ }) => {
1451+
(experimental, "experimental")
1452+
}
1453+
Some(attr::Stability { level: attr::Deprecated, _ }) => (deprecated, "deprecated"),
1454+
_ => return
1455+
};
1456+
1457+
let msg = match stability {
1458+
Some(attr::Stability { text: Some(ref s), _ }) => {
1459+
fmt!("use of %s item: %s", label, *s)
1460+
}
1461+
_ => fmt!("use of %s item", label)
1462+
};
1463+
1464+
cx.span_lint(lint, sp, msg);
1465+
}
1466+
}
1467+
1468+
impl SubitemStoppableVisitor for StabilityLintVisitor {
1469+
fn is_running_on_items(&mut self) -> bool { !self.stopping_on_items }
1470+
}
1471+
1472+
impl Visitor<@mut Context> for StabilityLintVisitor {
1473+
fn visit_item(&mut self, i:@ast::item, e:@mut Context) {
1474+
self.OVERRIDE_visit_item(i, e);
1475+
}
1476+
1477+
fn visit_fn(&mut self, fk:&visit::fn_kind, fd:&ast::fn_decl,
1478+
b:&ast::Block, s:Span, n:ast::NodeId, e:@mut Context) {
1479+
self.OVERRIDE_visit_fn(fk, fd, b, s, n, e);
1480+
}
1481+
1482+
fn visit_expr(&mut self, ex: @ast::Expr, cx: @mut Context) {
1483+
match ex.node {
1484+
ast::ExprMethodCall(*) |
1485+
ast::ExprPath(*) |
1486+
ast::ExprStruct(*) => {
1487+
match cx.tcx.def_map.find(&ex.id) {
1488+
Some(def) => self.handle_def(ex.span, def, cx),
1489+
None => {}
1490+
}
1491+
}
1492+
_ => {}
1493+
}
1494+
1495+
visit::walk_expr(self, ex, cx)
1496+
}
1497+
}
1498+
1499+
outer_lint_boilerplate_impl!(StabilityLintVisitor)
1500+
1501+
fn lint_stability() -> @mut OuterLint {
1502+
@mut StabilityLintVisitor { stopping_on_items: false } as @mut OuterLint
1503+
}
1504+
13781505
struct LintCheckVisitor;
13791506

13801507
impl Visitor<@mut Context> for LintCheckVisitor {
@@ -1458,6 +1585,7 @@ pub fn check_crate(tcx: ty::ctxt, crate: @ast::Crate) {
14581585
cx.add_old_lint(lint_unused_mut());
14591586
cx.add_old_lint(lint_unnecessary_allocations());
14601587
cx.add_old_lint(lint_missing_doc());
1588+
cx.add_old_lint(lint_stability());
14611589
cx.add_lint(lint_session(cx));
14621590

14631591
// Actually perform the lint checks (iterating the ast)

‎src/librustc/middle/ty.rs

-1
Original file line numberDiff line numberDiff line change
@@ -4706,4 +4706,3 @@ pub fn trait_of_method(tcx: ctxt, def_id: ast::DefId)
47064706

47074707
result
47084708
}
4709-

‎src/libsyntax/ast_map.rs

+20
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,26 @@ pub enum ast_node {
8080
node_callee_scope(@Expr)
8181
}
8282

83+
impl ast_node {
84+
pub fn with_attrs<T>(&self, f: &fn(Option<&[Attribute]>) -> T) -> T {
85+
let attrs = match *self {
86+
node_item(i, _) => Some(i.attrs.as_slice()),
87+
node_foreign_item(fi, _, _, _) => Some(fi.attrs.as_slice()),
88+
node_trait_method(tm, _, _) => match *tm {
89+
required(ref type_m) => Some(type_m.attrs.as_slice()),
90+
provided(m) => Some(m.attrs.as_slice())
91+
},
92+
node_method(m, _, _) => Some(m.attrs.as_slice()),
93+
node_variant(ref v, _, _) => Some(v.node.attrs.as_slice()),
94+
// unit/tuple structs take the attributes straight from
95+
// the struct definition.
96+
node_struct_ctor(_, strct, _) => Some(strct.attrs.as_slice()),
97+
_ => None
98+
};
99+
f(attrs)
100+
}
101+
}
102+
83103
pub type map = @mut HashMap<NodeId, ast_node>;
84104

85105
pub struct Ctx {

‎src/libsyntax/attr.rs

+38
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,44 @@ pub fn test_cfg<AM: AttrMetaMethods, It: Iterator<AM>>
313313
no_cfgs || some_cfg_matches
314314
}
315315

316+
/// Represents the #[deprecated="foo"] (etc) attributes.
317+
pub struct Stability {
318+
level: StabilityLevel,
319+
text: Option<@str>
320+
}
321+
322+
/// The available stability levels.
323+
#[deriving(Eq,Ord,Clone)]
324+
pub enum StabilityLevel {
325+
Deprecated,
326+
Experimental,
327+
Unstable,
328+
Stable,
329+
Frozen,
330+
Locked
331+
}
332+
333+
/// Find the first stability attribute. `None` if none exists.
334+
pub fn find_stability<AM: AttrMetaMethods, It: Iterator<AM>>(mut metas: It) -> Option<Stability> {
335+
for m in metas {
336+
let level = match m.name().as_slice() {
337+
"deprecated" => Deprecated,
338+
"experimental" => Experimental,
339+
"unstable" => Unstable,
340+
"stable" => Stable,
341+
"frozen" => Frozen,
342+
"locked" => Locked,
343+
_ => loop // not a stability level
344+
};
345+
346+
return Some(Stability {
347+
level: level,
348+
text: m.value_str()
349+
});
350+
}
351+
None
352+
}
353+
316354
pub fn require_unique_names(diagnostic: @mut span_handler,
317355
metas: &[@MetaItem]) {
318356
let mut set = HashSet::new();

‎src/test/auxiliary/lint_stability.rs

+162
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
#[link(name = "lint_stability",
11+
vers = "0.1")];
12+
#[crate_type = "lib"];
13+
14+
#[deprecated]
15+
pub fn deprecated() {}
16+
#[deprecated="text"]
17+
pub fn deprecated_text() {}
18+
19+
#[experimental]
20+
pub fn experimental() {}
21+
#[experimental="text"]
22+
pub fn experimental_text() {}
23+
24+
#[unstable]
25+
pub fn unstable() {}
26+
#[unstable="text"]
27+
pub fn unstable_text() {}
28+
29+
pub fn unmarked() {}
30+
31+
#[stable]
32+
pub fn stable() {}
33+
#[stable="text"]
34+
pub fn stable_text() {}
35+
36+
#[locked]
37+
pub fn locked() {}
38+
#[locked="text"]
39+
pub fn locked_text() {}
40+
41+
#[frozen]
42+
pub fn frozen() {}
43+
#[frozen="text"]
44+
pub fn frozen_text() {}
45+
46+
#[stable]
47+
pub struct MethodTester;
48+
49+
impl MethodTester {
50+
#[deprecated]
51+
pub fn method_deprecated(&self) {}
52+
#[deprecated="text"]
53+
pub fn method_deprecated_text(&self) {}
54+
55+
#[experimental]
56+
pub fn method_experimental(&self) {}
57+
#[experimental="text"]
58+
pub fn method_experimental_text(&self) {}
59+
60+
#[unstable]
61+
pub fn method_unstable(&self) {}
62+
#[unstable="text"]
63+
pub fn method_unstable_text(&self) {}
64+
65+
pub fn method_unmarked(&self) {}
66+
67+
#[stable]
68+
pub fn method_stable(&self) {}
69+
#[stable="text"]
70+
pub fn method_stable_text(&self) {}
71+
72+
#[locked]
73+
pub fn method_locked(&self) {}
74+
#[locked="text"]
75+
pub fn method_locked_text(&self) {}
76+
77+
#[frozen]
78+
pub fn method_frozen(&self) {}
79+
#[frozen="text"]
80+
pub fn method_frozen_text(&self) {}
81+
}
82+
83+
pub trait Trait {
84+
#[deprecated]
85+
fn trait_deprecated(&self) {}
86+
#[deprecated="text"]
87+
fn trait_deprecated_text(&self) {}
88+
89+
#[experimental]
90+
fn trait_experimental(&self) {}
91+
#[experimental="text"]
92+
fn trait_experimental_text(&self) {}
93+
94+
#[unstable]
95+
fn trait_unstable(&self) {}
96+
#[unstable="text"]
97+
fn trait_unstable_text(&self) {}
98+
99+
fn trait_unmarked(&self) {}
100+
101+
#[stable]
102+
fn trait_stable(&self) {}
103+
#[stable="text"]
104+
fn trait_stable_text(&self) {}
105+
106+
#[locked]
107+
fn trait_locked(&self) {}
108+
#[locked="text"]
109+
fn trait_locked_text(&self) {}
110+
111+
#[frozen]
112+
fn trait_frozen(&self) {}
113+
#[frozen="text"]
114+
fn trait_frozen_text(&self) {}
115+
}
116+
117+
impl Trait for MethodTester {}
118+
119+
#[deprecated]
120+
pub struct DeprecatedStruct { i: int }
121+
#[experimental]
122+
pub struct ExperimentalStruct { i: int }
123+
#[unstable]
124+
pub struct UnstableStruct { i: int }
125+
pub struct UnmarkedStruct { i: int }
126+
#[stable]
127+
pub struct StableStruct { i: int }
128+
#[frozen]
129+
pub struct FrozenStruct { i: int }
130+
#[locked]
131+
pub struct LockedStruct { i: int }
132+
133+
#[deprecated]
134+
pub struct DeprecatedUnitStruct;
135+
#[experimental]
136+
pub struct ExperimentalUnitStruct;
137+
#[unstable]
138+
pub struct UnstableUnitStruct;
139+
pub struct UnmarkedUnitStruct;
140+
#[stable]
141+
pub struct StableUnitStruct;
142+
#[frozen]
143+
pub struct FrozenUnitStruct;
144+
#[locked]
145+
pub struct LockedUnitStruct;
146+
147+
pub enum Enum {
148+
#[deprecated]
149+
DeprecatedVariant,
150+
#[experimental]
151+
ExperimentalVariant,
152+
#[unstable]
153+
UnstableVariant,
154+
155+
UnmarkedVariant,
156+
#[stable]
157+
StableVariant,
158+
#[frozen]
159+
FrozenVariant,
160+
#[locked]
161+
LockedVariant,
162+
}
+338
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,338 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// xfail-fast aux-build
12+
// aux-build:lint_stability.rs
13+
14+
#[deny(unstable)];
15+
#[deny(deprecated)];
16+
#[deny(experimental)];
17+
18+
mod cross_crate {
19+
extern mod lint_stability;
20+
use self::lint_stability::*;
21+
22+
fn test() {
23+
// XXX: attributes on methods are not encoded cross crate.
24+
let foo = MethodTester;
25+
26+
deprecated(); //~ ERROR use of deprecated item
27+
foo.method_deprecated(); // ~ ERROR use of deprecated item
28+
foo.trait_deprecated(); // ~ ERROR use of deprecated item
29+
30+
deprecated_text(); //~ ERROR use of deprecated item: text
31+
foo.method_deprecated_text(); // ~ ERROR use of deprecated item: text
32+
foo.trait_deprecated_text(); // ~ ERROR use of deprecated item: text
33+
34+
experimental(); //~ ERROR use of experimental item
35+
foo.method_experimental(); // ~ ERROR use of experimental item
36+
foo.trait_experimental(); // ~ ERROR use of experimental item
37+
38+
experimental_text(); //~ ERROR use of experimental item: text
39+
foo.method_experimental_text(); // ~ ERROR use of experimental item: text
40+
foo.trait_experimental_text(); // ~ ERROR use of experimental item: text
41+
42+
unstable(); //~ ERROR use of unstable item
43+
foo.method_unstable(); // ~ ERROR use of unstable item
44+
foo.trait_unstable(); // ~ ERROR use of unstable item
45+
46+
unstable_text(); //~ ERROR use of unstable item: text
47+
foo.method_unstable_text(); // ~ ERROR use of unstable item: text
48+
foo.trait_unstable_text(); // ~ ERROR use of unstable item: text
49+
50+
unmarked(); //~ ERROR use of unmarked item
51+
foo.method_unmarked(); // ~ ERROR use of unmarked item
52+
foo.trait_unmarked(); // ~ ERROR use of unmarked item
53+
54+
stable();
55+
foo.method_stable();
56+
foo.trait_stable();
57+
58+
stable_text();
59+
foo.method_stable_text();
60+
foo.trait_stable_text();
61+
62+
frozen();
63+
foo.method_frozen();
64+
foo.trait_frozen();
65+
66+
frozen_text();
67+
foo.method_frozen_text();
68+
foo.trait_frozen_text();
69+
70+
locked();
71+
foo.method_locked();
72+
foo.trait_locked();
73+
74+
locked_text();
75+
foo.method_locked_text();
76+
foo.trait_locked_text();
77+
78+
79+
let _ = DeprecatedStruct { i: 0 }; //~ ERROR use of deprecated item
80+
let _ = ExperimentalStruct { i: 0 }; //~ ERROR use of experimental item
81+
let _ = UnstableStruct { i: 0 }; //~ ERROR use of unstable item
82+
let _ = UnmarkedStruct { i: 0 }; //~ ERROR use of unmarked item
83+
let _ = StableStruct { i: 0 };
84+
let _ = FrozenStruct { i: 0 };
85+
let _ = LockedStruct { i: 0 };
86+
87+
let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated item
88+
let _ = ExperimentalUnitStruct; //~ ERROR use of experimental item
89+
let _ = UnstableUnitStruct; //~ ERROR use of unstable item
90+
let _ = UnmarkedUnitStruct; //~ ERROR use of unmarked item
91+
let _ = StableUnitStruct;
92+
let _ = FrozenUnitStruct;
93+
let _ = LockedUnitStruct;
94+
95+
let _ = DeprecatedVariant; //~ ERROR use of deprecated item
96+
let _ = ExperimentalVariant; //~ ERROR use of experimental item
97+
let _ = UnstableVariant; //~ ERROR use of unstable item
98+
let _ = UnmarkedVariant; //~ ERROR use of unmarked item
99+
let _ = StableVariant;
100+
let _ = FrozenVariant;
101+
let _ = LockedVariant;
102+
}
103+
}
104+
105+
mod this_crate {
106+
#[deprecated]
107+
pub fn deprecated() {}
108+
#[deprecated="text"]
109+
pub fn deprecated_text() {}
110+
111+
#[experimental]
112+
pub fn experimental() {}
113+
#[experimental="text"]
114+
pub fn experimental_text() {}
115+
116+
#[unstable]
117+
pub fn unstable() {}
118+
#[unstable="text"]
119+
pub fn unstable_text() {}
120+
121+
pub fn unmarked() {}
122+
123+
#[stable]
124+
pub fn stable() {}
125+
#[stable="text"]
126+
pub fn stable_text() {}
127+
128+
#[locked]
129+
pub fn locked() {}
130+
#[locked="text"]
131+
pub fn locked_text() {}
132+
133+
#[frozen]
134+
pub fn frozen() {}
135+
#[frozen="text"]
136+
pub fn frozen_text() {}
137+
138+
#[stable]
139+
pub struct MethodTester;
140+
141+
impl MethodTester {
142+
#[deprecated]
143+
pub fn method_deprecated(&self) {}
144+
#[deprecated="text"]
145+
pub fn method_deprecated_text(&self) {}
146+
147+
#[experimental]
148+
pub fn method_experimental(&self) {}
149+
#[experimental="text"]
150+
pub fn method_experimental_text(&self) {}
151+
152+
#[unstable]
153+
pub fn method_unstable(&self) {}
154+
#[unstable="text"]
155+
pub fn method_unstable_text(&self) {}
156+
157+
pub fn method_unmarked(&self) {}
158+
159+
#[stable]
160+
pub fn method_stable(&self) {}
161+
#[stable="text"]
162+
pub fn method_stable_text(&self) {}
163+
164+
#[locked]
165+
pub fn method_locked(&self) {}
166+
#[locked="text"]
167+
pub fn method_locked_text(&self) {}
168+
169+
#[frozen]
170+
pub fn method_frozen(&self) {}
171+
#[frozen="text"]
172+
pub fn method_frozen_text(&self) {}
173+
}
174+
175+
pub trait Trait {
176+
#[deprecated]
177+
fn trait_deprecated(&self) {}
178+
#[deprecated="text"]
179+
fn trait_deprecated_text(&self) {}
180+
181+
#[experimental]
182+
fn trait_experimental(&self) {}
183+
#[experimental="text"]
184+
fn trait_experimental_text(&self) {}
185+
186+
#[unstable]
187+
fn trait_unstable(&self) {}
188+
#[unstable="text"]
189+
fn trait_unstable_text(&self) {}
190+
191+
fn trait_unmarked(&self) {}
192+
193+
#[stable]
194+
fn trait_stable(&self) {}
195+
#[stable="text"]
196+
fn trait_stable_text(&self) {}
197+
198+
#[locked]
199+
fn trait_locked(&self) {}
200+
#[locked="text"]
201+
fn trait_locked_text(&self) {}
202+
203+
#[frozen]
204+
fn trait_frozen(&self) {}
205+
#[frozen="text"]
206+
fn trait_frozen_text(&self) {}
207+
}
208+
209+
impl Trait for MethodTester {}
210+
211+
#[deprecated]
212+
pub struct DeprecatedStruct { i: int }
213+
#[experimental]
214+
pub struct ExperimentalStruct { i: int }
215+
#[unstable]
216+
pub struct UnstableStruct { i: int }
217+
pub struct UnmarkedStruct { i: int }
218+
#[stable]
219+
pub struct StableStruct { i: int }
220+
#[frozen]
221+
pub struct FrozenStruct { i: int }
222+
#[locked]
223+
pub struct LockedStruct { i: int }
224+
225+
#[deprecated]
226+
pub struct DeprecatedUnitStruct;
227+
#[experimental]
228+
pub struct ExperimentalUnitStruct;
229+
#[unstable]
230+
pub struct UnstableUnitStruct;
231+
pub struct UnmarkedUnitStruct;
232+
#[stable]
233+
pub struct StableUnitStruct;
234+
#[frozen]
235+
pub struct FrozenUnitStruct;
236+
#[locked]
237+
pub struct LockedUnitStruct;
238+
239+
pub enum Enum {
240+
#[deprecated]
241+
DeprecatedVariant,
242+
#[experimental]
243+
ExperimentalVariant,
244+
#[unstable]
245+
UnstableVariant,
246+
247+
UnmarkedVariant,
248+
#[stable]
249+
StableVariant,
250+
#[frozen]
251+
FrozenVariant,
252+
#[locked]
253+
LockedVariant,
254+
}
255+
256+
fn test() {
257+
let foo = MethodTester;
258+
259+
deprecated(); //~ ERROR use of deprecated item
260+
foo.method_deprecated(); // ~ ERROR use of deprecated item
261+
foo.trait_deprecated(); // ~ ERROR use of deprecated item
262+
263+
deprecated_text(); //~ ERROR use of deprecated item: text
264+
foo.method_deprecated_text(); // ~ ERROR use of deprecated item: text
265+
foo.trait_deprecated_text(); // ~ ERROR use of deprecated item: text
266+
267+
experimental(); //~ ERROR use of experimental item
268+
foo.method_experimental(); // ~ ERROR use of experimental item
269+
foo.trait_experimental(); // ~ ERROR use of experimental item
270+
271+
experimental_text(); //~ ERROR use of experimental item: text
272+
foo.method_experimental_text(); // ~ ERROR use of experimental item: text
273+
foo.trait_experimental_text(); // ~ ERROR use of experimental item: text
274+
275+
unstable(); //~ ERROR use of unstable item
276+
foo.method_unstable(); // ~ ERROR use of unstable item
277+
foo.trait_unstable(); // ~ ERROR use of unstable item
278+
279+
unstable_text(); //~ ERROR use of unstable item: text
280+
foo.method_unstable_text(); // ~ ERROR use of unstable item: text
281+
foo.trait_unstable_text(); // ~ ERROR use of unstable item: text
282+
283+
unmarked(); //~ ERROR use of unmarked item
284+
foo.method_unmarked(); // ~ ERROR use of unmarked item
285+
foo.trait_unmarked(); // ~ ERROR use of unmarked item
286+
287+
stable();
288+
foo.method_stable();
289+
foo.trait_stable();
290+
291+
stable_text();
292+
foo.method_stable_text();
293+
foo.trait_stable_text();
294+
295+
frozen();
296+
foo.method_frozen();
297+
foo.trait_frozen();
298+
299+
frozen_text();
300+
foo.method_frozen_text();
301+
foo.trait_frozen_text();
302+
303+
locked();
304+
foo.method_locked();
305+
foo.trait_locked();
306+
307+
locked_text();
308+
foo.method_locked_text();
309+
foo.trait_locked_text();
310+
311+
312+
let _ = DeprecatedStruct { i: 0 }; //~ ERROR use of deprecated item
313+
let _ = ExperimentalStruct { i: 0 }; //~ ERROR use of experimental item
314+
let _ = UnstableStruct { i: 0 }; //~ ERROR use of unstable item
315+
let _ = UnmarkedStruct { i: 0 }; //~ ERROR use of unmarked item
316+
let _ = StableStruct { i: 0 };
317+
let _ = FrozenStruct { i: 0 };
318+
let _ = LockedStruct { i: 0 };
319+
320+
let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated item
321+
let _ = ExperimentalUnitStruct; //~ ERROR use of experimental item
322+
let _ = UnstableUnitStruct; //~ ERROR use of unstable item
323+
let _ = UnmarkedUnitStruct; //~ ERROR use of unmarked item
324+
let _ = StableUnitStruct;
325+
let _ = FrozenUnitStruct;
326+
let _ = LockedUnitStruct;
327+
328+
let _ = DeprecatedVariant; //~ ERROR use of deprecated item
329+
let _ = ExperimentalVariant; //~ ERROR use of experimental item
330+
let _ = UnstableVariant; //~ ERROR use of unstable item
331+
let _ = UnmarkedVariant; //~ ERROR use of unmarked item
332+
let _ = StableVariant;
333+
let _ = FrozenVariant;
334+
let _ = LockedVariant;
335+
}
336+
}
337+
338+
fn main() {}

0 commit comments

Comments
 (0)
Please sign in to comment.