diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 90fd31ecbdd73..bf1da57607d5f 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -68,6 +68,7 @@ fn main() { }; let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set"); let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set"); + let mut on_fail = env::var_os("RUSTC_ON_FAIL").map(|of| Command::new(of)); let rustc = env::var_os(rustc).unwrap_or_else(|| panic!("{:?} was not set", rustc)); let libdir = env::var_os(libdir).unwrap_or_else(|| panic!("{:?} was not set", libdir)); @@ -212,9 +213,20 @@ fn main() { } // Actually run the compiler! - std::process::exit(match exec_cmd(&mut cmd) { - Ok(s) => s.code().unwrap_or(0xfe), - Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e), + std::process::exit(if let Some(ref mut on_fail) = on_fail { + match cmd.status() { + Ok(s) if s.success() => 0, + _ => { + println!("\nDid not run successfully:\n{:?}\n-------------", cmd); + exec_cmd(on_fail).expect("could not run the backup command"); + 1 + } + } + } else { + std::process::exit(match exec_cmd(&mut cmd) { + Ok(s) => s.code().unwrap_or(0xfe), + Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e), + }) }) } diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index c5bbfd89b2787..b55f3d710ca7b 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -28,6 +28,7 @@ use step; /// Deserialized version of all flags for this compile. pub struct Flags { pub verbose: usize, // verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose + pub on_fail: Option, pub stage: Option, pub keep_stage: Option, pub build: String, @@ -81,6 +82,7 @@ impl Flags { opts.optopt("", "build", "build target of the stage0 compiler", "BUILD"); opts.optmulti("", "host", "host targets to build", "HOST"); opts.optmulti("", "target", "target targets to build", "TARGET"); + opts.optopt("", "on-fail", "command to run on failure", "CMD"); opts.optopt("", "stage", "stage to build", "N"); opts.optopt("", "keep-stage", "stage to keep without recompiling", "N"); opts.optopt("", "src", "path to the root of the rust checkout", "DIR"); @@ -283,6 +285,7 @@ To learn more about a subcommand, run `./x.py -h` Flags { verbose: m.opt_count("v"), stage: stage, + on_fail: m.opt_str("on-fail"), keep_stage: m.opt_str("keep-stage").map(|j| j.parse().unwrap()), build: m.opt_str("build").unwrap_or_else(|| { env::var("BUILD").unwrap() diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 7bd611eb53e3c..dab255789e11f 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -499,6 +499,10 @@ impl Build { cargo.env("RUSTC_INCREMENTAL", incr_dir); } + if let Some(ref on_fail) = self.flags.on_fail { + cargo.env("RUSTC_ON_FAIL", on_fail); + } + let verbose = cmp::max(self.config.verbose, self.flags.verbose); cargo.env("RUSTC_VERBOSE", format!("{}", verbose)); @@ -602,7 +606,7 @@ impl Build { /// Get the space-separated set of activated features for the standard /// library. fn std_features(&self) -> String { - let mut features = "panic-unwind asan lsan msan tsan".to_string(); + let mut features = "panic-unwind".to_string(); if self.config.debug_jemalloc { features.push_str(" debug-jemalloc"); diff --git a/src/doc/book/src/procedural-macros.md b/src/doc/book/src/procedural-macros.md index 6c4700f9305ca..079324d56d1e6 100644 --- a/src/doc/book/src/procedural-macros.md +++ b/src/doc/book/src/procedural-macros.md @@ -169,7 +169,7 @@ So this is where quotes comes in. The `ast` argument is a struct that gives us a representation of our type (which can be either a `struct` or an `enum`). Check out the [docs](https://docs.rs/syn/0.10.5/syn/struct.MacroInput.html), there is some useful information there. We are able to get the name of the -type using `ast.ident`. The `quote!` macro let's us write up the Rust code +type using `ast.ident`. The `quote!` macro lets us write up the Rust code that we wish to return and convert it into `Tokens`. `quote!` let's us use some really cool templating mechanics; we simply write `#name` and `quote!` will replace it with the variable named `name`. You can even do some repetition diff --git a/src/liblibc b/src/liblibc index 8d8264b967a31..7a3754f2bb5e6 160000 --- a/src/liblibc +++ b/src/liblibc @@ -1 +1 @@ -Subproject commit 8d8264b967a31a1a8cebe2a05110564106b6e909 +Subproject commit 7a3754f2bb5e65eb39adacb189c3626173032177 diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index d8212807eb277..3403cf0477450 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -777,6 +777,12 @@ pub enum StatementKind<'tcx> { /// End the current live range for the storage of the local. StorageDead(Lvalue<'tcx>), + InlineAsm { + asm: InlineAsm, + outputs: Vec>, + inputs: Vec> + }, + /// No-op. Useful for deleting instructions without affecting statement indices. Nop, } @@ -790,7 +796,10 @@ impl<'tcx> Debug for Statement<'tcx> { StorageDead(ref lv) => write!(fmt, "StorageDead({:?})", lv), SetDiscriminant{lvalue: ref lv, variant_index: index} => { write!(fmt, "discriminant({:?}) = {:?}", lv, index) - } + }, + InlineAsm { ref asm, ref outputs, ref inputs } => { + write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs) + }, Nop => write!(fmt, "nop"), } } @@ -1004,12 +1013,6 @@ pub enum Rvalue<'tcx> { /// that `Foo` has a destructor. These rvalues can be optimized /// away after type-checking and before lowering. Aggregate(AggregateKind<'tcx>, Vec>), - - InlineAsm { - asm: InlineAsm, - outputs: Vec>, - inputs: Vec> - } } #[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] @@ -1111,10 +1114,6 @@ impl<'tcx> Debug for Rvalue<'tcx> { UnaryOp(ref op, ref a) => write!(fmt, "{:?}({:?})", op, a), Discriminant(ref lval) => write!(fmt, "discriminant({:?})", lval), Box(ref t) => write!(fmt, "Box({:?})", t), - InlineAsm { ref asm, ref outputs, ref inputs } => { - write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs) - } - Ref(_, borrow_kind, ref lv) => { let kind_str = match borrow_kind { BorrowKind::Shared => "", diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 7b0863b4c42bc..5c8d031caf60d 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -207,7 +207,6 @@ impl<'tcx> Rvalue<'tcx> { } } } - Rvalue::InlineAsm { .. } => None } } } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index be3c43db7badd..7cdbd5cae061f 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -333,6 +333,16 @@ macro_rules! make_mir_visitor { StatementKind::StorageDead(ref $($mutability)* lvalue) => { self.visit_lvalue(lvalue, LvalueContext::StorageDead, location); } + StatementKind::InlineAsm { ref $($mutability)* outputs, + ref $($mutability)* inputs, + asm: _ } => { + for output in & $($mutability)* outputs[..] { + self.visit_lvalue(output, LvalueContext::Store, location); + } + for input in & $($mutability)* inputs[..] { + self.visit_operand(input, location); + } + } StatementKind::Nop => {} } } @@ -526,17 +536,6 @@ macro_rules! make_mir_visitor { self.visit_operand(operand, location); } } - - Rvalue::InlineAsm { ref $($mutability)* outputs, - ref $($mutability)* inputs, - asm: _ } => { - for output in & $($mutability)* outputs[..] { - self.visit_lvalue(output, LvalueContext::Store, location); - } - for input in & $($mutability)* inputs[..] { - self.visit_operand(input, location); - } - } } } diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs b/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs index 1fa4da94dd6bf..7888a56d39dfb 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs +++ b/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs @@ -473,6 +473,7 @@ impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> { } mir::StatementKind::StorageLive(_) | mir::StatementKind::StorageDead(_) | + mir::StatementKind::InlineAsm { .. } | mir::StatementKind::Nop => {} } } diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs index ea6ef423c92ce..940dd5433a0d9 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs +++ b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs @@ -104,6 +104,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } mir::StatementKind::StorageLive(_) | mir::StatementKind::StorageDead(_) | + mir::StatementKind::InlineAsm { .. } | mir::StatementKind::Nop => continue, mir::StatementKind::SetDiscriminant{ .. } => span_bug!(stmt.source_info.span, diff --git a/src/librustc_borrowck/borrowck/mir/gather_moves.rs b/src/librustc_borrowck/borrowck/mir/gather_moves.rs index 0c7e922c48ab4..35ace6628cfed 100644 --- a/src/librustc_borrowck/borrowck/mir/gather_moves.rs +++ b/src/librustc_borrowck/borrowck/mir/gather_moves.rs @@ -412,6 +412,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { span_bug!(stmt.source_info.span, "SetDiscriminant should not exist during borrowck"); } + StatementKind::InlineAsm { .. } | StatementKind::Nop => {} } } @@ -436,8 +437,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { } Rvalue::Ref(..) | Rvalue::Discriminant(..) | - Rvalue::Len(..) | - Rvalue::InlineAsm { .. } => {} + Rvalue::Len(..) => {} Rvalue::Box(..) => { // This returns an rvalue with uninitialized contents. We can't // move out of it here because it is an rvalue - assignments always diff --git a/src/librustc_borrowck/borrowck/mir/mod.rs b/src/librustc_borrowck/borrowck/mir/mod.rs index a0c36139ddcd2..d9283e7037f50 100644 --- a/src/librustc_borrowck/borrowck/mir/mod.rs +++ b/src/librustc_borrowck/borrowck/mir/mod.rs @@ -378,6 +378,7 @@ fn drop_flag_effects_for_location<'a, 'tcx, F>( } mir::StatementKind::StorageLive(_) | mir::StatementKind::StorageDead(_) | + mir::StatementKind::InlineAsm { .. } | mir::StatementKind::Nop => {} }, None => { diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index dad1d713168cd..7adcc0e730b15 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -49,21 +49,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ExprKind::Scope { extent, value } => { this.in_scope(extent, block, |this| this.as_rvalue(block, value)) } - ExprKind::InlineAsm { asm, outputs, inputs } => { - let outputs = outputs.into_iter().map(|output| { - unpack!(block = this.as_lvalue(block, output)) - }).collect(); - - let inputs = inputs.into_iter().map(|input| { - unpack!(block = this.as_operand(block, input)) - }).collect(); - - block.and(Rvalue::InlineAsm { - asm: asm.clone(), - outputs: outputs, - inputs: inputs - }) - } ExprKind::Repeat { value, count } => { let value_operand = unpack!(block = this.as_operand(block, value)); block.and(Rvalue::Repeat(value_operand, count)) @@ -238,6 +223,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ExprKind::Break { .. } | ExprKind::Continue { .. } | ExprKind::Return { .. } | + ExprKind::InlineAsm { .. } | ExprKind::StaticRef { .. } => { // these do not have corresponding `Rvalue` variants, // so make an operand and then return that diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 35841c2cbdf01..e66f2b4e2bfc0 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -232,6 +232,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ExprKind::AssignOp { .. } | ExprKind::Continue { .. } | ExprKind::Break { .. } | + ExprKind::InlineAsm { .. } | ExprKind::Return {.. } => { this.stmt_expr(block, expr) } @@ -257,7 +258,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ExprKind::Index { .. } | ExprKind::Deref { .. } | ExprKind::Literal { .. } | - ExprKind::InlineAsm { .. } | ExprKind::Field { .. } => { debug_assert!(match Category::of(&expr.kind).unwrap() { Category::Rvalue(RvalueFunc::Into) => false, diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir/build/expr/stmt.rs index f04d630379a35..c577aab40dbeb 100644 --- a/src/librustc_mir/build/expr/stmt.rs +++ b/src/librustc_mir/build/expr/stmt.rs @@ -117,6 +117,23 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { this.exit_scope(expr_span, extent, block, return_block); this.cfg.start_new_block().unit() } + ExprKind::InlineAsm { asm, outputs, inputs } => { + let outputs = outputs.into_iter().map(|output| { + unpack!(block = this.as_lvalue(block, output)) + }).collect(); + let inputs = inputs.into_iter().map(|input| { + unpack!(block = this.as_operand(block, input)) + }).collect(); + this.cfg.push(block, Statement { + source_info: source_info, + kind: StatementKind::InlineAsm { + asm: asm.clone(), + outputs: outputs, + inputs: inputs + }, + }); + block.unit() + } _ => { let expr_ty = expr.ty; let temp = this.temp(expr.ty.clone()); diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 922521726c626..4459142cfb274 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -774,10 +774,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } } } - - Rvalue::InlineAsm {..} => { - self.not_const(); - } } } @@ -933,6 +929,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { StatementKind::SetDiscriminant { .. } | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | + StatementKind::InlineAsm {..} | StatementKind::Nop => {} } }); diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index 8ede7aaab5f68..8d108815e0f3c 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -361,9 +361,9 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { span_mirbug!(self, stmt, "bad assignment ({:?} = {:?}): {:?}", lv_ty, rv_ty, terr); } - // FIXME: rvalue with undeterminable type - e.g. inline - // asm. } + // FIXME: rvalue with undeterminable type - e.g. AggregateKind::Array branch that + // returns `None`. } StatementKind::SetDiscriminant{ ref lvalue, variant_index } => { let lvalue_type = lvalue.ty(mir, tcx).to_ty(tcx); @@ -392,6 +392,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } } + StatementKind::InlineAsm { .. } | StatementKind::Nop => {} } } diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs index 517a472056334..33b7089c38214 100644 --- a/src/librustc_passes/mir_stats.rs +++ b/src/librustc_passes/mir_stats.rs @@ -128,6 +128,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { StatementKind::SetDiscriminant { .. } => "StatementKind::SetDiscriminant", StatementKind::StorageLive(..) => "StatementKind::StorageLive", StatementKind::StorageDead(..) => "StatementKind::StorageDead", + StatementKind::InlineAsm { .. } => "StatementKind::InlineAsm", StatementKind::Nop => "StatementKind::Nop", }, &statement.kind); self.super_statement(block, statement, location); @@ -198,7 +199,6 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { "Rvalue::Aggregate" } - Rvalue::InlineAsm { .. } => "Rvalue::InlineAsm", }; self.record(rvalue_kind, rvalue); self.super_rvalue(rvalue, location); diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 19139301bb0c4..7e17ae5f1d389 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -287,8 +287,9 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { mir::StatementKind::StorageLive(_) | mir::StatementKind::StorageDead(_) | mir::StatementKind::Nop => {} + mir::StatementKind::InlineAsm { .. } | mir::StatementKind::SetDiscriminant{ .. } => { - span_bug!(span, "SetDiscriminant should not appear in constants?"); + span_bug!(span, "{:?} should not appear in constants?", statement.kind); } } } diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 38ee67796c6de..7d4f542addbb1 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -16,7 +16,6 @@ use rustc::mir::tcx::LvalueTy; use rustc::mir; use middle::lang_items::ExchangeMallocFnLangItem; -use asm; use base; use builder::Builder; use callee::Callee; @@ -156,20 +155,6 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { bcx } - mir::Rvalue::InlineAsm { ref asm, ref outputs, ref inputs } => { - let outputs = outputs.iter().map(|output| { - let lvalue = self.trans_lvalue(&bcx, output); - (lvalue.llval, lvalue.ty.to_ty(bcx.tcx())) - }).collect(); - - let input_vals = inputs.iter().map(|input| { - self.trans_operand(&bcx, input).immediate() - }).collect(); - - asm::trans_inline_asm(&bcx, asm, outputs, input_vals); - bcx - } - _ => { assert!(rvalue_creates_operand(rvalue)); let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue); @@ -468,8 +453,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { (bcx, operand) } mir::Rvalue::Repeat(..) | - mir::Rvalue::Aggregate(..) | - mir::Rvalue::InlineAsm { .. } => { + mir::Rvalue::Aggregate(..) => { bug!("cannot generate operand from rvalue {:?}", rvalue); } @@ -669,8 +653,7 @@ pub fn rvalue_creates_operand(rvalue: &mir::Rvalue) -> bool { mir::Rvalue::Use(..) => true, mir::Rvalue::Repeat(..) | - mir::Rvalue::Aggregate(..) | - mir::Rvalue::InlineAsm { .. } => + mir::Rvalue::Aggregate(..) => false, } diff --git a/src/librustc_trans/mir/statement.rs b/src/librustc_trans/mir/statement.rs index 48fc9720e4b83..29a0648c8f8f8 100644 --- a/src/librustc_trans/mir/statement.rs +++ b/src/librustc_trans/mir/statement.rs @@ -11,6 +11,7 @@ use rustc::mir; use base; +use asm; use common; use builder::Builder; @@ -73,6 +74,19 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { mir::StatementKind::StorageDead(ref lvalue) => { self.trans_storage_liveness(bcx, lvalue, base::Lifetime::End) } + mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => { + let outputs = outputs.iter().map(|output| { + let lvalue = self.trans_lvalue(&bcx, output); + (lvalue.llval, lvalue.ty.to_ty(bcx.tcx())) + }).collect(); + + let input_vals = inputs.iter().map(|input| { + self.trans_operand(&bcx, input).immediate() + }).collect(); + + asm::trans_inline_asm(&bcx, asm, outputs, input_vals); + bcx + } mir::StatementKind::Nop => bcx, } } diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 2ba7517d3d202..46511452a7237 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -24,22 +24,18 @@ std_unicode = { path = "../libstd_unicode" } unwind = { path = "../libunwind" } [target.x86_64-unknown-linux-gnu.dependencies] -rustc_asan = { path = "../librustc_asan", optional = true } -rustc_lsan = { path = "../librustc_lsan", optional = true } -rustc_msan = { path = "../librustc_msan", optional = true } -rustc_tsan = { path = "../librustc_tsan", optional = true } +rustc_asan = { path = "../librustc_asan" } +rustc_lsan = { path = "../librustc_lsan" } +rustc_msan = { path = "../librustc_msan" } +rustc_tsan = { path = "../librustc_tsan" } [build-dependencies] build_helper = { path = "../build_helper" } gcc = "0.3.27" [features] -asan = ["rustc_asan"] backtrace = [] debug-jemalloc = ["alloc_jemalloc/debug"] jemalloc = ["alloc_jemalloc"] force_alloc_system = [] -lsan = ["rustc_lsan"] -msan = ["rustc_msan"] panic-unwind = ["panic_unwind"] -tsan = ["rustc_tsan"] diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index 0cff8661d8871..60767ea478661 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -200,18 +200,20 @@ impl Cursor { #[stable(feature = "rust1", since = "1.0.0")] impl io::Seek for Cursor where T: AsRef<[u8]> { fn seek(&mut self, style: SeekFrom) -> io::Result { - let pos = match style { - SeekFrom::Start(n) => { self.pos = n; return Ok(n) } - SeekFrom::End(n) => self.inner.as_ref().len() as i64 + n, - SeekFrom::Current(n) => self.pos as i64 + n, + let (base_pos, offset) = match style { + SeekFrom::Start(n) => { self.pos = n; return Ok(n); } + SeekFrom::End(n) => (self.inner.as_ref().len() as u64, n), + SeekFrom::Current(n) => (self.pos, n), }; - - if pos < 0 { - Err(Error::new(ErrorKind::InvalidInput, - "invalid seek to a negative position")) + let new_pos = if offset >= 0 { + base_pos.checked_add(offset as u64) } else { - self.pos = pos as u64; - Ok(self.pos) + base_pos.checked_sub((offset.wrapping_neg()) as u64) + }; + match new_pos { + Some(n) => {self.pos = n; Ok(self.pos)} + None => Err(Error::new(ErrorKind::InvalidInput, + "invalid seek to a negative or overflowing position")) } } } @@ -526,6 +528,43 @@ mod tests { assert_eq!(r.write(&[3]).unwrap(), 0); } + #[test] + fn seek_past_i64() { + let buf = [0xff]; + let mut r = Cursor::new(&buf[..]); + assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6); + assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6); + assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006); + assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006); + assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err()); + assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6); + + let mut r = Cursor::new(vec![10]); + assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6); + assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6); + assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006); + assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006); + assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err()); + assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6); + + let mut buf = [0]; + let mut r = Cursor::new(&mut buf[..]); + assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6); + assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6); + assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006); + assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006); + assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err()); + assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6); + + let mut r = Cursor::new(vec![10].into_boxed_slice()); + assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6); + assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6); + assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006); + assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006); + assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err()); + assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6); + } + #[test] fn seek_before_0() { let buf = [0xff]; diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index ba99375139139..1e7394c0b09e7 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -316,7 +316,7 @@ impl Once { } // Once we've enqueued ourselves, wait in a loop. - // Aftewards reload the state and continue with what we + // Afterwards reload the state and continue with what we // were doing from before. while !node.signaled.load(Ordering::SeqCst) { thread::park(); diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index 6992a17832e41..e78928c266792 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -483,41 +483,21 @@ pub fn home_dir() -> Option { target_os = "nacl", target_os = "emscripten")))] unsafe fn fallback() -> Option { - #[cfg(not(target_os = "solaris"))] - unsafe fn getpwduid_r(me: libc::uid_t, passwd: &mut libc::passwd, - buf: &mut Vec) -> Option<()> { - let mut result = ptr::null_mut(); - match libc::getpwuid_r(me, passwd, buf.as_mut_ptr(), - buf.capacity(), - &mut result) { - 0 if !result.is_null() => Some(()), - _ => None - } - } - - #[cfg(target_os = "solaris")] - unsafe fn getpwduid_r(me: libc::uid_t, passwd: &mut libc::passwd, - buf: &mut Vec) -> Option<()> { - // getpwuid_r semantics is different on Illumos/Solaris: - // http://illumos.org/man/3c/getpwuid_r - let result = libc::getpwuid_r(me, passwd, buf.as_mut_ptr(), - buf.capacity()); - if result.is_null() { None } else { Some(()) } - } - let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) { n if n < 0 => 512 as usize, n => n as usize, }; let mut buf = Vec::with_capacity(amt); let mut passwd: libc::passwd = mem::zeroed(); - - if getpwduid_r(libc::getuid(), &mut passwd, &mut buf).is_some() { - let ptr = passwd.pw_dir as *const _; - let bytes = CStr::from_ptr(ptr).to_bytes().to_vec(); - Some(OsStringExt::from_vec(bytes)) - } else { - None + let mut result = ptr::null_mut(); + match libc::getpwuid_r(libc::getuid(), &mut passwd, buf.as_mut_ptr(), + buf.capacity(), &mut result) { + 0 if !result.is_null() => { + let ptr = passwd.pw_dir as *const _; + let bytes = CStr::from_ptr(ptr).to_bytes().to_vec(); + Some(OsStringExt::from_vec(bytes)) + }, + _ => None, } } } diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 5166ddf8a21b6..66f09a7069c13 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -28,8 +28,8 @@ use mem; /// # Initialization and Destruction /// /// Initialization is dynamically performed on the first call to `with()` -/// within a thread, and values support destructors which will be run when a -/// thread exits. +/// within a thread, and values that implement `Drop` get destructed when a +/// thread exits. Some caveats apply, which are explained below. /// /// # Examples /// diff --git a/src/rustc/std_shim/Cargo.toml b/src/rustc/std_shim/Cargo.toml index db96079d3e916..14c9c5544b188 100644 --- a/src/rustc/std_shim/Cargo.toml +++ b/src/rustc/std_shim/Cargo.toml @@ -35,12 +35,8 @@ core = { path = "../../libcore" } # Reexport features from std [features] -asan = ["std/asan"] backtrace = ["std/backtrace"] debug-jemalloc = ["std/debug-jemalloc"] jemalloc = ["std/jemalloc"] force_alloc_system = ["std/force_alloc_system"] -lsan = ["std/lsan"] -msan = ["std/msan"] panic-unwind = ["std/panic-unwind"] -tsan = ["std/tsan"]