diff --git a/src/lib/builtins/mod.rs b/src/lib/builtins/mod.rs
index 27cf0e3fe1ac312c47f3b4141570c0e6945b081d..abe61c8d45aa4d986f47fd7fef33ee9931e57a05 100644
--- a/src/lib/builtins/mod.rs
+++ b/src/lib/builtins/mod.rs
@@ -158,13 +158,13 @@ pub fn builtin_cd(args: &[String], shell: &mut Shell) -> i32 {
         Ok(()) => {
             match env::current_dir() {
                 Ok(cwd) => {
-                    let pwd = shell.get_var_or_empty("PWD");
+                    let pwd = env::var("PWD").ok().unwrap_or_else(String::default);
                     let pwd = &pwd;
                     let current_dir = cwd.to_str().unwrap_or("?");
 
                     if pwd != current_dir {
                         shell.set_var("OLDPWD", pwd);
-                        shell.set_var("PWD", current_dir);
+                        env::set_var("PWD", current_dir);
                     }
                     fork_function(shell, "CD_CHANGE", &["ion"]);
                 }
diff --git a/src/lib/shell/directory_stack.rs b/src/lib/shell/directory_stack.rs
index e6da29f63fc31bbdb399a3f3bd78075336159c30..1c7f7cc47bbc3ccd569a25cd9aa00fb970315308 100644
--- a/src/lib/shell/directory_stack.rs
+++ b/src/lib/shell/directory_stack.rs
@@ -3,6 +3,7 @@ use super::{
 };
 use std::{
     borrow::Cow, collections::VecDeque, env::{current_dir, home_dir, set_current_dir},
+    env,
     path::PathBuf,
 };
 
@@ -234,8 +235,8 @@ impl DirectoryStack {
 
         // Update $PWD
         match current_dir() {
-            Ok(current_dir) => variables.set_var("PWD", current_dir.to_str().unwrap_or("?")),
-            Err(_) => variables.set_var("PWD", "?"),
+            Ok(current_dir) => env::set_var("PWD", current_dir.to_str().unwrap_or("?")),
+            Err(_) => env::set_var("PWD", "?"),
         }
     }
 
diff --git a/src/lib/shell/variables/mod.rs b/src/lib/shell/variables/mod.rs
index 8a5cc047b951d9685f8f5c4e8abdd89967a384f1..63e2653ffdbae3b1d289ac75d260e54f39e2c027 100644
--- a/src/lib/shell/variables/mod.rs
+++ b/src/lib/shell/variables/mod.rs
@@ -266,11 +266,10 @@ impl Variables {
             "" => if let Some(home) = env::home_dir() {
                 return Some(home.to_string_lossy().to_string() + remainder);
             },
-            "+" => if let Some(pwd) = self.get_var("PWD") {
-                return Some(pwd.to_string() + remainder);
-            } else if let Ok(pwd) = env::current_dir() {
-                return Some(pwd.to_string_lossy().to_string() + remainder);
-            },
+            "+" => return Some(match env::var("PWD") {
+                Ok(var) => var + remainder,
+                _ => ["?", remainder].concat()
+            }),
             "-" => if let Some(oldpwd) = self.get_var("OLDPWD") {
                 return Some(oldpwd.to_string() + remainder);
             },
@@ -520,7 +519,7 @@ impl Variables {
     /// Useful for getting smaller prompts, this will produce a simplified variant of the
     /// working directory which the leading `HOME` prefix replaced with a tilde character.
     fn get_simplified_directory(&self) -> Value {
-        self.get_var("PWD")
+        env::var("PWD")
             .unwrap()
             .replace(&self.get_var("HOME").unwrap(), "~")
     }
@@ -670,8 +669,8 @@ mod tests {
 
     #[test]
     fn minimal_directory_var_should_compact_path() {
-        let mut variables = Variables::default();
-        variables.set_var("PWD", "/var/log/nix");
+        let variables = Variables::default();
+        env::set_var("PWD", "/var/log/nix");
         assert_eq!(
             "v/l/nix",
             variables.get_var("MWD").expect("no value returned")
@@ -680,8 +679,8 @@ mod tests {
 
     #[test]
     fn minimal_directory_var_shouldnt_compact_path() {
-        let mut variables = Variables::default();
-        variables.set_var("PWD", "/var/log");
+        let variables = Variables::default();
+        env::set_var("PWD", "/var/log");
         assert_eq!(
             "/var/log",
             variables.get_var("MWD").expect("no value returned")