Skip to content

Increase monomorphization depth limit #5077

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/librustc/middle/trans/monomorphize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,9 @@ pub fn monomorphic_fn(ccx: @CrateContext,

let depth = option::get_or_default(ccx.monomorphizing.find(&fn_id), 0u);
// Random cut-off -- code that needs to instantiate the same function
// recursively more than ten times can probably safely be assumed to be
// recursively more than thirty times can probably safely be assumed to be
// causing an infinite expansion.
if depth > 10 {
if depth > 30 {
ccx.sess.span_fatal(
span, ~"overly deep expansion of inlined function");
}
Expand Down
2 changes: 0 additions & 2 deletions src/libstd/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1294,8 +1294,6 @@ mod tests {
}
}

// testing both auto_encode's calling patterns
// and json... not sure where to put these tests.
#[test]
fn test_write_enum () {
let bw = @io::BytesWriter();
Expand Down
28 changes: 17 additions & 11 deletions src/libsyntax/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,9 @@ use std::term;
pub type Emitter = fn@(cmsp: Option<(@codemap::CodeMap, span)>,
msg: &str, lvl: level);


pub trait span_handler {
fn span_fatal(@mut self, sp: span, msg: &str) -> !;
fn span_err(@mut self, sp: span, msg: &str);
fn span_warn(@mut self, sp: span, msg: &str);
fn span_note(@mut self, sp: span, msg: &str);
fn span_bug(@mut self, sp: span, msg: &str) -> !;
fn span_unimpl(@mut self, sp: span, msg: &str) -> !;
fn handler(@mut self) -> handler;
}

// a handler deals with errors; certain errors
// (fatal, bug, unimpl) may cause immediate exit,
// others log errors for later reporting.
pub trait handler {
fn fatal(@mut self, msg: &str) -> !;
fn err(@mut self, msg: &str);
Expand All @@ -45,6 +37,7 @@ pub trait handler {
fn abort_if_errors(@mut self);
fn warn(@mut self, msg: &str);
fn note(@mut self, msg: &str);
// used to indicate a bug in the compiler:
fn bug(@mut self, msg: &str) -> !;
fn unimpl(@mut self, msg: &str) -> !;
fn emit(@mut self,
Expand All @@ -53,6 +46,19 @@ pub trait handler {
lvl: level);
}

// a span-handler is like a handler but also
// accepts span information for source-location
// reporting.
pub trait span_handler {
fn span_fatal(@mut self, sp: span, msg: &str) -> !;
fn span_err(@mut self, sp: span, msg: &str);
fn span_warn(@mut self, sp: span, msg: &str);
fn span_note(@mut self, sp: span, msg: &str);
fn span_bug(@mut self, sp: span, msg: &str) -> !;
fn span_unimpl(@mut self, sp: span, msg: &str) -> !;
fn handler(@mut self) -> handler;
}

struct HandlerT {
err_count: uint,
emit: Emitter,
Expand Down
4 changes: 4 additions & 0 deletions src/libsyntax/parse/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use parse::token;

use core::either::{Either, Left, Right};

// a parser that can parse attributes.
pub trait parser_attr {
fn parse_outer_attributes() -> ~[ast::attribute];
fn parse_attribute(style: ast::attr_style) -> ast::attribute;
Expand Down Expand Up @@ -81,6 +82,9 @@ impl parser_attr for Parser {
// attribute of the next item (since we can't know whether the attribute
// is an inner attribute of the containing item or an outer attribute of
// the first contained item until we see the semi).

// you can make the 'next' field an Option, but the result is going to be
// more useful as a vector.
fn parse_inner_attrs_and_next() ->
(~[ast::attribute], ~[ast::attribute]) {
let mut inner_attrs: ~[ast::attribute] = ~[];
Expand Down
23 changes: 16 additions & 7 deletions src/libsyntax/parse/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,18 @@ pub fn new_parse_sess_special_handler(sh: span_handler, cm: @codemap::CodeMap)
}
}

// a bunch of utility functions of the form parse_<thing>_from_<source>
// where <thing> includes crate, expr, item, stmt, tts, and one that
// uses a HOF to parse anything, and <source> includes file and
// source_str.

// this appears to be the main entry point for rust parsing by
// rustc and crate:
pub fn parse_crate_from_file(input: &Path, cfg: ast::crate_cfg,
sess: @mut ParseSess) -> @ast::crate {
let p = new_crate_parser_from_file(sess, cfg, input);
let r = p.parse_crate_mod(cfg);
return r;
let p = new_parser_from_file(sess, cfg, input);
p.parse_crate_mod(cfg)
// why is there no p.abort_if_errors here?
}

pub fn parse_crate_from_source_str(name: ~str,
Expand Down Expand Up @@ -174,7 +181,9 @@ pub fn new_parser_from_source_str(sess: @mut ParseSess, cfg: ast::crate_cfg,
return Parser(sess, cfg, srdr as reader);
}

pub fn new_parser_from_file(sess: @mut ParseSess,
// Read the entire source file, return a parser
// that draws from that string
pub fn new_parser_result_from_file(sess: @mut ParseSess,
cfg: ast::crate_cfg,
path: &Path)
-> Result<Parser, ~str> {
Expand All @@ -194,9 +203,9 @@ pub fn new_parser_from_file(sess: @mut ParseSess,

/// Create a new parser for an entire crate, handling errors as appropriate
/// if the file doesn't exist
pub fn new_crate_parser_from_file(sess: @mut ParseSess, cfg: ast::crate_cfg,
pub fn new_parser_from_file(sess: @mut ParseSess, cfg: ast::crate_cfg,
path: &Path) -> Parser {
match new_parser_from_file(sess, cfg, path) {
match new_parser_result_from_file(sess, cfg, path) {
Ok(parser) => parser,
Err(e) => {
sess.span_diagnostic.handler().fatal(e)
Expand All @@ -208,7 +217,7 @@ pub fn new_crate_parser_from_file(sess: @mut ParseSess, cfg: ast::crate_cfg,
/// error messages correctly when the file does not exist.
pub fn new_sub_parser_from_file(sess: @mut ParseSess, cfg: ast::crate_cfg,
path: &Path, sp: span) -> Parser {
match new_parser_from_file(sess, cfg, path) {
match new_parser_result_from_file(sess, cfg, path) {
Ok(parser) => parser,
Err(e) => {
sess.span_diagnostic.span_fatal(sp, e)
Expand Down
41 changes: 38 additions & 3 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ type arg_or_capture_item = Either<arg, ()>;
type item_info = (ident, item_, Option<~[attribute]>);

pub enum item_or_view_item {
// indicates a failure to parse any kind of item:
iovi_none,
iovi_item(@item),
iovi_foreign_item(@foreign_item),
Expand Down Expand Up @@ -2666,7 +2667,8 @@ pub impl Parser {
_ => None
}
}
_ => fail!()
_ => self.bug(
~"is_ident() said this would be an identifier")
};

match maybe_bound {
Expand Down Expand Up @@ -3204,9 +3206,12 @@ pub impl Parser {
self.eat_keyword(~"static")
}

// given a termination token and a vector of already-parsed
// attributes (of length 0 or 1), parse all of the items in a module
fn parse_mod_items(term: token::Token,
+first_item_attrs: ~[attribute]) -> _mod {
// Shouldn't be any view items since we've already parsed an item attr
// parse all of the items up to closing or an attribute.
// view items are legal here.
let ParsedItemsAndViewItems {
attrs_remaining: attrs_remaining,
view_items: view_items,
Expand All @@ -3217,6 +3222,9 @@ pub impl Parser {
true);
let mut items: ~[@item] = starting_items;

// looks like this code depends on the invariant that
// outer attributes can't occur on view items (or macros
// invocations?)
let mut first = true;
while self.token != term {
let mut attrs = self.parse_outer_attributes();
Expand Down Expand Up @@ -3751,6 +3759,8 @@ pub impl Parser {
}
}

// parse one of the items or view items allowed by the
// flags; on failure, return iovi_none.
fn parse_item_or_view_item(+attrs: ~[attribute], items_allowed: bool,
foreign_items_allowed: bool,
macros_allowed: bool)
Expand All @@ -3770,14 +3780,17 @@ pub impl Parser {
}

if items_allowed && self.eat_keyword(~"const") {
// CONST ITEM
let (ident, item_, extra_attrs) = self.parse_item_const();
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
visibility,
maybe_append(attrs, extra_attrs)));
} else if foreign_items_allowed && self.is_keyword(~"const") {
// FOREIGN CONST ITEM
let item = self.parse_item_foreign_const(visibility, attrs);
return iovi_foreign_item(item);
} else if items_allowed &&
// FUNCTION ITEM (not sure about lookahead condition...)
self.is_keyword(~"fn") &&
!self.fn_expr_lookahead(self.look_ahead(1u)) {
self.bump();
Expand All @@ -3786,6 +3799,7 @@ pub impl Parser {
visibility,
maybe_append(attrs, extra_attrs)));
} else if items_allowed && self.eat_keyword(~"pure") {
// PURE FUNCTION ITEM
self.expect_keyword(~"fn");
let (ident, item_, extra_attrs) = self.parse_item_fn(pure_fn);
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
Expand All @@ -3794,10 +3808,12 @@ pub impl Parser {
} else if foreign_items_allowed &&
(self.is_keyword(~"fn") || self.is_keyword(~"pure") ||
self.is_keyword(~"unsafe")) {
// FOREIGN FUNCTION ITEM (no items allowed)
let item = self.parse_item_foreign_fn(attrs);
return iovi_foreign_item(item);
} else if items_allowed && self.is_keyword(~"unsafe")
&& self.look_ahead(1u) != token::LBRACE {
// UNSAFE FUNCTION ITEM (where items are allowed)
self.bump();
self.expect_keyword(~"fn");
let (ident, item_, extra_attrs) = self.parse_item_fn(unsafe_fn);
Expand All @@ -3806,46 +3822,55 @@ pub impl Parser {
maybe_append(attrs, extra_attrs)));
} else if self.eat_keyword(~"extern") {
if items_allowed && self.eat_keyword(~"fn") {
// EXTERN FUNCTION ITEM
let (ident, item_, extra_attrs) =
self.parse_item_fn(extern_fn);
return iovi_item(self.mk_item(lo, self.last_span.hi, ident,
item_, visibility,
maybe_append(attrs,
extra_attrs)));
}
// EXTERN MODULE ITEM
return self.parse_item_foreign_mod(lo, visibility, attrs,
items_allowed);
} else if items_allowed && self.eat_keyword(~"mod") {
// MODULE ITEM
let (ident, item_, extra_attrs) = self.parse_item_mod(attrs);
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
visibility,
maybe_append(attrs, extra_attrs)));
} else if items_allowed && self.eat_keyword(~"type") {
// TYPE ITEM
let (ident, item_, extra_attrs) = self.parse_item_type();
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
visibility,
maybe_append(attrs, extra_attrs)));
} else if items_allowed && self.eat_keyword(~"enum") {
// ENUM ITEM
let (ident, item_, extra_attrs) = self.parse_item_enum();
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
visibility,
maybe_append(attrs, extra_attrs)));
} else if items_allowed && self.eat_keyword(~"trait") {
// TRAIT ITEM
let (ident, item_, extra_attrs) = self.parse_item_trait();
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
visibility,
maybe_append(attrs, extra_attrs)));
} else if items_allowed && self.eat_keyword(~"impl") {
// IMPL ITEM
let (ident, item_, extra_attrs) = self.parse_item_impl();
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
visibility,
maybe_append(attrs, extra_attrs)));
} else if items_allowed && self.eat_keyword(~"struct") {
// STRUCT ITEM
let (ident, item_, extra_attrs) = self.parse_item_struct();
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
visibility,
maybe_append(attrs, extra_attrs)));
} else if self.eat_keyword(~"use") {
// USE ITEM
let view_item = self.parse_use();
self.expect(token::SEMI);
return iovi_view_item(@ast::view_item {
Expand All @@ -3859,6 +3884,7 @@ pub impl Parser {
&& (is_plain_ident(self.look_ahead(2))
|| self.look_ahead(2) == token::LPAREN
|| self.look_ahead(2) == token::LBRACE) {
// MACRO INVOCATION ITEM
if attrs.len() > 0 {
self.fatal(~"attrs on macros are not yet supported");
}
Expand All @@ -3875,6 +3901,7 @@ pub impl Parser {
} else {
token::special_idents::invalid // no special identifier
};
// eat a matched-delimiter token tree:
let tts = match self.token {
token::LPAREN | token::LBRACE => {
let ket = token::flip_delimiter(copy self.token);
Expand All @@ -3884,6 +3911,7 @@ pub impl Parser {
}
_ => self.fatal(~"expected open delimiter")
};
// single-variant-enum... :
let m = ast::mac_invoc_tt(pth, tts);
let m: ast::mac = codemap::spanned { node: m,
span: mk_sp(self.span.lo,
Expand All @@ -3892,6 +3920,7 @@ pub impl Parser {
return iovi_item(self.mk_item(lo, self.last_span.hi, id, item_,
visibility, attrs));
} else {
// FAILURE TO PARSE ITEM
if visibility != inherited {
let mut s = ~"unmatched visibility `";
s += if visibility == public { ~"pub" } else { ~"priv" };
Expand Down Expand Up @@ -4030,6 +4059,7 @@ pub impl Parser {
self.token_is_keyword(~"mod", next_tok))
}

// parse a view item.
fn parse_view_item(+attrs: ~[attribute], vis: visibility) -> @view_item {
let lo = self.span.lo;
let node = if self.eat_keyword(~"use") {
Expand All @@ -4040,7 +4070,7 @@ pub impl Parser {
let metadata = self.parse_optional_meta();
view_item_extern_mod(ident, metadata, self.get_id())
} else {
fail!();
self.bug(~"expected view item");
};
self.expect(token::SEMI);
@ast::view_item { node: node,
Expand All @@ -4049,6 +4079,8 @@ pub impl Parser {
span: mk_sp(lo, self.last_span.hi) }
}

// Parses a sequence of items. Stops when it finds program
// text that can't be parsed as an item
fn parse_items_and_view_items(+first_item_attrs: ~[attribute],
mode: view_item_parse_mode,
macros_allowed: bool)
Expand Down Expand Up @@ -4114,8 +4146,11 @@ pub impl Parser {
// Parses a source module as a crate
fn parse_crate_mod(_cfg: crate_cfg) -> @crate {
let lo = self.span.lo;
// parse the crate's inner attrs, maybe (oops) one
// of the attrs of an item:
let (inner, next) = self.parse_inner_attrs_and_next();
let first_item_outer_attrs = next;
// parse the items inside the crate:
let m = self.parse_mod_items(token::EOF, first_item_outer_attrs);
@spanned(lo, self.span.lo,
ast::crate_ { module: m,
Expand Down