diff options
| author | Eduard Burtescu <edy.burt@gmail.com> | 2014-03-06 20:37:24 +0200 |
|---|---|---|
| committer | Eduard Burtescu <edy.burt@gmail.com> | 2014-03-13 14:21:45 +0200 |
| commit | 26398b4f6d7b9016f1ddb6c23b5090cd98f1fa2e (patch) | |
| tree | bb13c1add07637c54bf252ef00fbda6eda0bde8d | |
| parent | 20b4e159edb54cecb8abdedb187ba05a869b3bf0 (diff) | |
| download | rust-26398b4f6d7b9016f1ddb6c23b5090cd98f1fa2e.tar.gz rust-26398b4f6d7b9016f1ddb6c23b5090cd98f1fa2e.zip | |
Introduce a common recursion limit for auto-dereference and monomorphization.
| -rw-r--r-- | src/librustc/driver/driver.rs | 3 | ||||
| -rw-r--r-- | src/librustc/driver/session.rs | 6 | ||||
| -rw-r--r-- | src/librustc/middle/trans/monomorphize.rs | 8 | ||||
| -rw-r--r-- | src/librustc/middle/ty.rs | 31 | ||||
| -rw-r--r-- | src/librustc/middle/typeck/check/mod.rs | 27 | ||||
| -rw-r--r-- | src/test/compile-fail/infinite-autoderef.rs | 33 | ||||
| -rw-r--r-- | src/test/compile-fail/infinite-instantiation.rs | 2 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-8727.rs | 2 | ||||
| -rw-r--r-- | src/test/compile-fail/recursion.rs | 2 |
9 files changed, 56 insertions, 58 deletions
diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 6f2934d9138..10b209c998b 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -1020,7 +1020,8 @@ pub fn build_session_(sopts: @session::Options, lints: RefCell::new(HashMap::new()), node_id: Cell::new(1), crate_types: @RefCell::new(Vec::new()), - features: front::feature_gate::Features::new() + features: front::feature_gate::Features::new(), + recursion_limit: Cell::new(64), } } diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index 4845060dd12..b4e1516074e 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -194,7 +194,11 @@ pub struct Session_ { Vec<(lint::Lint, codemap::Span, ~str)> >>, node_id: Cell<ast::NodeId>, crate_types: @RefCell<Vec<CrateType> >, - features: front::feature_gate::Features + features: front::feature_gate::Features, + + /// The maximum recursion limit for potentially infinitely recursive + /// operations such as auto-dereference and monomorphization. + recursion_limit: Cell<uint>, } pub type Session = @Session_; diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index ecfc1aae3d9..b39bcfb075f 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -172,11 +172,11 @@ pub fn monomorphic_fn(ccx: @CrateContext, // Random cut-off -- code that needs to instantiate the same function // recursively more than thirty times can probably safely be assumed // to be causing an infinite expansion. - if depth > 30 { - ccx.sess.span_fatal( - ccx.tcx.map.span(fn_id.node), - "overly deep expansion of inlined function"); + if depth > ccx.sess.recursion_limit.get() { + ccx.sess.span_fatal(ccx.tcx.map.span(fn_id.node), + "reached the recursion limit during monomorphization"); } + monomorphizing.get().insert(fn_id, depth + 1); } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 33b24653934..9d0fb866916 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -3467,37 +3467,6 @@ pub fn param_tys_in_type(ty: t) -> Vec<param_ty> { rslt } -pub fn occurs_check(tcx: ctxt, sp: Span, vid: TyVid, rt: t) { - // Returns a vec of all the type variables occurring in `ty`. It may - // contain duplicates. (Integral type vars aren't counted.) - fn vars_in_type(ty: t) -> Vec<TyVid> { - let mut rslt = Vec::new(); - walk_ty(ty, |ty| { - match get(ty).sty { - ty_infer(TyVar(v)) => rslt.push(v), - _ => () - } - }); - rslt - } - - // Fast path - if !type_needs_infer(rt) { return; } - - // Occurs check! - if vars_in_type(rt).contains(&vid) { - // Maybe this should be span_err -- however, there's an - // assertion later on that the type doesn't contain - // variables, so in this case we have to be sure to die. - tcx.sess.span_fatal - (sp, ~"type inference failed because I \ - could not find a type\n that's both of the form " - + ::util::ppaux::ty_to_str(tcx, mk_var(tcx, vid)) + - " and of the form " + ::util::ppaux::ty_to_str(tcx, rt) + - " - such a type would have to be infinitely large."); - } -} - pub fn ty_sort_str(cx: ctxt, t: t) -> ~str { match get(t).sty { ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) | diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 7a51a2cc231..e3db7f16064 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -1241,7 +1241,7 @@ pub enum LvaluePreference { NoPreference } -pub fn autoderef<T>(fcx: @FnCtxt, sp: Span, t: ty::t, +pub fn autoderef<T>(fcx: @FnCtxt, sp: Span, base_ty: ty::t, expr_id: Option<ast::NodeId>, mut lvalue_pref: LvaluePreference, should_stop: |ty::t, uint| -> Option<T>) @@ -1253,24 +1253,10 @@ pub fn autoderef<T>(fcx: @FnCtxt, sp: Span, t: ty::t, * responsible for inserting an AutoAdjustment record into `tcx.adjustments` * so that trans/borrowck/etc know about this autoderef. */ - let mut t = t; - let mut autoderefs = 0; - loop { + let mut t = base_ty; + for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) { let resolved_t = structurally_resolved_type(fcx, sp, t); - // Some extra checks to detect weird cycles and so forth: - match ty::get(resolved_t).sty { - ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_rptr(_, _) => { - match ty::get(t).sty { - ty::ty_infer(ty::TyVar(v1)) => { - ty::occurs_check(fcx.ccx.tcx, sp, v1, resolved_t); - } - _ => {} - } - } - _ => { /*ok*/ } - } - match should_stop(resolved_t, autoderefs) { Some(x) => return (resolved_t, autoderefs, Some(x)), None => {} @@ -1291,11 +1277,16 @@ pub fn autoderef<T>(fcx: @FnCtxt, sp: Span, t: ty::t, if mt.mutbl == ast::MutImmutable { lvalue_pref = NoPreference; } - autoderefs += 1; } None => return (resolved_t, autoderefs, None) } } + + // We've reached the recursion limit, error gracefully. + fcx.tcx().sess.span_err(sp, + format!("reached the recursion limit while auto-dereferencing {}", + base_ty.repr(fcx.tcx()))); + (ty::mk_err(), 0, None) } fn try_overloaded_deref(fcx: @FnCtxt, diff --git a/src/test/compile-fail/infinite-autoderef.rs b/src/test/compile-fail/infinite-autoderef.rs new file mode 100644 index 00000000000..ddef459453e --- /dev/null +++ b/src/test/compile-fail/infinite-autoderef.rs @@ -0,0 +1,33 @@ +// Copyright 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. + +// error-pattern: reached the recursion limit while auto-dereferencing + +use std::ops::Deref; + +struct Foo; + +impl Deref<Foo> for Foo { + fn deref<'a>(&'a self) -> &'a Foo { + self + } +} + +pub fn main() { + let mut x; + loop { + x = ~x; + x.foo; + x.bar(); + } + + Foo.foo; + Foo.bar(); +} diff --git a/src/test/compile-fail/infinite-instantiation.rs b/src/test/compile-fail/infinite-instantiation.rs index 1a7cc5d3ad5..b8fa6285d99 100644 --- a/src/test/compile-fail/infinite-instantiation.rs +++ b/src/test/compile-fail/infinite-instantiation.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: overly deep expansion +// error-pattern: reached the recursion limit during monomorphization // issue 2258 trait to_opt { diff --git a/src/test/compile-fail/issue-8727.rs b/src/test/compile-fail/issue-8727.rs index 003f1d67cdb..fca59ed74ee 100644 --- a/src/test/compile-fail/issue-8727.rs +++ b/src/test/compile-fail/issue-8727.rs @@ -15,7 +15,7 @@ struct Data(~Option<Data>); fn generic<T>( _ : ~[(Data,T)] ) { - //~^ ERROR overly deep expansion of inlined function + //~^ ERROR reached the recursion limit during monomorphization let rec : ~[(Data,(bool,T))] = ~[]; generic( rec ); } diff --git a/src/test/compile-fail/recursion.rs b/src/test/compile-fail/recursion.rs index 0fe042b924a..96676257184 100644 --- a/src/test/compile-fail/recursion.rs +++ b/src/test/compile-fail/recursion.rs @@ -20,7 +20,7 @@ impl<T:Dot> Dot for Cons<T> { } } fn test<T:Dot> (n:int, i:int, first:T, second:T) ->int { - //~^ ERROR: overly deep expansion of inlined function + //~^ ERROR: reached the recursion limit during monomorphization match n { 0 => {first.dot(second)} // Error message should be here. It should be a type error |
