diff --git a/src/lib/builtins/exists.rs b/src/lib/builtins/exists.rs
index efcee2f941e2104614eef341b2c480629d40971b..9774f301d822e7a61505de99daddbe0ec9c0d728 100644
--- a/src/lib/builtins/exists.rs
+++ b/src/lib/builtins/exists.rs
@@ -252,13 +252,13 @@ fn test_evaluate_arguments() {
     statements.push(Statement::End);
     let description = "description".to_owned();
 
-    shell.functions.insert(
+    shell.variables.insert_function(
         name.clone(),
         Function::new(Some(description), name, args, statements),
     );
 
     assert_eq!(evaluate_arguments(&["--fn".to_owned(), name_str.to_owned()], &shell), Ok(true));
-    shell.functions.remove(name_str);
+    shell.variables.remove_function(name_str);
     assert_eq!(evaluate_arguments(&["--fn".to_owned(), name_str.to_owned()], &shell), Ok(false));
 
     // check invalid flags / parameters (should all be treated as strings and
@@ -408,7 +408,7 @@ fn test_string_var_is_not_empty() {
 #[test]
 fn test_function_is_defined() {
     use parser::assignments::{KeyBuf, Primitive};
-    let mut shell = shell::ShellBuilder::new().as_library();
+    let shell = shell::ShellBuilder::new().as_library();
 
     // create a simple dummy function
     let name_str = "test_function";
@@ -422,12 +422,12 @@ fn test_function_is_defined() {
     statements.push(Statement::End);
     let description = "description".to_owned();
 
-    shell.functions.insert(
+    shell.variables.insert_function(
         name.clone(),
         Function::new(Some(description), name, args, statements),
     );
 
     assert_eq!(function_is_defined(name_str, &shell), true);
-    shell.functions.remove(name_str);
+    shell.variables.remove_function(name_str);
     assert_eq!(function_is_defined(name_str, &shell), false);
 }
diff --git a/src/lib/builtins/variables.rs b/src/lib/builtins/variables.rs
index 1f8cb7534f584403f61ada077c1bab38006c6403..7456dc452bbfc08f454db21c04f954883a407cd1 100644
--- a/src/lib/builtins/variables.rs
+++ b/src/lib/builtins/variables.rs
@@ -192,7 +192,7 @@ mod test {
     use parser::{expand_string, Expander};
     use shell::status::{FAILURE, SUCCESS};
 
-    struct VariableExpander(pub Variables);
+    struct VariableExpander(pub Variables<'static>);
 
     impl Expander for VariableExpander {
         fn variable(&self, var: &str, _: bool) -> Option<Value> { self.0.get_var(var) }
diff --git a/src/lib/parser/loops/for_grammar.rs b/src/lib/parser/loops/for_grammar.rs
index 58a3c8bfcdcd40392029e3d2d182e5e21feabf38..5d13e5cd6aeca85c71228b9959da55b25ea43314 100644
--- a/src/lib/parser/loops/for_grammar.rs
+++ b/src/lib/parser/loops/for_grammar.rs
@@ -67,7 +67,7 @@ mod tests {
     use super::*;
     use shell::variables::Variables;
 
-    struct VariableExpander(pub Variables);
+    struct VariableExpander(pub Variables<'static>);
 
     impl Expander for VariableExpander {
         fn variable(&self, var: &str, _: bool) -> Option<Value> { self.0.get_var(var) }
@@ -111,7 +111,7 @@ mod tests {
 
     #[test]
     fn for_variable() {
-        let mut variables = Variables::default();
+        let variables = Variables::default();
         variables.set_var("A", "1 2 3 4 5");
         assert_eq!(
             ForExpression::new(&["$A".to_owned()], &VariableExpander(variables)),
diff --git a/src/lib/shell/variables/mod.rs b/src/lib/shell/variables/mod.rs
index bf2e2b205ea92b58fbb10bf73e826138e5314ee8..c61cfb79246a2bf2ef715e26148e32a1a04f505c 100644
--- a/src/lib/shell/variables/mod.rs
+++ b/src/lib/shell/variables/mod.rs
@@ -280,7 +280,7 @@ impl<'a> Variables<'a> {
                     None => break
                 }
             }
-            None
+            env::var(name).ok()
         }
     }
     pub fn insert_alias(&self, name: SmallString, value: Value) -> Option<Value> {
@@ -356,6 +356,19 @@ impl<'a> Variables<'a> {
         }
         None
     }
+    pub fn remove_function(&self, name: &str) -> Option<Function> {
+        let mut me = self;
+        loop {
+            if let Some(var) = me.functions.borrow_mut().remove(name) {
+                return Some(var);
+            }
+            match me.parent {
+                Some(parent) => me = parent,
+                None => break
+            }
+        }
+        None
+    }
 
     /// Obtains the value for the **MWD** variable.
     ///
@@ -505,7 +518,7 @@ mod tests {
     use super::*;
     use parser::{expand_string, Expander};
 
-    struct VariableExpander(pub Variables);
+    struct VariableExpander(pub Variables<'static>);
 
     impl Expander for VariableExpander {
         fn variable(&self, var: &str, _: bool) -> Option<Value> { self.0.get_var(var) }
@@ -520,7 +533,7 @@ mod tests {
 
     #[test]
     fn set_var_and_expand_a_variable() {
-        let mut variables = Variables::default();
+        let variables = Variables::default();
         variables.set_var("FOO", "BAR");
         let expanded = expand_string("$FOO", &VariableExpander(variables), false).join("");
         assert_eq!("BAR", &expanded);
@@ -538,7 +551,7 @@ mod tests {
 
     #[test]
     fn minimal_directory_var_should_compact_path() {
-        let mut variables = Variables::default();
+        let variables = Variables::default();
         variables.set_var("PWD", "/var/log/nix");
         assert_eq!(
             "v/l/nix",
@@ -548,7 +561,7 @@ mod tests {
 
     #[test]
     fn minimal_directory_var_shouldnt_compact_path() {
-        let mut variables = Variables::default();
+        let variables = Variables::default();
         variables.set_var("PWD", "/var/log");
         assert_eq!(
             "/var/log",