diff --git a/Cargo.lock b/Cargo.lock index 551cd8634754a1e32ef00350f25293537e172581..7c0b7813164fd038d1b733223654d222a47ea833 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -176,6 +176,7 @@ dependencies = [ "regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallstring 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "users 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -209,7 +210,7 @@ dependencies = [ [[package]] name = "liner" version = "0.4.5" -source = "git+https://gitlab.redox-os.org/redox-os/liner#98f723d1501701a659ab998226d7f5b32098ffc2" +source = "git+https://gitlab.redox-os.org/redox-os/liner#82c1715faffe2535f0e9a5bc379c5c0230a360fe" dependencies = [ "bytecount 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -354,6 +355,11 @@ dependencies = [ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "take_mut" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "termion" version = "1.5.1" @@ -506,6 +512,7 @@ source = "git+https://github.com/whitequark/rust-xdg#090afef2509d746e48d6bfa9b2e "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd" +"checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" diff --git a/Cargo.toml b/Cargo.toml index 82cbe48f66ba72a7a7f7cf14822ea6a78749c81c..53679b83c4d154f1e1e21d37679a60ab8b4a1449 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,6 +42,7 @@ smallstring = "0.1" smallvec = "0.6" unicode-segmentation = "1.2" xdg = { git = "https://github.com/whitequark/rust-xdg" } +take_mut = "0.2.2" [lib] path = "src/lib/lib.rs" diff --git a/src/lib/lib.rs b/src/lib/lib.rs index 6cea2825c4b1e0d10bdaa45b935213e1a90e9d65..db4de8723f26b09e4790f3dbd3e4ce67c458f4bb 100644 --- a/src/lib/lib.rs +++ b/src/lib/lib.rs @@ -17,6 +17,7 @@ extern crate glob; extern crate itoa; #[macro_use] extern crate lazy_static; +extern crate take_mut; #[cfg(test)] extern crate test; #[cfg(all(unix, not(target_os = "redox")))] diff --git a/src/lib/shell/flow.rs b/src/lib/shell/flow.rs index 8847dd57ff8d5dd6aff125db293529d94c10134f..022ca5524c7e8e10ac5a2d093a1844691e5fc548 100644 --- a/src/lib/shell/flow.rs +++ b/src/lib/shell/flow.rs @@ -608,17 +608,7 @@ impl FlowLogic for Shell { } fn execute_statements(&mut self, mut statements: Vec<Statement>) -> Condition { - self.with_vars(|old: &Variables| { - let new = old.new_scope(); - // TODO: THIS IS SUPER UNSAFE!!!!!11111 - // I'm bypassing the borrow checker here because I'm too gosh darn lazy - // to make Shell take a lifetime pararmeter. - // THIS. IS. WRONG. - // This should be fixed. Some day. Ugh. - // Don't do this at home, kids! - let new: Variables<'static> = unsafe { mem::transmute(new) }; - new - }, |shell| { + self.with_vars(|old: &Variables| old.new_scope(), |shell| { let mut iterator = statements.drain(..); while let Some(statement) = iterator.next() { match shell.execute_statement(&mut iterator, statement) { diff --git a/src/lib/shell/flow_control.rs b/src/lib/shell/flow_control.rs index 948cdc08a8af497e0d86b7cf911323ae186291f1..9649417f6975b3dc4f97f6e72c9dd974a76ba6a3 100644 --- a/src/lib/shell/flow_control.rs +++ b/src/lib/shell/flow_control.rs @@ -1,8 +1,7 @@ -use super::{flow::FlowLogic, Shell, Variables}; +use super::{flow::FlowLogic, Shell}; use parser::{assignments::*, pipelines::Pipeline}; use smallvec::SmallVec; use std::fmt::{self, Display, Formatter}; -use std::mem; use types::Identifier; #[derive(Debug, PartialEq, Clone)] @@ -195,15 +194,7 @@ impl Function { while !vars.functions.borrow().contains_key(&name) { vars = vars.parent.expect("execute called on function that's not in scope"); } - let vars = vars.new_scope(); - // TODO: THIS IS SUPER UNSAFE!!!!!11111 - // I'm bypassing the borrow checker here because I'm too gosh darn lazy - // to make Shell take a lifetime pararmeter. - // THIS. IS. WRONG. - // This should be fixed. Some day. Ugh. - // Don't do this at home, kids! - let vars: Variables<'static> = unsafe { mem::transmute(vars) }; - vars + vars.new_scope() }, move |shell| { for (type_, value) in values { match value { diff --git a/src/lib/shell/mod.rs b/src/lib/shell/mod.rs index 35100d28718c7e63f8118a956d297e1e6a3f42b9..ffdf5bf0691a8d5d258b6d2f11114703e796778f 100644 --- a/src/lib/shell/mod.rs +++ b/src/lib/shell/mod.rs @@ -36,10 +36,11 @@ use liner::Context; use parser::{pipelines::Pipeline, ArgumentSplitter, Expander, Select, Terminator}; use smallvec::SmallVec; use std::{ - fs::File, io::{self, Read, Write}, iter::FromIterator, mem, ops::Deref, path::Path, ptr, process, + fs::File, io::{self, Read, Write}, iter::FromIterator, mem, ops::Deref, path::Path, process, sync::{atomic::Ordering, Arc, Mutex}, time::SystemTime, }; use sys; +use take_mut; use types::*; use xdg::BaseDirectories; @@ -171,17 +172,25 @@ impl<'a> Shell { /// A method for temporarily using a separate set of variables for this shell. /// Calls the inner callback and then swaps back. pub fn with_vars<VF, F, T>(&mut self, variables: VF, callback: F) -> T - where VF: FnOnce(&Variables) -> Variables<'static>, + where VF: for <'b> FnOnce(&'b Variables) -> Variables<'b>, F: FnOnce(&mut Self) -> T { - // TODO: It's undefined behavior if variables() callback panics. - // This could be solved with the take-mut crate. - let old = mem::replace(&mut self.variables, unsafe { mem::uninitialized() }); - let new = variables(&old); - unsafe { ptr::write(&mut self.variables, new); } - + let mut old = None; + take_mut::take(&mut self.variables, |old2| { + old = Some(old2); + let new = variables(old.as_ref().unwrap()); + + // TODO: THIS IS SUPER UNSAFE!!!!!11111 + // I'm bypassing the borrow checker here because I'm too gosh darn lazy + // to make Shell take a lifetime pararmeter. + // THIS. IS. WRONG. + // This should be fixed. Some day. Ugh. + // Don't do this at home, kids! + let new: Variables<'static> = unsafe { mem::transmute(new) }; + new + }); let value = callback(self); - mem::replace(&mut self.variables, old); + mem::replace(&mut self.variables, old.unwrap()); value }