forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
move const block checks before lowering step
this makes sure the checks run before typeck (which might use the constant or const function to calculate an array length) and gives prettier error messages in case of for loops and such (since they aren't expanded yet).
- Loading branch information
Showing
15 changed files
with
310 additions
and
72 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
// Copyright 2012-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. | ||
|
||
//! Verifies that const fn arguments are immutable by value bindings | ||
//! and the const fn body doesn't contain any statements | ||
use rustc::session::Session; | ||
|
||
use syntax::ast; | ||
use syntax::visit::{self, Visitor, FnKind}; | ||
use syntax::codemap::Span; | ||
|
||
pub fn check_crate(sess: &Session, krate: &ast::Crate) { | ||
visit::walk_crate(&mut CheckConstFn{ sess: sess }, krate); | ||
sess.abort_if_errors(); | ||
} | ||
|
||
struct CheckConstFn<'a> { | ||
sess: &'a Session, | ||
} | ||
|
||
struct CheckBlock<'a> { | ||
sess: &'a Session, | ||
kind: &'static str, | ||
} | ||
|
||
impl<'a, 'v> Visitor<'v> for CheckBlock<'a> { | ||
fn visit_block(&mut self, block: &'v ast::Block) { | ||
check_block(&self.sess, block, self.kind); | ||
CheckConstFn{ sess: self.sess}.visit_block(block); | ||
} | ||
fn visit_expr(&mut self, e: &'v ast::Expr) { | ||
if let ast::ExprClosure(..) = e.node { | ||
CheckConstFn{ sess: self.sess}.visit_expr(e); | ||
} else { | ||
visit::walk_expr(self, e); | ||
} | ||
} | ||
fn visit_item(&mut self, _i: &'v ast::Item) { panic!("should be handled in CheckConstFn") } | ||
fn visit_fn(&mut self, | ||
_fk: FnKind<'v>, | ||
_fd: &'v ast::FnDecl, | ||
_b: &'v ast::Block, | ||
_s: Span, | ||
_fn_id: ast::NodeId) { panic!("should be handled in CheckConstFn") } | ||
} | ||
|
||
fn check_block(sess: &Session, b: &ast::Block, kind: &'static str) { | ||
// Check all statements in the block | ||
for stmt in &b.stmts { | ||
let span = match stmt.node { | ||
ast::StmtDecl(ref decl, _) => { | ||
match decl.node { | ||
ast::DeclLocal(_) => decl.span, | ||
|
||
// Item statements are allowed | ||
ast::DeclItem(_) => continue, | ||
} | ||
} | ||
ast::StmtExpr(ref expr, _) => expr.span, | ||
ast::StmtSemi(ref semi, _) => semi.span, | ||
ast::StmtMac(..) => unreachable!(), | ||
}; | ||
span_err!(sess, span, E0016, | ||
"blocks in {}s are limited to items and tail expressions", kind); | ||
} | ||
} | ||
|
||
impl<'a, 'v> Visitor<'v> for CheckConstFn<'a> { | ||
fn visit_item(&mut self, i: &'v ast::Item) { | ||
visit::walk_item(self, i); | ||
match i.node { | ||
ast::ItemConst(_, ref e) => { | ||
CheckBlock{ sess: self.sess, kind: "constant"}.visit_expr(e) | ||
}, | ||
ast::ItemStatic(_, _, ref e) => { | ||
CheckBlock{ sess: self.sess, kind: "static"}.visit_expr(e) | ||
}, | ||
_ => {}, | ||
} | ||
} | ||
|
||
fn visit_fn(&mut self, | ||
fk: FnKind<'v>, | ||
fd: &'v ast::FnDecl, | ||
b: &'v ast::Block, | ||
s: Span, | ||
_fn_id: ast::NodeId) { | ||
visit::walk_fn(self, fk, fd, b, s); | ||
match fk { | ||
FnKind::ItemFn(_, _, _, ast::Constness::Const, _, _) => {}, | ||
FnKind::Method(_, m, _) if m.constness == ast::Constness::Const => {}, | ||
_ => return, | ||
} | ||
|
||
// Ensure the arguments are simple, not mutable/by-ref or patterns. | ||
for arg in &fd.inputs { | ||
match arg.pat.node { | ||
ast::PatWild => {} | ||
ast::PatIdent(ast::BindingMode::ByValue(ast::MutImmutable), _, None) => {} | ||
_ => { | ||
span_err!(self.sess, arg.pat.span, E0022, | ||
"arguments of constant functions can only \ | ||
be immutable by-value bindings"); | ||
} | ||
} | ||
} | ||
check_block(&self.sess, b, "const function"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// 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. | ||
|
||
#![allow(non_snake_case)] | ||
|
||
register_long_diagnostics! { | ||
E0016: r##" | ||
Blocks in constants may only contain items (such as constant, function | ||
definition, etc...) and a tail expression. Example: | ||
``` | ||
const FOO: i32 = { let x = 0; x }; // 'x' isn't an item! | ||
``` | ||
To avoid it, you have to replace the non-item object: | ||
``` | ||
const FOO: i32 = { const X : i32 = 0; X }; | ||
``` | ||
"##, | ||
|
||
E0022: r##" | ||
Constant functions are not allowed to mutate anything. Thus, binding to an | ||
argument with a mutable pattern is not allowed. For example, | ||
``` | ||
const fn foo(mut x: u8) { | ||
// do stuff | ||
} | ||
``` | ||
is bad because the function body may not mutate `x`. | ||
Remove any mutable bindings from the argument list to fix this error. In case | ||
you need to mutate the argument, try lazily initializing a global variable | ||
instead of using a `const fn`, or refactoring the code to a functional style to | ||
avoid mutation if possible. | ||
"##, | ||
} | ||
|
||
register_diagnostics! { | ||
E0472, // asm! is unsupported on this target | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// Copyright 2012-2013 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. | ||
|
||
//! Various checks | ||
//! | ||
//! # Note | ||
//! | ||
//! This API is completely unstable and subject to change. | ||
#![crate_name = "rustc_passes"] | ||
#![unstable(feature = "rustc_private", issue = "27812")] | ||
#![crate_type = "dylib"] | ||
#![crate_type = "rlib"] | ||
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", | ||
html_favicon_url = "https://doc.rust-lang.org/favicon.ico", | ||
html_root_url = "https://doc.rust-lang.org/nightly/")] | ||
|
||
#![feature(rustc_diagnostic_macros)] | ||
#![feature(staged_api)] | ||
#![feature(rustc_private)] | ||
|
||
extern crate core; | ||
extern crate rustc; | ||
|
||
#[macro_use] extern crate syntax; | ||
|
||
pub mod diagnostics; | ||
pub mod const_fn; | ||
pub mod no_asm; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.