mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-06 12:18:33 +00:00
Fix rustc panic on second compile_input
This commit is contained in:
parent
29e928f2ba
commit
004533ea75
@ -51,6 +51,12 @@ pub fn compile_input(sess: Session,
|
|||||||
outdir: &Option<Path>,
|
outdir: &Option<Path>,
|
||||||
output: &Option<Path>,
|
output: &Option<Path>,
|
||||||
addl_plugins: Option<Plugins>) {
|
addl_plugins: Option<Plugins>) {
|
||||||
|
// These may be left in an incoherent state after a previous compile.
|
||||||
|
// `clear_tables` and `get_ident_interner().clear()` can be used to free
|
||||||
|
// memory, but they do not restore the initial state.
|
||||||
|
syntax::ext::mtwt::reset_tables();
|
||||||
|
token::reset_ident_interner();
|
||||||
|
|
||||||
// We need nested scopes here, because the intermediate results can keep
|
// We need nested scopes here, because the intermediate results can keep
|
||||||
// large chunks of memory alive and we want to free them as soon as
|
// large chunks of memory alive and we want to free them as soon as
|
||||||
// possible to keep the peak memory usage low
|
// possible to keep the peak memory usage low
|
||||||
|
@ -136,6 +136,16 @@ pub fn clear_tables() {
|
|||||||
with_resolve_table_mut(|table| *table = HashMap::new());
|
with_resolve_table_mut(|table| *table = HashMap::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reset the tables to their initial state
|
||||||
|
pub fn reset_tables() {
|
||||||
|
with_sctable(|table| {
|
||||||
|
*table.table.borrow_mut() = vec!(EmptyCtxt, IllegalCtxt);
|
||||||
|
*table.mark_memo.borrow_mut() = HashMap::new();
|
||||||
|
*table.rename_memo.borrow_mut() = HashMap::new();
|
||||||
|
});
|
||||||
|
with_resolve_table_mut(|table| *table = HashMap::new());
|
||||||
|
}
|
||||||
|
|
||||||
/// Add a value to the end of a vec, return its index
|
/// Add a value to the end of a vec, return its index
|
||||||
fn idx_push<T>(vec: &mut Vec<T>, val: T) -> u32 {
|
fn idx_push<T>(vec: &mut Vec<T>, val: T) -> u32 {
|
||||||
vec.push(val);
|
vec.push(val);
|
||||||
|
@ -564,6 +564,12 @@ pub fn get_ident_interner() -> Rc<IdentInterner> {
|
|||||||
KEY.with(|k| k.clone())
|
KEY.with(|k| k.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reset the ident interner to its initial state.
|
||||||
|
pub fn reset_ident_interner() {
|
||||||
|
let interner = get_ident_interner();
|
||||||
|
interner.reset(mk_fresh_ident_interner());
|
||||||
|
}
|
||||||
|
|
||||||
/// Represents a string stored in the task-local interner. Because the
|
/// Represents a string stored in the task-local interner. Because the
|
||||||
/// interner lives for the life of the task, this can be safely treated as an
|
/// interner lives for the life of the task, this can be safely treated as an
|
||||||
/// immortal string, as long as it never crosses between tasks.
|
/// immortal string, as long as it never crosses between tasks.
|
||||||
|
@ -214,6 +214,11 @@ impl StrInterner {
|
|||||||
*self.map.borrow_mut() = HashMap::new();
|
*self.map.borrow_mut() = HashMap::new();
|
||||||
*self.vect.borrow_mut() = Vec::new();
|
*self.vect.borrow_mut() = Vec::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reset(&self, other: StrInterner) {
|
||||||
|
*self.map.borrow_mut() = other.map.into_inner();
|
||||||
|
*self.vect.borrow_mut() = other.vect.into_inner();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
9
src/test/run-make/issue-19371/Makefile
Normal file
9
src/test/run-make/issue-19371/Makefile
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
-include ../tools.mk
|
||||||
|
|
||||||
|
# This test ensures that rustc compile_input can be called twice in one task
|
||||||
|
# without causing a panic.
|
||||||
|
# The program needs the path to rustc to get sysroot.
|
||||||
|
|
||||||
|
all:
|
||||||
|
$(RUSTC) foo.rs
|
||||||
|
$(call RUN,foo $(TMPDIR) $(RUSTC))
|
62
src/test/run-make/issue-19371/foo.rs
Normal file
62
src/test/run-make/issue-19371/foo.rs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
extern crate rustc;
|
||||||
|
extern crate rustc_trans;
|
||||||
|
extern crate syntax;
|
||||||
|
|
||||||
|
use rustc::session::{build_session, Session};
|
||||||
|
use rustc::session::config::{basic_options, build_configuration, OutputTypeExe};
|
||||||
|
use rustc_trans::driver::driver::{Input, StrInput, compile_input};
|
||||||
|
use syntax::diagnostics::registry::Registry;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let src = r#"
|
||||||
|
fn main() {}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let args = std::os::args();
|
||||||
|
|
||||||
|
if args.len() < 4 {
|
||||||
|
panic!("expected rustc path");
|
||||||
|
}
|
||||||
|
|
||||||
|
let tmpdir = Path::new(args[1].as_slice());
|
||||||
|
|
||||||
|
let mut sysroot = Path::new(args[3].as_slice());
|
||||||
|
sysroot.pop();
|
||||||
|
sysroot.pop();
|
||||||
|
|
||||||
|
compile(src.to_string(), tmpdir.join("out"), sysroot.clone());
|
||||||
|
|
||||||
|
compile(src.to_string(), tmpdir.join("out"), sysroot.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn basic_sess(sysroot: Path) -> Session {
|
||||||
|
let mut opts = basic_options();
|
||||||
|
opts.output_types = vec![OutputTypeExe];
|
||||||
|
opts.maybe_sysroot = Some(sysroot);
|
||||||
|
|
||||||
|
let descriptions = Registry::new(&rustc::DIAGNOSTICS);
|
||||||
|
let sess = build_session(opts, None, descriptions);
|
||||||
|
sess
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compile(code: String, output: Path, sysroot: Path) {
|
||||||
|
let sess = basic_sess(sysroot);
|
||||||
|
let cfg = build_configuration(&sess);
|
||||||
|
|
||||||
|
compile_input(sess,
|
||||||
|
cfg,
|
||||||
|
&StrInput(code),
|
||||||
|
&None,
|
||||||
|
&Some(output),
|
||||||
|
None);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user