Add static_recursion feature gate.
This commit is contained in:
parent
8ebf95257b
commit
742e1242d9
@ -8,16 +8,17 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// This compiler pass detects static items that refer to themselves
|
||||
// This compiler pass detects constants that refer to themselves
|
||||
// recursively.
|
||||
|
||||
use ast_map;
|
||||
use session::Session;
|
||||
use middle::def::{DefConst, DefAssociatedConst, DefVariant, DefMap};
|
||||
use middle::def::{DefStatic, DefConst, DefAssociatedConst, DefVariant, DefMap};
|
||||
use util::nodemap::NodeMap;
|
||||
|
||||
use syntax::{ast, ast_util};
|
||||
use syntax::codemap::Span;
|
||||
use syntax::feature_gate::emit_feature_err;
|
||||
use syntax::visit::Visitor;
|
||||
use syntax::visit;
|
||||
|
||||
@ -37,6 +38,7 @@ struct CheckCrateVisitor<'a, 'ast: 'a> {
|
||||
impl<'a, 'ast: 'a> Visitor<'ast> for CheckCrateVisitor<'a, 'ast> {
|
||||
fn visit_item(&mut self, it: &'ast ast::Item) {
|
||||
match it.node {
|
||||
ast::ItemStatic(..) |
|
||||
ast::ItemConst(..) => {
|
||||
let mut recursion_visitor =
|
||||
CheckItemRecursionVisitor::new(self, &it.span);
|
||||
@ -124,8 +126,27 @@ impl<'a, 'ast: 'a> CheckItemRecursionVisitor<'a, 'ast> {
|
||||
}
|
||||
fn with_item_id_pushed<F>(&mut self, id: ast::NodeId, f: F)
|
||||
where F: Fn(&mut Self) {
|
||||
if self.idstack.iter().any(|x| *x == id) {
|
||||
span_err!(self.sess, *self.root_span, E0265, "recursive constant");
|
||||
if self.idstack.iter().any(|&x| x == id) {
|
||||
let any_static = self.idstack.iter().any(|&x| {
|
||||
if let ast_map::NodeItem(item) = self.ast_map.get(x) {
|
||||
if let ast::ItemStatic(..) = item.node {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
if any_static {
|
||||
if !self.sess.features.borrow().static_recursion {
|
||||
emit_feature_err(&self.sess.parse_sess.span_diagnostic,
|
||||
"static_recursion",
|
||||
*self.root_span, "recursive static");
|
||||
}
|
||||
} else {
|
||||
span_err!(self.sess, *self.root_span, E0265, "recursive constant");
|
||||
}
|
||||
return;
|
||||
}
|
||||
self.idstack.push(id);
|
||||
@ -216,6 +237,7 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> {
|
||||
match e.node {
|
||||
ast::ExprPath(..) => {
|
||||
match self.def_map.borrow().get(&e.id).map(|d| d.base_def) {
|
||||
Some(DefStatic(def_id, _)) |
|
||||
Some(DefAssociatedConst(def_id, _)) |
|
||||
Some(DefConst(def_id))
|
||||
if ast_util::is_local(def_id) => {
|
||||
|
@ -160,6 +160,9 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[
|
||||
|
||||
// Allows using #[prelude_import] on glob `use` items.
|
||||
("prelude_import", "1.2.0", Active),
|
||||
|
||||
// Allows the definition recursive static items.
|
||||
("static_recursion", "1.3.0", Active),
|
||||
];
|
||||
// (changing above list without updating src/doc/reference.md makes @cmr sad)
|
||||
|
||||
@ -338,6 +341,7 @@ pub struct Features {
|
||||
/// #![feature] attrs for non-language (library) features
|
||||
pub declared_lib_features: Vec<(InternedString, Span)>,
|
||||
pub const_fn: bool,
|
||||
pub static_recursion: bool
|
||||
}
|
||||
|
||||
impl Features {
|
||||
@ -362,6 +366,7 @@ impl Features {
|
||||
declared_stable_lang_features: Vec::new(),
|
||||
declared_lib_features: Vec::new(),
|
||||
const_fn: false,
|
||||
static_recursion: false
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -859,6 +864,7 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler,
|
||||
declared_stable_lang_features: accepted_features,
|
||||
declared_lib_features: unknown_features,
|
||||
const_fn: cx.has_feature("const_fn"),
|
||||
static_recursion: cx.has_feature("static_recursion")
|
||||
}
|
||||
}
|
||||
|
||||
|
16
src/test/compile-fail/static-recursion-gate.rs
Normal file
16
src/test/compile-fail/static-recursion-gate.rs
Normal 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.
|
||||
|
||||
static mut S: *const u8 = unsafe { &S as *const *const u8 as *const u8 };
|
||||
//~^ ERROR recursive static
|
||||
|
||||
pub fn main() {
|
||||
unsafe { assert_eq!(S, *(S as *const *const u8)); }
|
||||
}
|
@ -8,6 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(static_recursion)]
|
||||
|
||||
static mut S: *const u8 = unsafe { &S as *const *const u8 as *const u8 };
|
||||
|
||||
pub fn main() {
|
||||
|
Loading…
Reference in New Issue
Block a user