提交 a12d0d4f 编写于 作者: A Alex Burka

honor #[rustc_const_unstable] attributes

上级 824952f4
......@@ -81,7 +81,12 @@ fn hash_stable<W: StableHasherResult>(&self,
});
impl_stable_hash_for!(struct ::syntax::attr::Deprecation { since, note });
impl_stable_hash_for!(struct ::syntax::attr::Stability { level, feature, rustc_depr });
impl_stable_hash_for!(struct ::syntax::attr::Stability {
level,
feature,
rustc_depr,
rustc_const_unstable
});
impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
for ::syntax::attr::StabilityLevel {
......@@ -102,6 +107,7 @@ fn hash_stable<W: StableHasherResult>(&self,
}
impl_stable_hash_for!(struct ::syntax::attr::RustcDeprecation { since, reason });
impl_stable_hash_for!(struct ::syntax::attr::RustcConstUnstable { feature });
impl_stable_hash_for!(enum ::syntax::attr::IntType {
......
......@@ -427,6 +427,7 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Index<'tcx> {
},
feature: Symbol::intern("rustc_private"),
rustc_depr: None,
rustc_const_unstable: None,
});
annotator.parent_stab = Some(stability);
}
......
......@@ -30,6 +30,7 @@
use rustc::mir::visit::{LvalueContext, Visitor};
use rustc::middle::lang_items;
use syntax::abi::Abi;
use syntax::attr;
use syntax::feature_gate::UnstableFeatures;
use syntax_pos::{Span, DUMMY_SP};
......@@ -713,14 +714,14 @@ fn visit_terminator_kind(&mut self,
self.visit_operand(func, location);
let fn_ty = func.ty(self.mir, self.tcx);
let (mut is_shuffle, mut is_const_fn) = (false, false);
let (mut is_shuffle, mut is_const_fn) = (false, None);
if let ty::TyFnDef(def_id, _) = fn_ty.sty {
match self.tcx.fn_sig(def_id).abi() {
Abi::RustIntrinsic |
Abi::PlatformIntrinsic => {
assert!(!self.tcx.is_const_fn(def_id));
match &self.tcx.item_name(def_id)[..] {
"size_of" | "min_align_of" => is_const_fn = true,
"size_of" | "min_align_of" => is_const_fn = Some(def_id),
name if name.starts_with("simd_shuffle") => {
is_shuffle = true;
......@@ -730,7 +731,9 @@ fn visit_terminator_kind(&mut self,
}
}
_ => {
is_const_fn = self.tcx.is_const_fn(def_id);
if self.tcx.is_const_fn(def_id) {
is_const_fn = Some(def_id);
}
}
}
}
......@@ -751,25 +754,38 @@ fn visit_terminator_kind(&mut self,
}
// Const fn calls.
if is_const_fn {
// We are in a const or static initializer,
if self.mode != Mode::Fn &&
// feature-gate is not enabled,
!self.tcx.sess.features.borrow().const_fn &&
// this doesn't come from a crate with the feature-gate enabled,
self.def_id.is_local() &&
// this doesn't come from a macro that has #[allow_internal_unstable]
!self.span.allows_unstable()
{
let mut err = self.tcx.sess.struct_span_err(self.span,
"const fns are an unstable feature");
help!(&mut err,
"in Nightly builds, add `#![feature(const_fn)]` \
to the crate attributes to enable");
err.emit();
if let Some(def_id) = is_const_fn {
// find corresponding rustc_const_unstable feature
if let Some(&attr::Stability {
rustc_const_unstable: Some(attr::RustcConstUnstable {
feature: ref feature_name
}),
.. }) = self.tcx.lookup_stability(def_id) {
// We are in a const or static initializer,
if self.mode != Mode::Fn &&
// feature-gate is not enabled,
!self.tcx.sess.features.borrow()
.declared_lib_features
.iter()
.any(|&(ref sym, _)| sym == feature_name) &&
// this doesn't come from a crate with the feature-gate enabled,
self.def_id.is_local() &&
// this doesn't come from a macro that has #[allow_internal_unstable]
!self.span.allows_unstable()
{
let mut err = self.tcx.sess.struct_span_err(self.span,
&format!("`{}` is not yet stable as a const fn",
self.tcx.item_path_str(def_id)));
help!(&mut err,
"in Nightly builds, add `#![feature({})]` \
to the crate attributes to enable",
feature_name);
err.emit();
}
}
} else {
self.qualif = Qualif::NOT_CONST;
......
......@@ -637,12 +637,13 @@ pub fn eval_condition<F>(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F)
}
}
/// Represents the #[stable], #[unstable] and #[rustc_deprecated] attributes.
/// Represents the #[stable], #[unstable], #[rustc_{deprecated,const_unstable}] attributes.
#[derive(RustcEncodable, RustcDecodable, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Stability {
pub level: StabilityLevel,
pub feature: Symbol,
pub rustc_depr: Option<RustcDeprecation>,
pub rustc_const_unstable: Option<RustcConstUnstable>,
}
/// The available stability levels.
......@@ -659,6 +660,11 @@ pub struct RustcDeprecation {
pub reason: Symbol,
}
#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
pub struct RustcConstUnstable {
pub feature: Symbol,
}
#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
pub struct Deprecation {
pub since: Option<Symbol>,
......@@ -678,9 +684,15 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
{
let mut stab: Option<Stability> = None;
let mut rustc_depr: Option<RustcDeprecation> = None;
let mut rustc_const_unstable: Option<RustcConstUnstable> = None;
'outer: for attr in attrs_iter {
if attr.path != "rustc_deprecated" && attr.path != "unstable" && attr.path != "stable" {
if ![
"rustc_deprecated",
"rustc_const_unstable",
"unstable",
"stable",
].iter().any(|&s| attr.path == s) {
continue // not a stability level
}
......@@ -703,21 +715,18 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
}
};
match &*meta.name.as_str() {
"rustc_deprecated" => {
if rustc_depr.is_some() {
span_err!(diagnostic, item_sp, E0540,
"multiple rustc_deprecated attributes");
break
}
let mut since = None;
let mut reason = None;
macro_rules! get_meta {
($($name:ident),+) => {
$(
let mut $name = None;
)+
for meta in metas {
if let Some(mi) = meta.meta_item() {
match &*mi.name().as_str() {
"since" => if !get(mi, &mut since) { continue 'outer },
"reason" => if !get(mi, &mut reason) { continue 'outer },
$(
stringify!($name)
=> if !get(mi, &mut $name) { continue 'outer },
)+
_ => {
handle_errors(diagnostic, mi.span,
AttrError::UnknownMetaItem(mi.name()));
......@@ -729,6 +738,18 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
continue 'outer
}
}
}
}
match &*meta.name.as_str() {
"rustc_deprecated" => {
if rustc_depr.is_some() {
span_err!(diagnostic, item_sp, E0540,
"multiple rustc_deprecated attributes");
continue 'outer
}
get_meta!(since, reason);
match (since, reason) {
(Some(since), Some(reason)) => {
......@@ -747,6 +768,23 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
}
}
}
"rustc_const_unstable" => {
if rustc_const_unstable.is_some() {
span_err!(diagnostic, item_sp, E0553,
"multiple rustc_const_unstable attributes");
continue 'outer
}
get_meta!(feature);
if let Some(feature) = feature {
rustc_const_unstable = Some(RustcConstUnstable {
feature
});
} else {
span_err!(diagnostic, attr.span(), E0629, "missing 'feature'");
continue
}
}
"unstable" => {
if stab.is_some() {
handle_errors(diagnostic, attr.span(), AttrError::MultipleStabilityLevels);
......@@ -791,6 +829,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
},
feature,
rustc_depr: None,
rustc_const_unstable: None,
})
}
(None, _, _) => {
......@@ -836,6 +875,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
},
feature,
rustc_depr: None,
rustc_const_unstable: None,
})
}
(None, _) => {
......@@ -867,6 +907,17 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
}
}
// Merge the const-unstable info into the stability info
if let Some(rustc_const_unstable) = rustc_const_unstable {
if let Some(ref mut stab) = stab {
stab.rustc_const_unstable = Some(rustc_const_unstable);
} else {
span_err!(diagnostic, item_sp, E0630,
"rustc_const_unstable attribute must be paired with \
either stable or unstable attribute");
}
}
stab
}
......
......@@ -357,8 +357,11 @@ fn main() {
E0549, // rustc_deprecated attribute must be paired with either stable or unstable attribute
E0550, // multiple deprecated attributes
E0551, // incorrect meta item
E0553, // multiple rustc_const_unstable attributes
E0555, // malformed feature attribute, expected #![feature(...)]
E0556, // malformed feature, expected just one word
E0584, // file for module `..` found at both .. and ..
E0589, // invalid `repr(align)` attribute
E0629, // missing 'feature' (rustc_const_unstable)
E0630, // rustc_const_unstable attribute must be paired with stable/unstable attribute
}
......@@ -137,6 +137,7 @@ pub fn new() -> Features {
// rustc internal
(active, rustc_diagnostic_macros, "1.0.0", None),
(active, rustc_const_unstable, "1.0.0", None),
(active, advanced_slice_patterns, "1.0.0", Some(23121)),
(active, box_syntax, "1.0.0", Some(27779)),
(active, placement_in_syntax, "1.0.0", Some(27779)),
......@@ -622,6 +623,11 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
"the `#[rustc_on_unimplemented]` attribute \
is an experimental feature",
cfg_fn!(on_unimplemented))),
("rustc_const_unstable", Normal, Gated(Stability::Unstable,
"rustc_const_unstable",
"the `#[rustc_const_unstable]` attribute \
is an internal feature",
cfg_fn!(rustc_const_unstable))),
("global_allocator", Normal, Gated(Stability::Unstable,
"global_allocator",
"the `#[global_allocator]` attribute is \
......
// 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.
// Test use of const fns in std using individual feature gates.
use std::cell::Cell;
const CELL: Cell<i32> = Cell::new(42); //~ERROR not yet stable as a const fn
//~^HELP #![feature(const_cell_new)]
fn main() {
let v = CELL.get();
CELL.set(v+1);
assert_eq!(CELL.get(), v);
}
// 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.
// Test internal const fn feature gate.
#![feature(staged_api)]
#![feature(const_fn)]
//#![feature(rustc_const_unstable)]
#[stable(feature="zing", since="1.0.0")]
#[rustc_const_unstable(feature="fzzzzzt")] //~ERROR internal feature
pub const fn bazinga() {}
fn main() {
}
......@@ -10,7 +10,7 @@
// Various checks that stability attributes are used correctly, per RFC 507
#![feature(staged_api)]
#![feature(const_fn, staged_api, rustc_const_unstable)]
#![stable(feature = "rust1", since = "1.0.0")]
......@@ -88,8 +88,11 @@ fn multiple3() { }
#[stable(feature = "a", since = "b")]
#[rustc_deprecated(since = "b", reason = "text")]
#[rustc_deprecated(since = "b", reason = "text")]
fn multiple4() { } //~ ERROR multiple rustc_deprecated attributes [E0540]
#[rustc_const_unstable(feature = "a")]
#[rustc_const_unstable(feature = "b")]
pub const fn multiple4() { } //~ ERROR multiple rustc_deprecated attributes [E0540]
//~^ ERROR Invalid stability or deprecation version found
//~| ERROR multiple rustc_const_unstable attributes
#[rustc_deprecated(since = "a", reason = "text")]
fn deprecated_without_unstable_or_stable() { }
......
// 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.
// Test use of const fns in std using individual feature gates.
#![feature(const_cell_new)]
use std::cell::Cell;
const CELL: Cell<i32> = Cell::new(42);
fn main() {
let v = CELL.get();
CELL.set(v+1);
assert_eq!(CELL.get(), v);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册