These levels are directly inspired by
[Node.js' "stability index"](http://nodejs.org/api/documentation.html).
-There are lints for disallowing items marked with certain levels:
-`deprecated`, `experimental` and `unstable`; the first two will warn
-by default. Items with not marked with a stability are considered to
-be unstable for the purposes of the lint. One can give an optional
+Stability levels are inherited, so an items's stability attribute is the
+default stability for everything nested underneath it.
+
+There are lints for disallowing items marked with certain levels: `deprecated`,
+`experimental` and `unstable`. For now, only `deprecated` warns by default, but
+this will change once the standard library has been stabilized.
+Stability levels are meant to be promises at the crate
+ level, so these lints only apply when referencing
+items from an _external_ crate, not to items defined within the
+current crate. Items with no stability level are considered
+to be unstable for the purposes of the lint. One can give an optional
string that will be displayed when the lint flags the use of an item.
-~~~~ {.ignore}
-#![warn(unstable)]
+For example, if we define one crate called `stability_levels`:
+~~~~ {.ignore}
#[deprecated="replaced by `best`"]
-fn bad() {
+pub fn bad() {
// delete everything
}
-fn better() {
+pub fn better() {
// delete fewer things
}
#[stable]
-fn best() {
+pub fn best() {
// delete nothing
}
+~~~~
+
+then the lints will work as follows for a client crate:
+
+~~~~ {.ignore}
+#![warn(unstable)]
+extern crate stability_levels;
+use stability_levels::{bad, better, best};
fn main() {
bad(); // "warning: use of deprecated item: replaced by `best`"
use metadata::creader;
use middle::cfg;
use middle::cfg::graphviz::LabelledCFG;
-use middle::{trans, freevars, kind, ty, typeck, lint, reachable};
+use middle::{trans, freevars, stability, kind, ty, typeck, lint, reachable};
use middle::dependency_format;
use middle;
use plugin::load::Plugins;
time(time_passes, "loop checking", (), |_|
middle::check_loop::check_crate(&sess, krate));
+ let stability_index = time(time_passes, "stability index", (), |_|
+ stability::Index::build(krate));
+
let ty_cx = ty::mk_ctxt(sess, def_map, named_region_map, ast_map,
- freevars, region_map, lang_items);
+ freevars, region_map, lang_items, stability_index);
// passes are timed inside typeck
typeck::check_crate(&ty_cx, trait_map, krate);
pub mod weak_lang_items;
pub mod save;
pub mod intrinsicck;
+ pub mod stability;
}
pub mod front {
pub static tag_reachable_extern_fns: uint = 0x90;
pub static tag_reachable_extern_fn_id: uint = 0x91;
+pub static tag_items_data_item_stability: uint = 0x92;
+
+
#[deriving(Clone, Show)]
pub struct LinkMeta {
pub crateid: CrateId,
use std::rc::Rc;
use syntax::ast;
use syntax::ast_map;
+use syntax::attr;
use syntax::diagnostic::expect;
use syntax::parse::token;
let cdata = cstore.get_crate_data(did.krate);
decoder::is_typedef(&*cdata, did.node)
}
+
+pub fn get_stability(cstore: &cstore::CStore,
+ def: ast::DefId)
+ -> Option<attr::Stability> {
+ let cdata = cstore.get_crate_data(def.krate);
+ decoder::get_stability(&*cdata, def.node)
+}
}
}
+pub fn get_stability(cdata: Cmd, id: ast::NodeId) -> Option<attr::Stability> {
+ let item = lookup_item(id, cdata.data());
+ reader::maybe_get_doc(item, tag_items_data_item_stability).map(|doc| {
+ let mut decoder = reader::Decoder::new(doc);
+ Decodable::decode(&mut decoder).unwrap()
+ })
+}
+
pub fn get_impl_trait(cdata: Cmd,
id: ast::NodeId,
tcx: &ty::ctxt) -> Option<Rc<ty::TraitRef>>
encode_parent_item(ebml_w, local_def(id));
encode_visibility(ebml_w, variant.node.vis);
encode_attributes(ebml_w, variant.node.attrs.as_slice());
+
+ let stab = ecx.tcx.stability.borrow().lookup_local(variant.node.id);
+ encode_stability(ebml_w, stab);
+
match variant.node.kind {
ast::TupleVariantKind(ref args)
if args.len() > 0 && generics.ty_params.len() == 0 => {
encode_path(ebml_w, path.clone());
encode_visibility(ebml_w, vis);
+ encode_stability(ebml_w, ecx.tcx.stability.borrow().lookup_local(id));
// Encode the reexports of this module, if this module is public.
if vis == Public {
encode_symbol(ecx, ebml_w, ctor_id);
}
+ encode_stability(ebml_w, ecx.tcx.stability.borrow().lookup_local(ctor_id));
+
// 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
// they actually have a ctor rather than a normal function
encode_method_ty_fields(ecx, ebml_w, m);
encode_parent_item(ebml_w, local_def(parent_id));
+ let stab = ecx.tcx.stability.borrow().lookup_local(m.def_id.node);
+ encode_stability(ebml_w, stab);
+
// The type for methods gets encoded twice, which is unfortunate.
let tpt = lookup_item_type(ecx.tcx, m.def_id);
encode_bounds_and_type(ebml_w, ecx, &tpt);
ebml_w.end_tag();
}
+fn encode_stability(ebml_w: &mut Encoder, stab_opt: Option<attr::Stability>) {
+ stab_opt.map(|stab| {
+ ebml_w.start_tag(tag_items_data_item_stability);
+ stab.encode(ebml_w).unwrap();
+ ebml_w.end_tag();
+ });
+}
+
fn encode_info_for_item(ecx: &EncodeContext,
ebml_w: &mut Encoder,
item: &Item,
ecx.tcx.sess.codemap().span_to_str(item.span));
let def_id = local_def(item.id);
+ let stab = tcx.stability.borrow().lookup_local(item.id);
+
match item.node {
ItemStatic(_, m, _) => {
add_to_index(item, ebml_w, index);
encode_inlined_item(ecx, ebml_w, IIItemRef(item));
}
encode_visibility(ebml_w, vis);
+ encode_stability(ebml_w, stab);
ebml_w.end_tag();
}
ItemFn(ref decl, fn_style, _, ref generics, _) => {
encode_symbol(ecx, ebml_w, item.id);
}
encode_visibility(ebml_w, vis);
+ encode_stability(ebml_w, stab);
encode_method_argument_names(ebml_w, &**decl);
ebml_w.end_tag();
}
ebml_w.end_tag();
}
encode_visibility(ebml_w, vis);
+ encode_stability(ebml_w, stab);
ebml_w.end_tag();
}
ItemTy(..) => {
encode_name(ebml_w, item.ident.name);
encode_path(ebml_w, path);
encode_visibility(ebml_w, vis);
+ encode_stability(ebml_w, stab);
ebml_w.end_tag();
}
ItemEnum(ref enum_definition, ref generics) => {
encode_inherent_implementations(ecx, ebml_w, def_id);
encode_visibility(ebml_w, vis);
+ encode_stability(ebml_w, stab);
ebml_w.end_tag();
encode_enum_variant_info(ecx,
encode_name(ebml_w, item.ident.name);
encode_attributes(ebml_w, item.attrs.as_slice());
encode_path(ebml_w, path.clone());
+ encode_stability(ebml_w, stab);
encode_visibility(ebml_w, vis);
/* Encode def_ids for each field and method
encode_impl_vtables(ebml_w, ecx, &impl_vtables);
}
encode_path(ebml_w, path.clone());
+ encode_stability(ebml_w, stab);
ebml_w.end_tag();
// Iterate down the methods, emitting them. We rely on the
// should no longer need this ugly little hack either.
encode_sized(ebml_w, sized);
encode_visibility(ebml_w, vis);
+ encode_stability(ebml_w, stab);
for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
ebml_w.start_tag(tag_item_trait_method);
encode_def_id(ebml_w, method_def_id);
ebml_w.start_tag(tag_items_data_item);
encode_method_ty_fields(ecx, ebml_w, &*method_ty);
-
encode_parent_item(ebml_w, def_id);
+ let stab = tcx.stability.borrow().lookup_local(method_def_id.node);
+ encode_stability(ebml_w, stab);
+
let elem = ast_map::PathName(method_ty.ident.name);
encode_path(ebml_w, path.clone().chain(Some(elem).move_iter()));
LintSpec {
lint: Experimental,
desc: "detects use of #[experimental] items",
- default: Warn
+ // FIXME #6875: Change to Warn after std library stabilization is complete
+ default: Allow
}),
("unstable",
/// Checks for use of items with #[deprecated], #[experimental] and
/// #[unstable] (or none of them) attributes.
fn check_stability(cx: &Context, e: &ast::Expr) {
+ let tcx = cx.tcx;
+
let id = match e.node {
ast::ExprPath(..) | ast::ExprStruct(..) => {
match cx.tcx.def_map.borrow().find(&e.id) {
}
ast::ExprMethodCall(..) => {
let method_call = typeck::MethodCall::expr(e.id);
- match cx.tcx.method_map.borrow().find(&method_call) {
+ match tcx.method_map.borrow().find(&method_call) {
Some(method) => {
match method.origin {
typeck::MethodStatic(def_id) => {
// of the method inside trait definition.
// Otherwise, use the current def_id (which refers
// to the method inside impl).
- ty::trait_method_of_method(
- cx.tcx, def_id).unwrap_or(def_id)
+ ty::trait_method_of_method(cx.tcx, def_id)
+ .unwrap_or(def_id)
}
typeck::MethodParam(typeck::MethodParam {
trait_id: trait_id,
_ => return
};
- let stability = if ast_util::is_local(id) {
- // this crate
- let s = cx.tcx.map.with_attrs(id.node, |attrs| {
- attrs.map(|a| attr::find_stability(a.as_slice()))
- });
- match s {
- Some(s) => s,
+ // stability attributes are promises made across crates; do not
+ // check anything for crate-local usage.
+ if ast_util::is_local(id) { return }
- // no possibility of having attributes
- // (e.g. it's a local variable), so just
- // ignore it.
- None => return
- }
- } else {
- // cross-crate
-
- let mut s = None;
- // run through all the attributes and take the first
- // stability one.
- csearch::get_item_attrs(&cx.tcx.sess.cstore, id, |attrs| {
- if s.is_none() {
- s = attr::find_stability(attrs.as_slice())
- }
- });
- s
- };
+ let stability = tcx.stability.borrow_mut().lookup(&tcx.sess.cstore, id);
let (lint, label) = match stability {
// no stability attributes == Unstable
--- /dev/null
+// Copyright 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.
+
+//! A pass that annotates every item and method with its stability level,
+//! propagating default levels lexically from parent to children ast nodes.
+
+use util::nodemap::{NodeMap, DefIdMap};
+use syntax::codemap::Span;
+use syntax::{attr, visit};
+use syntax::ast::{Attribute, Block, Crate, DefId, FnDecl, NodeId, Variant};
+use syntax::ast::{Item, Required, Provided, TraitMethod, TypeMethod, Method};
+use syntax::ast::{Generics, StructDef, Ident};
+use syntax::ast_util::is_local;
+use syntax::attr::Stability;
+use syntax::visit::{FnKind, FkMethod, Visitor};
+use metadata::{cstore, csearch};
+
+/// A stability index, giving the stability level for items and methods.
+pub struct Index {
+ // stability for crate-local items; unmarked stability == no entry
+ local: NodeMap<Stability>,
+ // cache for extern-crate items; unmarked stability == entry with None
+ extern_cache: DefIdMap<Option<Stability>>
+}
+
+// A private tree-walker for producing an Index.
+struct Annotator {
+ index: Index
+}
+
+impl Annotator {
+ // Determine the stability for a node based on its attributes and inherited
+ // stability. The stability is recorded in the index and returned.
+ fn annotate(&mut self, id: NodeId, attrs: &[Attribute],
+ parent: Option<Stability>) -> Option<Stability> {
+ match attr::find_stability(attrs).or(parent) {
+ Some(stab) => {
+ self.index.local.insert(id, stab.clone());
+ Some(stab)
+ }
+ None => None
+ }
+ }
+}
+
+impl Visitor<Option<Stability>> for Annotator {
+ fn visit_item(&mut self, i: &Item, parent: Option<Stability>) {
+ let stab = self.annotate(i.id, i.attrs.as_slice(), parent);
+ visit::walk_item(self, i, stab)
+ }
+
+ fn visit_fn(&mut self, fk: &FnKind, fd: &FnDecl, b: &Block,
+ s: Span, _: NodeId, parent: Option<Stability>) {
+ let stab = match *fk {
+ FkMethod(_, _, meth) =>
+ self.annotate(meth.id, meth.attrs.as_slice(), parent),
+ _ => parent
+ };
+ visit::walk_fn(self, fk, fd, b, s, stab)
+ }
+
+ fn visit_trait_method(&mut self, t: &TraitMethod, parent: Option<Stability>) {
+ let stab = match *t {
+ Required(TypeMethod {attrs: ref attrs, id: id, ..}) =>
+ self.annotate(id, attrs.as_slice(), parent),
+
+ // work around lack of pattern matching for @ types
+ Provided(method) => match *method {
+ Method {attrs: ref attrs, id: id, ..} =>
+ self.annotate(id, attrs.as_slice(), parent)
+ }
+ };
+ visit::walk_trait_method(self, t, stab)
+ }
+
+ fn visit_variant(&mut self, v: &Variant, g: &Generics, parent: Option<Stability>) {
+ let stab = self.annotate(v.node.id, v.node.attrs.as_slice(), parent);
+ visit::walk_variant(self, v, g, stab)
+ }
+
+ fn visit_struct_def(&mut self, s: &StructDef, _: Ident, _: &Generics,
+ _: NodeId, parent: Option<Stability>) {
+ s.ctor_id.map(|id| self.annotate(id, &[], parent.clone()));
+ visit::walk_struct_def(self, s, parent)
+ }
+}
+
+impl Index {
+ /// Construct the stability index for a crate being compiled.
+ pub fn build(krate: &Crate) -> Index {
+ let mut annotator = Annotator {
+ index: Index {
+ local: NodeMap::new(),
+ extern_cache: DefIdMap::new()
+ }
+ };
+ visit::walk_crate(&mut annotator, krate,
+ attr::find_stability(krate.attrs.as_slice()));
+ annotator.index
+ }
+
+ /// Lookup the stability for a node, loading external crate
+ /// metadata as necessary.
+ pub fn lookup(&mut self, cstore: &cstore::CStore, id: DefId) -> Option<Stability> {
+ if is_local(id) {
+ self.lookup_local(id.node)
+ } else {
+ let stab = csearch::get_stability(cstore, id);
+ self.extern_cache.insert(id, stab.clone());
+ stab
+ }
+ }
+
+ /// Lookup the stability for a local node without loading any external crates
+ pub fn lookup_local(&self, id: NodeId) -> Option<Stability> {
+ self.local.find_copy(&id)
+ }
+}
use middle::resolve_lifetime;
use middle::subst;
use middle::subst::{Subst, Substs, VecPerParamSpace};
+use middle::stability;
use middle::ty;
use middle::typeck;
use middle::typeck::MethodCall;
/// to be valid. We gather up these restrictions in the intrinsicck pass
/// and check them in trans.
pub transmute_restrictions: RefCell<Vec<TransmuteRestriction>>,
+
+ /// Maps any item's def-id to its stability index.
+ pub stability: RefCell<stability::Index>,
}
pub enum tbox_flag {
map: ast_map::Map,
freevars: freevars::freevar_map,
region_maps: middle::region::RegionMaps,
- lang_items: middle::lang_items::LanguageItems)
+ lang_items: middle::lang_items::LanguageItems,
+ stability: stability::Index)
-> ctxt {
ctxt {
named_region_map: named_region_map,
dependency_formats: RefCell::new(HashMap::new()),
node_lint_levels: RefCell::new(HashMap::new()),
transmute_restrictions: RefCell::new(Vec::new()),
+ stability: RefCell::new(stability)
}
}
}
/// Represents the #[deprecated="foo"] and friends attributes.
+#[deriving(Encodable,Decodable,Clone,Show)]
pub struct Stability {
pub level: StabilityLevel,
pub text: Option<InternedString>
}
/// The available stability levels.
-#[deriving(PartialEq,PartialOrd,Clone,Show)]
+#[deriving(Encodable,Decodable,PartialEq,PartialOrd,Clone,Show)]
pub enum StabilityLevel {
Deprecated,
Experimental,
--- /dev/null
+// Copyright 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.
+#![crate_id="inherited_stability#0.1"]
+#![crate_type = "lib"]
+#![experimental]
+
+pub fn experimental() {}
+
+#[stable]
+pub fn stable() {}
+
+#[stable]
+pub mod stable_mod {
+ #[experimental]
+ pub fn experimental() {}
+
+ pub fn stable() {}
+}
+
+pub mod experimental_mod {
+ pub fn experimental() {}
+
+ #[stable]
+ pub fn stable() {}
+}
+
+#[stable]
+pub trait Stable {
+ #[experimental]
+ fn experimental(&self);
+
+ fn stable(&self);
+}
+
+impl Stable for uint {
+ fn experimental(&self) {}
+ fn stable(&self) {}
+}
+
+pub enum Experimental {
+ ExperimentalVariant,
+ #[stable]
+ StableVariant
+}
--- /dev/null
+// Copyright 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.
+
+#![crate_id="lint_output_format#0.1"]
+#![crate_type = "lib"]
+
+#[deprecated]
+pub fn foo() -> uint {
+ 20
+}
+
+#[experimental]
+pub fn bar() -> uint {
+ 40
+}
+
+#[unstable]
+pub fn baz() -> uint {
+ 30
+}
// except according to those terms.
// compile-flags:-F experimental -D unstable
+// aux-build:lint_output_format.rs
-#[deprecated]
-fn foo() -> uint {
- 20
-}
-
-#[experimental]
-fn bar() -> uint {
- 40
-}
-
-#[unstable]
-fn baz() -> uint {
- 30
-}
+extern crate lint_output_format;
+use lint_output_format::{foo, bar, baz};
fn main() {
let _x = foo(); //~ WARNING #[warn(deprecated)] on by default
// except according to those terms.
// aux-build:lint_stability.rs
+// aux-build:inherited_stability.rs
#![feature(globs)]
#![deny(unstable)]
use self::lint_stability::*;
fn test() {
- // FIXME: attributes on methods are not encoded cross crate.
let foo = MethodTester;
deprecated(); //~ ERROR use of deprecated item
}
}
+mod inheritance {
+ extern crate inherited_stability;
+ use self::inherited_stability::*;
+
+ fn test_inheritance() {
+ experimental(); //~ ERROR use of experimental item
+ stable();
+
+ stable_mod::experimental(); //~ ERROR use of experimental item
+ stable_mod::stable();
+
+ experimental_mod::experimental(); //~ ERROR use of experimental item
+ experimental_mod::stable();
+
+ let _ = ExperimentalVariant; //~ ERROR use of experimental item
+ let _ = StableVariant;
+
+ let x: uint = 0;
+ x.experimental(); //~ ERROR use of experimental item
+ x.stable();
+ }
+}
+
mod this_crate {
#[deprecated]
pub fn deprecated() {}
pub struct LockedTupleStruct(int);
fn test() {
+ // None of the following should generate errors, because
+ // stability attributes now have meaning only *across* crates,
+ // not within a single crate.
+
let foo = MethodTester;
- deprecated(); //~ ERROR use of deprecated item
- foo.method_deprecated(); //~ ERROR use of deprecated item
- foo.trait_deprecated(); //~ ERROR use of deprecated item
+ deprecated();
+ foo.method_deprecated();
+ foo.trait_deprecated();
- deprecated_text(); //~ ERROR use of deprecated item: text
- foo.method_deprecated_text(); //~ ERROR use of deprecated item: text
- foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
+ deprecated_text();
+ foo.method_deprecated_text();
+ foo.trait_deprecated_text();
- experimental(); //~ ERROR use of experimental item
- foo.method_experimental(); //~ ERROR use of experimental item
- foo.trait_experimental(); //~ ERROR use of experimental item
+ experimental();
+ foo.method_experimental();
+ foo.trait_experimental();
- experimental_text(); //~ ERROR use of experimental item: text
- foo.method_experimental_text(); //~ ERROR use of experimental item: text
- foo.trait_experimental_text(); //~ ERROR use of experimental item: text
+ experimental_text();
+ foo.method_experimental_text();
+ foo.trait_experimental_text();
- unstable(); //~ ERROR use of unstable item
- foo.method_unstable(); //~ ERROR use of unstable item
- foo.trait_unstable(); //~ ERROR use of unstable item
+ unstable();
+ foo.method_unstable();
+ foo.trait_unstable();
- unstable_text(); //~ ERROR use of unstable item: text
- foo.method_unstable_text(); //~ ERROR use of unstable item: text
- foo.trait_unstable_text(); //~ ERROR use of unstable item: text
+ unstable_text();
+ foo.method_unstable_text();
+ foo.trait_unstable_text();
- unmarked(); //~ ERROR use of unmarked item
- foo.method_unmarked(); //~ ERROR use of unmarked item
- foo.trait_unmarked(); //~ ERROR use of unmarked item
+ unmarked();
+ foo.method_unmarked();
+ foo.trait_unmarked();
stable();
foo.method_stable();
foo.trait_locked_text();
- let _ = DeprecatedStruct { i: 0 }; //~ ERROR use of deprecated item
- let _ = ExperimentalStruct { i: 0 }; //~ ERROR use of experimental item
- let _ = UnstableStruct { i: 0 }; //~ ERROR use of unstable item
- let _ = UnmarkedStruct { i: 0 }; //~ ERROR use of unmarked item
+ let _ = DeprecatedStruct { i: 0 };
+ let _ = ExperimentalStruct { i: 0 };
+ let _ = UnstableStruct { i: 0 };
+ let _ = UnmarkedStruct { i: 0 };
let _ = StableStruct { i: 0 };
let _ = FrozenStruct { i: 0 };
let _ = LockedStruct { i: 0 };
- let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated item
- let _ = ExperimentalUnitStruct; //~ ERROR use of experimental item
- let _ = UnstableUnitStruct; //~ ERROR use of unstable item
- let _ = UnmarkedUnitStruct; //~ ERROR use of unmarked item
+ let _ = DeprecatedUnitStruct;
+ let _ = ExperimentalUnitStruct;
+ let _ = UnstableUnitStruct;
+ let _ = UnmarkedUnitStruct;
let _ = StableUnitStruct;
let _ = FrozenUnitStruct;
let _ = LockedUnitStruct;
- let _ = DeprecatedVariant; //~ ERROR use of deprecated item
- let _ = ExperimentalVariant; //~ ERROR use of experimental item
- let _ = UnstableVariant; //~ ERROR use of unstable item
- let _ = UnmarkedVariant; //~ ERROR use of unmarked item
+ let _ = DeprecatedVariant;
+ let _ = ExperimentalVariant;
+ let _ = UnstableVariant;
+ let _ = UnmarkedVariant;
let _ = StableVariant;
let _ = FrozenVariant;
let _ = LockedVariant;
- let _ = DeprecatedTupleStruct (1); //~ ERROR use of deprecated item
- let _ = ExperimentalTupleStruct (1); //~ ERROR use of experimental item
- let _ = UnstableTupleStruct (1); //~ ERROR use of unstable item
- let _ = UnmarkedTupleStruct (1); //~ ERROR use of unmarked item
+ let _ = DeprecatedTupleStruct (1);
+ let _ = ExperimentalTupleStruct (1);
+ let _ = UnstableTupleStruct (1);
+ let _ = UnmarkedTupleStruct (1);
let _ = StableTupleStruct (1);
let _ = FrozenTupleStruct (1);
let _ = LockedTupleStruct (1);
}
fn test_method_param<F: Trait>(foo: F) {
- foo.trait_deprecated(); //~ ERROR use of deprecated item
- foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
- foo.trait_experimental(); //~ ERROR use of experimental item
- foo.trait_experimental_text(); //~ ERROR use of experimental item: text
- foo.trait_unstable(); //~ ERROR use of unstable item
- foo.trait_unstable_text(); //~ ERROR use of unstable item: text
- foo.trait_unmarked(); //~ ERROR use of unmarked item
+ foo.trait_deprecated();
+ foo.trait_deprecated_text();
+ foo.trait_experimental();
+ foo.trait_experimental_text();
+ foo.trait_unstable();
+ foo.trait_unstable_text();
+ foo.trait_unmarked();
foo.trait_stable();
}
fn test_method_object(foo: &Trait) {
- foo.trait_deprecated(); //~ ERROR use of deprecated item
- foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
- foo.trait_experimental(); //~ ERROR use of experimental item
- foo.trait_experimental_text(); //~ ERROR use of experimental item: text
- foo.trait_unstable(); //~ ERROR use of unstable item
- foo.trait_unstable_text(); //~ ERROR use of unstable item: text
- foo.trait_unmarked(); //~ ERROR use of unmarked item
+ foo.trait_deprecated();
+ foo.trait_deprecated_text();
+ foo.trait_experimental();
+ foo.trait_experimental_text();
+ foo.trait_unstable();
+ foo.trait_unstable_text();
+ foo.trait_unmarked();
foo.trait_stable();
}
}