Skip to content

Commit 8c07822

Browse files
committed
---
yaml --- r: 133819 b: refs/heads/snap-stage3 c: b88d103 h: refs/heads/master i: 133817: 8bb756d 133815: 70edea2 v: v3
1 parent e9e16ad commit 8c07822

File tree

11 files changed

+189
-67
lines changed

11 files changed

+189
-67
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
refs/heads/master: 0e784e16840e8a0c623cc6166de26da9334db3d6
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
4-
refs/heads/snap-stage3: 3a54a4ee6bb9e0ab02c2556f029c288dda3c3de1
4+
refs/heads/snap-stage3: b88d1030e11410d64b8e6c16e3b8de8b4a8efbbd
55
refs/heads/try: 777654cfccbfa39bc7f671d8e9629018ed8ca12d
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b

branches/snap-stage3/src/librustc/driver/driver.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,9 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
414414
let stability_index = time(time_passes, "stability index", (), |_|
415415
stability::Index::build(krate));
416416

417+
time(time_passes, "static item recursion checking", (), |_|
418+
middle::check_static_recursion::check_crate(&sess, krate, &def_map, &ast_map));
419+
417420
let ty_cx = ty::mk_ctxt(sess,
418421
type_arena,
419422
def_map,

branches/snap-stage3/src/librustc/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ pub mod middle {
8080
pub mod borrowck;
8181
pub mod cfg;
8282
pub mod check_const;
83+
pub mod check_static_recursion;
8384
pub mod check_loop;
8485
pub mod check_match;
8586
pub mod check_rvalues;

branches/snap-stage3/src/librustc/middle/check_const.rs

Lines changed: 1 addition & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,13 @@
99
// except according to those terms.
1010

1111

12-
use driver::session::Session;
1312
use middle::def::*;
14-
use middle::resolve;
1513
use middle::ty;
1614
use middle::typeck;
1715
use util::ppaux;
1816

1917
use syntax::ast::*;
20-
use syntax::{ast_util, ast_map};
18+
use syntax::ast_util;
2119
use syntax::visit::Visitor;
2220
use syntax::visit;
2321

@@ -63,7 +61,6 @@ fn check_item(v: &mut CheckCrateVisitor, it: &Item) {
6361
match it.node {
6462
ItemStatic(_, _, ref ex) => {
6563
v.inside_const(|v| v.visit_expr(&**ex));
66-
check_item_recursion(&v.tcx.sess, &v.tcx.map, &v.tcx.def_map, it);
6764
}
6865
ItemEnum(ref enum_definition, _) => {
6966
for var in (*enum_definition).variants.iter() {
@@ -214,55 +211,3 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr) {
214211
}
215212
visit::walk_expr(v, e);
216213
}
217-
218-
struct CheckItemRecursionVisitor<'a, 'ast: 'a> {
219-
root_it: &'a Item,
220-
sess: &'a Session,
221-
ast_map: &'a ast_map::Map<'ast>,
222-
def_map: &'a resolve::DefMap,
223-
idstack: Vec<NodeId>
224-
}
225-
226-
// Make sure a const item doesn't recursively refer to itself
227-
// FIXME: Should use the dependency graph when it's available (#1356)
228-
pub fn check_item_recursion<'a>(sess: &'a Session,
229-
ast_map: &'a ast_map::Map,
230-
def_map: &'a resolve::DefMap,
231-
it: &'a Item) {
232-
233-
let mut visitor = CheckItemRecursionVisitor {
234-
root_it: it,
235-
sess: sess,
236-
ast_map: ast_map,
237-
def_map: def_map,
238-
idstack: Vec::new()
239-
};
240-
visitor.visit_item(it);
241-
}
242-
243-
impl<'a, 'ast, 'v> Visitor<'v> for CheckItemRecursionVisitor<'a, 'ast> {
244-
fn visit_item(&mut self, it: &Item) {
245-
if self.idstack.iter().any(|x| x == &(it.id)) {
246-
self.sess.span_fatal(self.root_it.span, "recursive constant");
247-
}
248-
self.idstack.push(it.id);
249-
visit::walk_item(self, it);
250-
self.idstack.pop();
251-
}
252-
253-
fn visit_expr(&mut self, e: &Expr) {
254-
match e.node {
255-
ExprPath(..) => {
256-
match self.def_map.borrow().find(&e.id) {
257-
Some(&DefStatic(def_id, _)) if
258-
ast_util::is_local(def_id) => {
259-
self.visit_item(&*self.ast_map.expect_item(def_id.node));
260-
}
261-
_ => ()
262-
}
263-
},
264-
_ => ()
265-
}
266-
visit::walk_expr(self, e);
267-
}
268-
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// This compiler pass detects static items that refer to themselves
12+
// recursively.
13+
14+
use driver::session::Session;
15+
use middle::resolve;
16+
use middle::def::DefStatic;
17+
18+
use syntax::ast::{Crate, Expr, ExprPath, Item, ItemStatic, NodeId};
19+
use syntax::{ast_util, ast_map};
20+
use syntax::visit::Visitor;
21+
use syntax::visit;
22+
23+
struct CheckCrateVisitor<'a, 'ast: 'a> {
24+
sess: &'a Session,
25+
def_map: &'a resolve::DefMap,
26+
ast_map: &'a ast_map::Map<'ast>
27+
}
28+
29+
impl<'v, 'a, 'ast> Visitor<'v> for CheckCrateVisitor<'a, 'ast> {
30+
fn visit_item(&mut self, i: &Item) {
31+
check_item(self, i);
32+
}
33+
}
34+
35+
pub fn check_crate<'ast>(sess: &Session,
36+
krate: &Crate,
37+
def_map: &resolve::DefMap,
38+
ast_map: &ast_map::Map<'ast>) {
39+
let mut visitor = CheckCrateVisitor {
40+
sess: sess,
41+
def_map: def_map,
42+
ast_map: ast_map
43+
};
44+
visit::walk_crate(&mut visitor, krate);
45+
sess.abort_if_errors();
46+
}
47+
48+
fn check_item(v: &mut CheckCrateVisitor, it: &Item) {
49+
match it.node {
50+
ItemStatic(_, _, ref ex) => {
51+
check_item_recursion(v.sess, v.ast_map, v.def_map, it);
52+
visit::walk_expr(v, &**ex)
53+
},
54+
_ => visit::walk_item(v, it)
55+
}
56+
}
57+
58+
struct CheckItemRecursionVisitor<'a, 'ast: 'a> {
59+
root_it: &'a Item,
60+
sess: &'a Session,
61+
ast_map: &'a ast_map::Map<'ast>,
62+
def_map: &'a resolve::DefMap,
63+
idstack: Vec<NodeId>
64+
}
65+
66+
// Make sure a const item doesn't recursively refer to itself
67+
// FIXME: Should use the dependency graph when it's available (#1356)
68+
pub fn check_item_recursion<'a>(sess: &'a Session,
69+
ast_map: &'a ast_map::Map,
70+
def_map: &'a resolve::DefMap,
71+
it: &'a Item) {
72+
73+
let mut visitor = CheckItemRecursionVisitor {
74+
root_it: it,
75+
sess: sess,
76+
ast_map: ast_map,
77+
def_map: def_map,
78+
idstack: Vec::new()
79+
};
80+
visitor.visit_item(it);
81+
}
82+
83+
impl<'a, 'ast, 'v> Visitor<'v> for CheckItemRecursionVisitor<'a, 'ast> {
84+
fn visit_item(&mut self, it: &Item) {
85+
if self.idstack.iter().any(|x| x == &(it.id)) {
86+
self.sess.span_err(self.root_it.span, "recursive constant");
87+
return;
88+
}
89+
self.idstack.push(it.id);
90+
visit::walk_item(self, it);
91+
self.idstack.pop();
92+
}
93+
94+
fn visit_expr(&mut self, e: &Expr) {
95+
match e.node {
96+
ExprPath(..) => {
97+
match self.def_map.borrow().find(&e.id) {
98+
Some(&DefStatic(def_id, _)) if
99+
ast_util::is_local(def_id) => {
100+
self.visit_item(&*self.ast_map.expect_item(def_id.node));
101+
}
102+
_ => ()
103+
}
104+
},
105+
_ => ()
106+
}
107+
visit::walk_expr(self, e);
108+
}
109+
}

branches/snap-stage3/src/libsyntax/parse/parser.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4140,20 +4140,20 @@ impl<'a> Parser<'a> {
41404140
(optional_unboxed_closure_kind, args)
41414141
}
41424142
};
4143-
let output = if self.eat(&token::RARROW) {
4144-
self.parse_ty(true)
4143+
let (style, output) = if self.token == token::RARROW {
4144+
self.parse_ret_ty()
41454145
} else {
4146-
P(Ty {
4146+
(Return, P(Ty {
41474147
id: ast::DUMMY_NODE_ID,
41484148
node: TyInfer,
41494149
span: self.span,
4150-
})
4150+
}))
41514151
};
41524152

41534153
(P(FnDecl {
41544154
inputs: inputs_captures,
41554155
output: output,
4156-
cf: Return,
4156+
cf: style,
41574157
variadic: false
41584158
}), optional_unboxed_closure_kind)
41594159
}
@@ -4166,20 +4166,20 @@ impl<'a> Parser<'a> {
41664166
seq_sep_trailing_allowed(token::COMMA),
41674167
|p| p.parse_fn_block_arg());
41684168

4169-
let output = if self.eat(&token::RARROW) {
4170-
self.parse_ty(true)
4169+
let (style, output) = if self.token == token::RARROW {
4170+
self.parse_ret_ty()
41714171
} else {
4172-
P(Ty {
4172+
(Return, P(Ty {
41734173
id: ast::DUMMY_NODE_ID,
41744174
node: TyInfer,
41754175
span: self.span,
4176-
})
4176+
}))
41774177
};
41784178

41794179
P(FnDecl {
41804180
inputs: inputs,
41814181
output: output,
4182-
cf: Return,
4182+
cf: style,
41834183
variadic: false
41844184
})
41854185
}

branches/snap-stage3/src/test/compile-fail/closure-that-fails.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,8 @@ fn foo(f: || -> !) {}
1313
fn main() {
1414
// Type inference didn't use to be able to handle this:
1515
foo(|| fail!());
16+
foo(|| -> ! fail!());
1617
foo(|| 22); //~ ERROR mismatched types
18+
foo(|| -> ! 22); //~ ERROR mismatched types
19+
let x = || -> ! 1; //~ ERROR mismatched types
1720
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![deny(unreachable_code)]
12+
13+
fn main() {
14+
let x: || -> ! = || fail!();
15+
x();
16+
println!("Foo bar"); //~ ERROR: unreachable statement
17+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
static FOO: uint = FOO; //~ ERROR recursive constant
12+
13+
fn main() {
14+
let _x: [u8, ..FOO]; // caused stack overflow prior to fix
15+
let _y: uint = 1 + {
16+
static BAR: uint = BAR; //~ ERROR recursive constant
17+
let _z: [u8, ..BAR]; // caused stack overflow prior to fix
18+
1
19+
};
20+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![allow(dead_code)]
12+
13+
fn f(x: || -> !) -> ! {
14+
x();
15+
}
16+
17+
fn main() {
18+
let x: || -> ! = || fail!();
19+
let _y: || -> ! = || x();
20+
}

branches/snap-stage3/src/test/run-pass/closure-syntax.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ fn bar<'b>() {
7878

7979
let a = A;
8080
a.foo::<<'a>||>();
81+
82+
// issue #13490
83+
let _ = || -> ! loop {};
84+
let _ = proc() -> ! loop {};
8185
}
8286

8387
struct B<T>;

0 commit comments

Comments
 (0)