Add static_recursion feature gate.
This commit is contained in:
parent
8ebf95257b
commit
742e1242d9
4 changed files with 50 additions and 4 deletions
|
@ -8,16 +8,17 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// 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.
|
// recursively.
|
||||||
|
|
||||||
use ast_map;
|
use ast_map;
|
||||||
use session::Session;
|
use session::Session;
|
||||||
use middle::def::{DefConst, DefAssociatedConst, DefVariant, DefMap};
|
use middle::def::{DefStatic, DefConst, DefAssociatedConst, DefVariant, DefMap};
|
||||||
use util::nodemap::NodeMap;
|
use util::nodemap::NodeMap;
|
||||||
|
|
||||||
use syntax::{ast, ast_util};
|
use syntax::{ast, ast_util};
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
|
use syntax::feature_gate::emit_feature_err;
|
||||||
use syntax::visit::Visitor;
|
use syntax::visit::Visitor;
|
||||||
use syntax::visit;
|
use syntax::visit;
|
||||||
|
|
||||||
|
@ -37,6 +38,7 @@ struct CheckCrateVisitor<'a, 'ast: 'a> {
|
||||||
impl<'a, 'ast: 'a> Visitor<'ast> for CheckCrateVisitor<'a, 'ast> {
|
impl<'a, 'ast: 'a> Visitor<'ast> for CheckCrateVisitor<'a, 'ast> {
|
||||||
fn visit_item(&mut self, it: &'ast ast::Item) {
|
fn visit_item(&mut self, it: &'ast ast::Item) {
|
||||||
match it.node {
|
match it.node {
|
||||||
|
ast::ItemStatic(..) |
|
||||||
ast::ItemConst(..) => {
|
ast::ItemConst(..) => {
|
||||||
let mut recursion_visitor =
|
let mut recursion_visitor =
|
||||||
CheckItemRecursionVisitor::new(self, &it.span);
|
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)
|
fn with_item_id_pushed<F>(&mut self, id: ast::NodeId, f: F)
|
||||||
where F: Fn(&mut Self) {
|
where F: Fn(&mut Self) {
|
||||||
if self.idstack.iter().any(|x| *x == id) {
|
if self.idstack.iter().any(|&x| x == id) {
|
||||||
span_err!(self.sess, *self.root_span, E0265, "recursive constant");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
self.idstack.push(id);
|
self.idstack.push(id);
|
||||||
|
@ -216,6 +237,7 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> {
|
||||||
match e.node {
|
match e.node {
|
||||||
ast::ExprPath(..) => {
|
ast::ExprPath(..) => {
|
||||||
match self.def_map.borrow().get(&e.id).map(|d| d.base_def) {
|
match self.def_map.borrow().get(&e.id).map(|d| d.base_def) {
|
||||||
|
Some(DefStatic(def_id, _)) |
|
||||||
Some(DefAssociatedConst(def_id, _)) |
|
Some(DefAssociatedConst(def_id, _)) |
|
||||||
Some(DefConst(def_id))
|
Some(DefConst(def_id))
|
||||||
if ast_util::is_local(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.
|
// Allows using #[prelude_import] on glob `use` items.
|
||||||
("prelude_import", "1.2.0", Active),
|
("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)
|
// (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
|
/// #![feature] attrs for non-language (library) features
|
||||||
pub declared_lib_features: Vec<(InternedString, Span)>,
|
pub declared_lib_features: Vec<(InternedString, Span)>,
|
||||||
pub const_fn: bool,
|
pub const_fn: bool,
|
||||||
|
pub static_recursion: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Features {
|
impl Features {
|
||||||
|
@ -362,6 +366,7 @@ impl Features {
|
||||||
declared_stable_lang_features: Vec::new(),
|
declared_stable_lang_features: Vec::new(),
|
||||||
declared_lib_features: Vec::new(),
|
declared_lib_features: Vec::new(),
|
||||||
const_fn: false,
|
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_stable_lang_features: accepted_features,
|
||||||
declared_lib_features: unknown_features,
|
declared_lib_features: unknown_features,
|
||||||
const_fn: cx.has_feature("const_fn"),
|
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
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![feature(static_recursion)]
|
||||||
|
|
||||||
static mut S: *const u8 = unsafe { &S as *const *const u8 as *const u8 };
|
static mut S: *const u8 = unsafe { &S as *const *const u8 as *const u8 };
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
|
|
Loading…
Reference in a new issue