Skip to content

Commit cf3b790

Browse files
committed
Make recursion_limit and type_length_limit thread-safe
1 parent 472b416 commit cf3b790

File tree

10 files changed

+25
-24
lines changed

10 files changed

+25
-24
lines changed

src/librustc/middle/recursion_limit.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,17 @@
1818
use session::Session;
1919
use syntax::ast;
2020

21-
use std::cell::Cell;
21+
use rustc_data_structures::sync::Once;
2222

2323
pub fn update_limits(sess: &Session, krate: &ast::Crate) {
2424
update_limit(sess, krate, &sess.recursion_limit, "recursion_limit",
25-
"recursion limit");
25+
"recursion limit", 64);
2626
update_limit(sess, krate, &sess.type_length_limit, "type_length_limit",
27-
"type length limit");
27+
"type length limit", 1048576);
2828
}
2929

30-
fn update_limit(sess: &Session, krate: &ast::Crate, limit: &Cell<usize>,
31-
name: &str, description: &str) {
30+
fn update_limit(sess: &Session, krate: &ast::Crate, limit: &Once<usize>,
31+
name: &str, description: &str, default: usize) {
3232
for attr in &krate.attrs {
3333
if !attr.check_name(name) {
3434
continue;
@@ -45,4 +45,5 @@ fn update_limit(sess: &Session, krate: &ast::Crate, limit: &Cell<usize>,
4545
"malformed {} attribute, expected #![{}=\"N\"]",
4646
description, name);
4747
}
48+
limit.set(default);
4849
}

src/librustc/session/mod.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use util::nodemap::{FxHashMap, FxHashSet};
2626
use util::common::{duration_to_secs_str, ErrorReported};
2727
use util::common::ProfileQueriesMsg;
2828

29-
use rustc_data_structures::sync::{Lrc, Lock, OneThread};
29+
use rustc_data_structures::sync::{Lrc, Lock, OneThread, Once};
3030

3131
use syntax::ast::NodeId;
3232
use errors::{self, DiagnosticBuilder, DiagnosticId};
@@ -46,13 +46,13 @@ use rustc_back::target::{Target, TargetTriple};
4646
use rustc_data_structures::flock;
4747
use jobserver::Client;
4848

49+
use std;
4950
use std::cell::{self, Cell, RefCell};
5051
use std::collections::HashMap;
5152
use std::env;
5253
use std::fmt;
5354
use std::io::Write;
5455
use std::path::{Path, PathBuf};
55-
use std::sync::{Once, ONCE_INIT};
5656
use std::time::Duration;
5757
use std::sync::mpsc;
5858

@@ -105,10 +105,10 @@ pub struct Session {
105105

106106
/// The maximum recursion limit for potentially infinitely recursive
107107
/// operations such as auto-dereference and monomorphization.
108-
pub recursion_limit: Cell<usize>,
108+
pub recursion_limit: Once<usize>,
109109

110110
/// The maximum length of types during monomorphization.
111-
pub type_length_limit: Cell<usize>,
111+
pub type_length_limit: Once<usize>,
112112

113113
/// The maximum number of stackframes allowed in const eval
114114
pub const_eval_stack_frame_limit: Cell<usize>,
@@ -1147,8 +1147,8 @@ pub fn build_session_(
11471147
dependency_formats: RefCell::new(FxHashMap()),
11481148
crate_disambiguator: RefCell::new(None),
11491149
features: RefCell::new(None),
1150-
recursion_limit: Cell::new(64),
1151-
type_length_limit: Cell::new(1048576),
1150+
recursion_limit: Once::new(),
1151+
type_length_limit: Once::new(),
11521152
const_eval_stack_frame_limit: Cell::new(100),
11531153
const_eval_step_limit: Cell::new(1_000_000),
11541154
next_node_id: Cell::new(NodeId::new(1)),
@@ -1188,7 +1188,7 @@ pub fn build_session_(
11881188
// per-process.
11891189
jobserver_from_env: unsafe {
11901190
static mut GLOBAL_JOBSERVER: *mut Option<Client> = 0 as *mut _;
1191-
static INIT: Once = ONCE_INIT;
1191+
static INIT: std::sync::Once = std::sync::ONCE_INIT;
11921192
INIT.call_once(|| {
11931193
GLOBAL_JOBSERVER = Box::into_raw(Box::new(Client::from_env()));
11941194
});

src/librustc/traits/project.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
345345
Reveal::UserFacing => ty,
346346

347347
Reveal::All => {
348-
let recursion_limit = self.tcx().sess.recursion_limit.get();
348+
let recursion_limit = *self.tcx().sess.recursion_limit.get();
349349
if self.depth >= recursion_limit {
350350
let obligation = Obligation::with_depth(
351351
self.cause.clone(),
@@ -566,7 +566,7 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
566566
found cache entry: in-progress");
567567

568568
// But for now, let's classify this as an overflow:
569-
let recursion_limit = selcx.tcx().sess.recursion_limit.get();
569+
let recursion_limit = *selcx.tcx().sess.recursion_limit.get();
570570
let obligation = Obligation::with_depth(cause.clone(),
571571
recursion_limit,
572572
param_env,
@@ -848,7 +848,7 @@ fn project_type<'cx, 'gcx, 'tcx>(
848848
debug!("project(obligation={:?})",
849849
obligation);
850850

851-
let recursion_limit = selcx.tcx().sess.recursion_limit.get();
851+
let recursion_limit = *selcx.tcx().sess.recursion_limit.get();
852852
if obligation.recursion_depth >= recursion_limit {
853853
debug!("project: overflow!");
854854
selcx.infcx().report_overflow_error(&obligation, true);

src/librustc/traits/query/normalize.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
109109
Reveal::UserFacing => ty,
110110

111111
Reveal::All => {
112-
let recursion_limit = self.tcx().sess.recursion_limit.get();
112+
let recursion_limit = *self.tcx().sess.recursion_limit.get();
113113
if self.anon_depth >= recursion_limit {
114114
let obligation = Obligation::with_depth(
115115
self.cause.clone(),

src/librustc/traits/select.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -997,7 +997,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
997997
{
998998
// Watch out for overflow. This intentionally bypasses (and does
999999
// not update) the cache.
1000-
let recursion_limit = self.infcx.tcx.sess.recursion_limit.get();
1000+
let recursion_limit = *self.infcx.tcx.sess.recursion_limit.get();
10011001
if stack.obligation.recursion_depth >= recursion_limit {
10021002
self.infcx().report_overflow_error(&stack.obligation, true);
10031003
}

src/librustc/ty/layout.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -898,7 +898,7 @@ fn layout_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
898898
{
899899
let (param_env, ty) = query.into_parts();
900900

901-
let rec_limit = tcx.sess.recursion_limit.get();
901+
let rec_limit = *tcx.sess.recursion_limit.get();
902902
let depth = tcx.layout_depth.get();
903903
if depth > rec_limit {
904904
tcx.sess.fatal(

src/librustc_driver/driver.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -783,7 +783,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
783783
let features = sess.features_untracked();
784784
let cfg = syntax::ext::expand::ExpansionConfig {
785785
features: Some(&features),
786-
recursion_limit: sess.recursion_limit.get(),
786+
recursion_limit: *sess.recursion_limit.get(),
787787
trace_mac: sess.opts.debugging_opts.trace_macros,
788788
should_test: sess.opts.test,
789789
..syntax::ext::expand::ExpansionConfig::default(crate_name.to_string())

src/librustc_mir/monomorphize/collector.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ fn check_recursion_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
457457
// Code that needs to instantiate the same function recursively
458458
// more than the recursion limit is assumed to be causing an
459459
// infinite expansion.
460-
if recursion_depth > tcx.sess.recursion_limit.get() {
460+
if recursion_depth > *tcx.sess.recursion_limit.get() {
461461
let error = format!("reached the recursion limit while instantiating `{}`",
462462
instance);
463463
if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
@@ -484,7 +484,7 @@ fn check_type_length_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
484484
// which means that rustc basically hangs.
485485
//
486486
// Bail out in these cases to avoid that bad user experience.
487-
let type_length_limit = tcx.sess.type_length_limit.get();
487+
let type_length_limit = *tcx.sess.type_length_limit.get();
488488
if type_length > type_length_limit {
489489
// The instance name is already known to be too long for rustc. Use
490490
// `{:.64}` to avoid blasting the user's terminal with thousands of

src/librustc_traits/dropck_outlives.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
153153
span, for_ty, depth, ty
154154
);
155155

156-
if depth >= tcx.sess.recursion_limit.get() {
156+
if depth >= *tcx.sess.recursion_limit.get() {
157157
return Ok(DtorckConstraint {
158158
outlives: vec![],
159159
dtorck_types: vec![],

src/librustc_typeck/check/autoderef.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> {
5656
return Some((self.cur_ty, 0));
5757
}
5858

59-
if self.steps.len() >= tcx.sess.recursion_limit.get() {
59+
if self.steps.len() >= *tcx.sess.recursion_limit.get() {
6060
// We've reached the recursion limit, error gracefully.
61-
let suggested_limit = tcx.sess.recursion_limit.get() * 2;
61+
let suggested_limit = *tcx.sess.recursion_limit.get() * 2;
6262
let msg = format!("reached the recursion limit while auto-dereferencing {:?}",
6363
self.cur_ty);
6464
let error_id = (DiagnosticMessageId::ErrorId(55), Some(self.span), msg.clone());

0 commit comments

Comments
 (0)