From 8d5eac76cdd1c8dd9c57f0b410dfcef76a806cd6 Mon Sep 17 00:00:00 2001
From: stratact <stratact1@gmail.com>
Date: Tue, 29 May 2018 18:19:10 -0700
Subject: [PATCH] Pass existing `&[String]` arg values instead of converting
 them into `&[&str]` by `Vec` collecting to save some allocation

---
 src/lib/builtins/calc.rs         |  2 +-
 src/lib/builtins/command_info.rs | 16 +++----
 src/lib/builtins/conditionals.rs |  2 +-
 src/lib/builtins/echo.rs         |  4 +-
 src/lib/builtins/exec.rs         |  6 +--
 src/lib/builtins/exists.rs       |  8 ++--
 src/lib/builtins/ion.rs          |  2 +-
 src/lib/builtins/is.rs           |  6 +--
 src/lib/builtins/job_control.rs  | 10 ++--
 src/lib/builtins/man_pages.rs    |  4 +-
 src/lib/builtins/mod.rs          | 80 ++++++++++++++++----------------
 src/lib/builtins/random.rs       |  6 +--
 src/lib/builtins/set.rs          | 14 +++---
 src/lib/builtins/source.rs       |  2 +-
 src/lib/builtins/status.rs       |  4 +-
 src/lib/builtins/test.rs         |  8 ++--
 src/lib/shell/history.rs         |  4 +-
 src/lib/shell/job.rs             |  9 +---
 src/lib/shell/mod.rs             |  3 +-
 src/lib/shell/pipe_exec/mod.rs   |  5 +-
 src/lib/sys/unix/mod.rs          |  6 +--
 21 files changed, 96 insertions(+), 105 deletions(-)

diff --git a/src/lib/builtins/calc.rs b/src/lib/builtins/calc.rs
index 21d128ae..e86828d8 100644
--- a/src/lib/builtins/calc.rs
+++ b/src/lib/builtins/calc.rs
@@ -8,7 +8,7 @@ fn calc_or_polish_calc(args: String) -> Result<Value, CalcError> {
     }
 }
 
-pub(crate) fn calc(args: &[&str]) -> Result<(), String> {
+pub(crate) fn calc(args: &[String]) -> Result<(), String> {
     let stdout = io::stdout();
     let mut stdout = stdout.lock();
     if !args.is_empty() {
diff --git a/src/lib/builtins/command_info.rs b/src/lib/builtins/command_info.rs
index dd11439e..b9c3400c 100644
--- a/src/lib/builtins/command_info.rs
+++ b/src/lib/builtins/command_info.rs
@@ -4,7 +4,7 @@ use sys;
 
 use std::{borrow::Cow, env, path::Path};
 
-pub(crate) fn which(args: &[&str], shell: &mut Shell) -> Result<i32, ()> {
+pub(crate) fn which(args: &[String], shell: &mut Shell) -> Result<i32, ()> {
     if check_help(args, MAN_WHICH) {
         return Ok(SUCCESS);
     }
@@ -15,11 +15,11 @@ pub(crate) fn which(args: &[&str], shell: &mut Shell) -> Result<i32, ()> {
     }
 
     let mut result = SUCCESS;
-    for &command in &args[1..] {
-        if let Ok(c_type) = get_command_info(command, shell) {
+    for command in &args[1..] {
+        if let Ok(c_type) = get_command_info(&**command, shell) {
             match c_type.as_ref() {
                 "alias" => {
-                    let alias = shell.variables.aliases.get(command).unwrap();
+                    let alias = shell.variables.aliases.get(&**command).unwrap();
                     println!("{}: alias to {}", command, alias);
                 }
                 "function" => println!("{}: function", command),
@@ -33,7 +33,7 @@ pub(crate) fn which(args: &[&str], shell: &mut Shell) -> Result<i32, ()> {
     Ok(result)
 }
 
-pub(crate) fn find_type(args: &[&str], shell: &mut Shell) -> Result<i32, ()> {
+pub(crate) fn find_type(args: &[String], shell: &mut Shell) -> Result<i32, ()> {
     // Type does not accept help flags, aka "--help".
     if args.len() == 1 {
         eprintln!("type: Expected at least 1 args, got only 0");
@@ -41,11 +41,11 @@ pub(crate) fn find_type(args: &[&str], shell: &mut Shell) -> Result<i32, ()> {
     }
 
     let mut result = FAILURE;
-    for &command in &args[1..] {
-        if let Ok(c_type) = get_command_info(command, shell) {
+    for command in &args[1..] {
+        if let Ok(c_type) = get_command_info(&**command, shell) {
             match c_type.as_ref() {
                 "alias" => {
-                    let alias = shell.variables.aliases.get(command).unwrap();
+                    let alias = shell.variables.aliases.get(&**command).unwrap();
                     println!("{} is aliased to `{}`", command, alias);
                 }
                 // TODO Make it print the function.
diff --git a/src/lib/builtins/conditionals.rs b/src/lib/builtins/conditionals.rs
index 763fb6c9..9f21e199 100644
--- a/src/lib/builtins/conditionals.rs
+++ b/src/lib/builtins/conditionals.rs
@@ -2,7 +2,7 @@ use shell::{status::*, Shell};
 
 macro_rules! string_function {
     ($method:tt) => {
-        pub(crate) fn $method(args: &[&str], _: &mut Shell) -> i32 {
+        pub(crate) fn $method(args: &[String], _: &mut Shell) -> i32 {
             match args.len() {
                 0...2 => {
                     eprintln!("ion: {}: two arguments must be supplied", args[0]);
diff --git a/src/lib/builtins/echo.rs b/src/lib/builtins/echo.rs
index 65fdbe7a..6b7f948d 100644
--- a/src/lib/builtins/echo.rs
+++ b/src/lib/builtins/echo.rs
@@ -9,12 +9,12 @@ bitflags! {
     }
 }
 
-pub(crate) fn echo(args: &[&str]) -> Result<(), io::Error> {
+pub(crate) fn echo(args: &[String]) -> Result<(), io::Error> {
     let mut flags = Flags::empty();
     let mut data: SmallVec<[&str; 16]> = SmallVec::with_capacity(16);
 
     for arg in args {
-        match *arg {
+        match &**arg {
             "--escape" => flags |= Flags::ESCAPE,
             "--no-newline" => flags |= Flags::NO_NEWLINE,
             "--no-spaces" => flags |= Flags::NO_SPACES,
diff --git a/src/lib/builtins/exec.rs b/src/lib/builtins/exec.rs
index 81b20459..eef34dfd 100644
--- a/src/lib/builtins/exec.rs
+++ b/src/lib/builtins/exec.rs
@@ -4,13 +4,13 @@ use std::error::Error;
 use sys::execve;
 
 /// Executes the givent commmand.
-pub(crate) fn exec(shell: &mut Shell, args: &[&str]) -> Result<(), String> {
+pub(crate) fn exec(shell: &mut Shell, args: &[String]) -> Result<(), String> {
     const CLEAR_ENV: u8 = 1;
 
     let mut flags = 0u8;
     let mut idx = 0;
-    for &arg in args.iter() {
-        match arg {
+    for arg in args.iter() {
+        match &**arg {
             "-c" => flags |= CLEAR_ENV,
             _ if check_help(args, MAN_EXEC) => {
                 return Ok(());
diff --git a/src/lib/builtins/exists.rs b/src/lib/builtins/exists.rs
index 9ba6ede7..1262bc82 100644
--- a/src/lib/builtins/exists.rs
+++ b/src/lib/builtins/exists.rs
@@ -10,14 +10,14 @@ use shell;
 use shell::flow_control::{Function, Statement};
 use shell::Shell;
 
-pub(crate) fn exists(args: &[&str], shell: &Shell) -> Result<bool, String> {
+pub(crate) fn exists(args: &[String], shell: &Shell) -> Result<bool, String> {
     let arguments = &args[1..];
     evaluate_arguments(arguments, shell)
 }
 
-fn evaluate_arguments(arguments: &[&str], shell: &Shell) -> Result<bool, String> {
+fn evaluate_arguments(arguments: &[String], shell: &Shell) -> Result<bool, String> {
     match arguments.first() {
-        Some(&s) if s.starts_with("--") => {
+        Some(ref s) if s.starts_with("--") => {
             let (_, option) = s.split_at(2);
             // If no argument was given, return `SUCCESS`, as this means a string starting
             // with a dash was given
@@ -27,7 +27,7 @@ fn evaluate_arguments(arguments: &[&str], shell: &Shell) -> Result<bool, String>
                 Ok(match_option_argument(option, arg, shell))
             })
         }
-        Some(&s) if s.starts_with("-") => {
+        Some(ref s) if s.starts_with("-") => {
             // Access the second character in the flag string: this will be type of the
             // flag. If no flag was given, return `SUCCESS`, as this means a
             // string with value "-" was checked.
diff --git a/src/lib/builtins/ion.rs b/src/lib/builtins/ion.rs
index 74f7f0f7..3abdb36d 100644
--- a/src/lib/builtins/ion.rs
+++ b/src/lib/builtins/ion.rs
@@ -5,7 +5,7 @@ use std::process::Command;
 
 const DOCPATH: &str = "/usr/share/ion/docs/index.html";
 
-pub(crate) fn ion_docs(_: &[&str], shell: &mut Shell) -> i32 {
+pub(crate) fn ion_docs(_: &[String], shell: &mut Shell) -> i32 {
     if !Path::new(DOCPATH).exists() {
         eprintln!("ion: ion shell documentation is not installed");
         return FAILURE;
diff --git a/src/lib/builtins/is.rs b/src/lib/builtins/is.rs
index 8d3d1b43..c6dc63fd 100644
--- a/src/lib/builtins/is.rs
+++ b/src/lib/builtins/is.rs
@@ -1,14 +1,14 @@
 use builtins::man_pages::{check_help, MAN_IS};
 use shell::Shell;
 
-pub(crate) fn is(args: &[&str], shell: &mut Shell) -> Result<(), String> {
+pub(crate) fn is(args: &[String], shell: &mut Shell) -> Result<(), String> {
     match args.len() {
         4 => if args[1] != "not" {
             return Err(format!("Expected 'not' instead found '{}'\n", args[1]).to_string());
-        } else if eval_arg(args[2], shell) == eval_arg(args[3], shell) {
+        } else if eval_arg(&*args[2], shell) == eval_arg(&*args[3], shell) {
             return Err("".to_string());
         },
-        3 => if eval_arg(args[1], shell) != eval_arg(args[2], shell) {
+        3 => if eval_arg(&*args[1], shell) != eval_arg(&*args[2], shell) {
             return Err("".to_string());
         },
         2 => if !check_help(args, MAN_IS) {
diff --git a/src/lib/builtins/job_control.rs b/src/lib/builtins/job_control.rs
index a6de2fc9..423ca273 100644
--- a/src/lib/builtins/job_control.rs
+++ b/src/lib/builtins/job_control.rs
@@ -9,7 +9,7 @@ use smallvec::SmallVec;
 /// Disowns given process job IDs, and optionally marks jobs to not receive SIGHUP signals.
 /// The `-a` flag selects all jobs, `-r` selects all running jobs, and `-h` specifies to mark
 /// SIGHUP ignoral.
-pub(crate) fn disown(shell: &mut Shell, args: &[&str]) -> Result<(), String> {
+pub(crate) fn disown(shell: &mut Shell, args: &[String]) -> Result<(), String> {
     // Specifies that a process should be set to not receive SIGHUP signals.
     const NO_SIGHUP: u8 = 1;
     // Specifies that all jobs in the process table should be manipulated.
@@ -20,8 +20,8 @@ pub(crate) fn disown(shell: &mut Shell, args: &[&str]) -> Result<(), String> {
     // Set flags and collect all job specs listed as arguments.
     let mut collected_jobs: SmallVec<[u32; 16]> = SmallVec::with_capacity(16);
     let mut flags = 0u8;
-    for &arg in args {
-        match arg {
+    for arg in args {
+        match &**arg {
             "-a" => flags |= ALL_JOBS,
             "-h" => flags |= NO_SIGHUP,
             "-r" => flags |= RUN_JOBS,
@@ -97,7 +97,7 @@ pub(crate) fn jobs(shell: &mut Shell) {
 /// Hands control of the foreground process to the specified jobs, recording their exit status.
 /// If the job is stopped, the job will be resumed.
 /// If multiple jobs are given, then only the last job's exit status will be returned.
-pub(crate) fn fg(shell: &mut Shell, args: &[&str]) -> i32 {
+pub(crate) fn fg(shell: &mut Shell, args: &[String]) -> i32 {
     fn fg_job(shell: &mut Shell, njob: u32) -> i32 {
         let job = if let Some(borrowed_job) =
             shell.background.lock().unwrap().iter().nth(njob as usize)
@@ -146,7 +146,7 @@ pub(crate) fn fg(shell: &mut Shell, args: &[&str]) -> i32 {
 }
 
 /// Resumes a stopped background process, if it was stopped.
-pub(crate) fn bg(shell: &mut Shell, args: &[&str]) -> i32 {
+pub(crate) fn bg(shell: &mut Shell, args: &[String]) -> i32 {
     fn bg_job(shell: &mut Shell, njob: u32) -> bool {
         if let Some(job) = shell
             .background
diff --git a/src/lib/builtins/man_pages.rs b/src/lib/builtins/man_pages.rs
index 8db0e36b..ed698139 100644
--- a/src/lib/builtins/man_pages.rs
+++ b/src/lib/builtins/man_pages.rs
@@ -14,9 +14,9 @@ pub(crate) fn print_man(man_page: &'static str) {
     }
 }
 
-pub(crate) fn check_help(args: &[&str], man_page: &'static str) -> bool {
+pub(crate) fn check_help(args: &[String], man_page: &'static str) -> bool {
     for arg in args {
-        if *arg == "-h" || *arg == "--help" {
+        if &**arg == "-h" || &**arg == "--help" {
             print_man(man_page);
             return true;
         }
diff --git a/src/lib/builtins/mod.rs b/src/lib/builtins/mod.rs
index e383294d..e0078d6b 100644
--- a/src/lib/builtins/mod.rs
+++ b/src/lib/builtins/mod.rs
@@ -42,7 +42,7 @@ const SOURCE_DESC: &str = "Evaluate the file following the command or re-initial
 const DISOWN_DESC: &str =
     "Disowning a process removes that process from the shell's background process table.";
 
-pub type BuiltinFunction = fn(&[&str], &mut Shell) -> i32;
+pub type BuiltinFunction = fn(&[String], &mut Shell) -> i32;
 
 macro_rules! map {
     ($($name:expr => $func:ident: $help:expr),+) => {{
@@ -136,7 +136,7 @@ impl BuiltinMap {
 }
 
 // Definitions of simple builtins go here
-fn builtin_status(args: &[&str], shell: &mut Shell) -> i32 {
+fn builtin_status(args: &[String], shell: &mut Shell) -> i32 {
     match status(args, shell) {
         Ok(()) => SUCCESS,
         Err(why) => {
@@ -148,7 +148,7 @@ fn builtin_status(args: &[&str], shell: &mut Shell) -> i32 {
     }
 }
 
-pub fn builtin_cd(args: &[&str], shell: &mut Shell) -> i32 {
+pub fn builtin_cd(args: &[String], shell: &mut Shell) -> i32 {
     if check_help(args, MAN_CD) {
         return SUCCESS;
     }
@@ -178,7 +178,7 @@ pub fn builtin_cd(args: &[&str], shell: &mut Shell) -> i32 {
     }
 }
 
-fn builtin_bool(args: &[&str], shell: &mut Shell) -> i32 {
+fn builtin_bool(args: &[String], shell: &mut Shell) -> i32 {
     if args.len() != 2 {
         let stderr = io::stderr();
         let mut stderr = stderr.lock();
@@ -195,7 +195,7 @@ fn builtin_bool(args: &[&str], shell: &mut Shell) -> i32 {
     match sh_var {
         "1" => (),
         "true" => (),
-        _ => match args[1] {
+        _ => match &*args[1] {
             "1" => (),
             "true" => (),
             "--help" => print_man(MAN_BOOL),
@@ -206,7 +206,7 @@ fn builtin_bool(args: &[&str], shell: &mut Shell) -> i32 {
     SUCCESS
 }
 
-fn builtin_is(args: &[&str], shell: &mut Shell) -> i32 {
+fn builtin_is(args: &[String], shell: &mut Shell) -> i32 {
     match is(args, shell) {
         Ok(()) => SUCCESS,
         Err(why) => {
@@ -218,7 +218,7 @@ fn builtin_is(args: &[&str], shell: &mut Shell) -> i32 {
     }
 }
 
-fn builtin_dirs(args: &[&str], shell: &mut Shell) -> i32 {
+fn builtin_dirs(args: &[String], shell: &mut Shell) -> i32 {
     if check_help(args, MAN_DIRS) {
         return SUCCESS;
     }
@@ -226,7 +226,7 @@ fn builtin_dirs(args: &[&str], shell: &mut Shell) -> i32 {
     shell.directory_stack.dirs(args)
 }
 
-fn builtin_pushd(args: &[&str], shell: &mut Shell) -> i32 {
+fn builtin_pushd(args: &[String], shell: &mut Shell) -> i32 {
     if check_help(args, MAN_PUSHD) {
         return SUCCESS;
     }
@@ -241,7 +241,7 @@ fn builtin_pushd(args: &[&str], shell: &mut Shell) -> i32 {
     }
 }
 
-fn builtin_popd(args: &[&str], shell: &mut Shell) -> i32 {
+fn builtin_popd(args: &[String], shell: &mut Shell) -> i32 {
     if check_help(args, MAN_POPD) {
         return SUCCESS;
     }
@@ -256,27 +256,27 @@ fn builtin_popd(args: &[&str], shell: &mut Shell) -> i32 {
     }
 }
 
-fn builtin_alias(args: &[&str], shell: &mut Shell) -> i32 {
+fn builtin_alias(args: &[String], shell: &mut Shell) -> i32 {
     let args_str = args[1..].join(" ");
     alias(&mut shell.variables, &args_str)
 }
 
-fn builtin_unalias(args: &[&str], shell: &mut Shell) -> i32 {
+fn builtin_unalias(args: &[String], shell: &mut Shell) -> i32 {
     drop_alias(&mut shell.variables, args)
 }
 
 // TODO There is a man page for fn however the -h and --help flags are not
 // checked for.
-fn builtin_fn(_: &[&str], shell: &mut Shell) -> i32 { fn_(&mut shell.functions) }
+fn builtin_fn(_: &[String], shell: &mut Shell) -> i32 { fn_(&mut shell.functions) }
 
-fn builtin_read(args: &[&str], shell: &mut Shell) -> i32 {
+fn builtin_read(args: &[String], shell: &mut Shell) -> i32 {
     if check_help(args, MAN_READ) {
         return SUCCESS;
     }
     shell.variables.read(args)
 }
 
-fn builtin_drop(args: &[&str], shell: &mut Shell) -> i32 {
+fn builtin_drop(args: &[String], shell: &mut Shell) -> i32 {
     if check_help(args, MAN_DROP) {
         return SUCCESS;
     }
@@ -287,14 +287,14 @@ fn builtin_drop(args: &[&str], shell: &mut Shell) -> i32 {
     }
 }
 
-fn builtin_set(args: &[&str], shell: &mut Shell) -> i32 {
+fn builtin_set(args: &[String], shell: &mut Shell) -> i32 {
     if check_help(args, MAN_SET) {
         return SUCCESS;
     }
     set::set(args, shell)
 }
 
-fn builtin_eval(args: &[&str], shell: &mut Shell) -> i32 {
+fn builtin_eval(args: &[String], shell: &mut Shell) -> i32 {
     if check_help(args, MAN_EVAL) {
         return SUCCESS;
     }
@@ -309,14 +309,14 @@ fn builtin_eval(args: &[&str], shell: &mut Shell) -> i32 {
     }
 }
 
-fn builtin_history(args: &[&str], shell: &mut Shell) -> i32 {
+fn builtin_history(args: &[String], shell: &mut Shell) -> i32 {
     if check_help(args, MAN_HISTORY) {
         return SUCCESS;
     }
     shell.print_history(args)
 }
 
-fn builtin_source(args: &[&str], shell: &mut Shell) -> i32 {
+fn builtin_source(args: &[String], shell: &mut Shell) -> i32 {
     if check_help(args, MAN_SOURCE) {
         return SUCCESS;
     }
@@ -331,7 +331,7 @@ fn builtin_source(args: &[&str], shell: &mut Shell) -> i32 {
     }
 }
 
-fn builtin_echo(args: &[&str], _: &mut Shell) -> i32 {
+fn builtin_echo(args: &[String], _: &mut Shell) -> i32 {
     if check_help(args, MAN_ECHO) {
         return SUCCESS;
     }
@@ -346,7 +346,7 @@ fn builtin_echo(args: &[&str], _: &mut Shell) -> i32 {
     }
 }
 
-fn builtin_test(args: &[&str], _: &mut Shell) -> i32 {
+fn builtin_test(args: &[String], _: &mut Shell) -> i32 {
     // Do not use `check_help` for the `test` builtin. The
     // `test` builtin contains a "-h" option.
     match test(args) {
@@ -360,7 +360,7 @@ fn builtin_test(args: &[&str], _: &mut Shell) -> i32 {
 }
 
 // TODO create manpage.
-fn builtin_calc(args: &[&str], _: &mut Shell) -> i32 {
+fn builtin_calc(args: &[String], _: &mut Shell) -> i32 {
     match calc::calc(&args[1..]) {
         Ok(()) => SUCCESS,
         Err(why) => {
@@ -370,7 +370,7 @@ fn builtin_calc(args: &[&str], _: &mut Shell) -> i32 {
     }
 }
 
-fn builtin_random(args: &[&str], _: &mut Shell) -> i32 {
+fn builtin_random(args: &[String], _: &mut Shell) -> i32 {
     if check_help(args, MAN_RANDOM) {
         return SUCCESS;
     }
@@ -383,12 +383,12 @@ fn builtin_random(args: &[&str], _: &mut Shell) -> i32 {
     }
 }
 
-fn builtin_true(args: &[&str], _: &mut Shell) -> i32 {
+fn builtin_true(args: &[String], _: &mut Shell) -> i32 {
     check_help(args, MAN_TRUE);
     SUCCESS
 }
 
-fn builtin_false(args: &[&str], _: &mut Shell) -> i32 {
+fn builtin_false(args: &[String], _: &mut Shell) -> i32 {
     if check_help(args, MAN_FALSE) {
         return SUCCESS;
     }
@@ -396,32 +396,32 @@ fn builtin_false(args: &[&str], _: &mut Shell) -> i32 {
 }
 
 // TODO create a manpage
-fn builtin_wait(_: &[&str], shell: &mut Shell) -> i32 {
+fn builtin_wait(_: &[String], shell: &mut Shell) -> i32 {
     shell.wait_for_background();
     SUCCESS
 }
 
-fn builtin_jobs(args: &[&str], shell: &mut Shell) -> i32 {
+fn builtin_jobs(args: &[String], shell: &mut Shell) -> i32 {
     check_help(args, MAN_JOBS);
     job_control::jobs(shell);
     SUCCESS
 }
 
-fn builtin_bg(args: &[&str], shell: &mut Shell) -> i32 {
+fn builtin_bg(args: &[String], shell: &mut Shell) -> i32 {
     if check_help(args, MAN_BG) {
         return SUCCESS;
     }
     job_control::bg(shell, &args[1..])
 }
 
-fn builtin_fg(args: &[&str], shell: &mut Shell) -> i32 {
+fn builtin_fg(args: &[String], shell: &mut Shell) -> i32 {
     if check_help(args, MAN_FG) {
         return SUCCESS;
     }
     job_control::fg(shell, &args[1..])
 }
 
-fn builtin_suspend(args: &[&str], _: &mut Shell) -> i32 {
+fn builtin_suspend(args: &[String], _: &mut Shell) -> i32 {
     if check_help(args, MAN_SUSPEND) {
         return SUCCESS;
     }
@@ -429,7 +429,7 @@ fn builtin_suspend(args: &[&str], _: &mut Shell) -> i32 {
     SUCCESS
 }
 
-fn builtin_disown(args: &[&str], shell: &mut Shell) -> i32 {
+fn builtin_disown(args: &[String], shell: &mut Shell) -> i32 {
     for arg in args {
         if *arg == "--help" {
             print_man(MAN_DISOWN);
@@ -445,7 +445,7 @@ fn builtin_disown(args: &[&str], shell: &mut Shell) -> i32 {
     }
 }
 
-fn builtin_help(args: &[&str], shell: &mut Shell) -> i32 {
+fn builtin_help(args: &[String], shell: &mut Shell) -> i32 {
     let builtins = shell.builtins;
     let stdout = io::stdout();
     let mut stdout = stdout.lock();
@@ -471,7 +471,7 @@ fn builtin_help(args: &[&str], shell: &mut Shell) -> i32 {
     SUCCESS
 }
 
-fn builtin_exit(args: &[&str], shell: &mut Shell) -> i32 {
+fn builtin_exit(args: &[String], shell: &mut Shell) -> i32 {
     if check_help(args, MAN_EXIT) {
         return SUCCESS;
     }
@@ -489,7 +489,7 @@ fn builtin_exit(args: &[&str], shell: &mut Shell) -> i32 {
     )
 }
 
-fn builtin_exec(args: &[&str], shell: &mut Shell) -> i32 {
+fn builtin_exec(args: &[String], shell: &mut Shell) -> i32 {
     match exec(shell, &args[1..]) {
         // Shouldn't ever hit this case.
         Ok(()) => SUCCESS,
@@ -503,7 +503,7 @@ fn builtin_exec(args: &[&str], shell: &mut Shell) -> i32 {
 }
 
 use regex::Regex;
-fn builtin_matches(args: &[&str], _: &mut Shell) -> i32 {
+fn builtin_matches(args: &[String], _: &mut Shell) -> i32 {
     if check_help(args, MAN_MATCHES) {
         return SUCCESS;
     }
@@ -513,8 +513,8 @@ fn builtin_matches(args: &[&str], _: &mut Shell) -> i32 {
         let _ = stderr.write_all(b"match takes two arguments\n");
         return BAD_ARG;
     }
-    let input = args[1];
-    let re = match Regex::new(args[2]) {
+    let input = &args[1];
+    let re = match Regex::new(&args[2]) {
         Ok(r) => r,
         Err(e) => {
             let stderr = io::stderr();
@@ -532,7 +532,7 @@ fn builtin_matches(args: &[&str], _: &mut Shell) -> i32 {
     }
 }
 
-fn builtin_exists(args: &[&str], shell: &mut Shell) -> i32 {
+fn builtin_exists(args: &[String], shell: &mut Shell) -> i32 {
     if check_help(args, MAN_EXISTS) {
         return SUCCESS;
     }
@@ -546,21 +546,21 @@ fn builtin_exists(args: &[&str], shell: &mut Shell) -> i32 {
     }
 }
 
-fn builtin_which(args: &[&str], shell: &mut Shell) -> i32 {
+fn builtin_which(args: &[String], shell: &mut Shell) -> i32 {
     match which(args, shell) {
         Ok(result) => result,
         Err(()) => FAILURE,
     }
 }
 
-fn builtin_type(args: &[&str], shell: &mut Shell) -> i32 {
+fn builtin_type(args: &[String], shell: &mut Shell) -> i32 {
     match find_type(args, shell) {
         Ok(result) => result,
         Err(()) => FAILURE,
     }
 }
 
-fn builtin_isatty(args: &[&str], _: &mut Shell) -> i32 {
+fn builtin_isatty(args: &[String], _: &mut Shell) -> i32 {
     if check_help(args, MAN_ISATTY) {
         return SUCCESS;
     }
diff --git a/src/lib/builtins/random.rs b/src/lib/builtins/random.rs
index 958b0d93..9acedf41 100644
--- a/src/lib/builtins/random.rs
+++ b/src/lib/builtins/random.rs
@@ -3,7 +3,7 @@ use self::rand::Rng;
 use std::io::{self, Write};
 
 #[allow(unused_must_use)]
-fn rand_list(args: &[&str]) -> Result<(), String> {
+fn rand_list(args: &[String]) -> Result<(), String> {
     let stdout = io::stdout();
     let mut stdout = stdout.lock();
     let mut output = Vec::new();
@@ -13,7 +13,7 @@ fn rand_list(args: &[&str]) -> Result<(), String> {
     };
     while output.len() < arg1 {
         let rand_num = rand::thread_rng().gen_range(1, args.len());
-        output.push(args[rand_num]);
+        output.push(&*args[rand_num]);
         output.dedup();
     }
     for out in output {
@@ -23,7 +23,7 @@ fn rand_list(args: &[&str]) -> Result<(), String> {
     Ok(())
 }
 #[allow(unused_must_use)]
-pub(crate) fn random(args: &[&str]) -> Result<(), String> {
+pub(crate) fn random(args: &[String]) -> Result<(), String> {
     let stdout = io::stdout();
     let mut stdout = stdout.lock();
     match args.len() {
diff --git a/src/lib/builtins/set.rs b/src/lib/builtins/set.rs
index 36b810a4..cb3f9e0e 100644
--- a/src/lib/builtins/set.rs
+++ b/src/lib/builtins/set.rs
@@ -9,7 +9,7 @@ enum PositionalArgs {
 
 use self::PositionalArgs::*;
 
-pub(crate) fn set(args: &[&str], shell: &mut Shell) -> i32 {
+pub(crate) fn set(args: &[String], shell: &mut Shell) -> i32 {
     let mut args_iter = args.iter();
     let mut positionals = None;
 
@@ -28,14 +28,14 @@ pub(crate) fn set(args: &[&str], shell: &mut Shell) -> i32 {
             for flag in arg.bytes().skip(1) {
                 match flag {
                     b'e' => shell.flags |= ERR_EXIT,
-                    b'o' => match args_iter.next() {
-                        Some(&"vi") => if let Some(context) = shell.context.as_mut() {
+                    b'o' => match args_iter.next().map(|s| s as &str) {
+                        Some("vi") => if let Some(context) = shell.context.as_mut() {
                             context.key_bindings = KeyBindings::Vi;
                         },
-                        Some(&"emacs") => if let Some(context) = shell.context.as_mut() {
+                        Some("emacs") => if let Some(context) = shell.context.as_mut() {
                             context.key_bindings = KeyBindings::Emacs;
                         },
-                        Some(&"huponexit") => shell.flags |= HUPONEXIT,
+                        Some("huponexit") => shell.flags |= HUPONEXIT,
                         Some(_) => {
                             eprintln!("ion: set: invalid option");
                             return 0;
@@ -54,8 +54,8 @@ pub(crate) fn set(args: &[&str], shell: &mut Shell) -> i32 {
                 match flag {
                     b'e' => shell.flags &= 255 ^ ERR_EXIT,
                     b'x' => shell.flags &= 255 ^ PRINT_COMMS,
-                    b'o' => match args_iter.next() {
-                        Some(&"huponexit") => shell.flags &= 255 ^ HUPONEXIT,
+                    b'o' => match args_iter.next().map(|s| s as &str) {
+                        Some("huponexit") => shell.flags &= 255 ^ HUPONEXIT,
                         Some(_) => {
                             eprintln!("ion: set: invalid option");
                             return 0;
diff --git a/src/lib/builtins/source.rs b/src/lib/builtins/source.rs
index bb121ad9..9a52ea48 100644
--- a/src/lib/builtins/source.rs
+++ b/src/lib/builtins/source.rs
@@ -2,7 +2,7 @@ use shell::{FlowLogic, Shell};
 use std::{fs::File, io::Read};
 
 /// Evaluates the given file and returns 'SUCCESS' if it succeeds.
-pub(crate) fn source(shell: &mut Shell, arguments: &[&str]) -> Result<(), String> {
+pub(crate) fn source(shell: &mut Shell, arguments: &[String]) -> Result<(), String> {
     match arguments.get(1) {
         Some(argument) => if let Ok(mut file) = File::open(&argument) {
             let capacity = file.metadata().map(|x| x.len()).unwrap_or(0) as usize;
diff --git a/src/lib/builtins/status.rs b/src/lib/builtins/status.rs
index 55d0ac87..9802d873 100644
--- a/src/lib/builtins/status.rs
+++ b/src/lib/builtins/status.rs
@@ -12,7 +12,7 @@ bitflags! {
     }
 }
 
-pub(crate) fn status(args: &[&str], shell: &mut Shell) -> Result<(), String> {
+pub(crate) fn status(args: &[String], shell: &mut Shell) -> Result<(), String> {
     let mut flags = Flags::empty();
     let shell_args: Vec<_> = env::args().collect();
 
@@ -32,7 +32,7 @@ pub(crate) fn status(args: &[&str], shell: &mut Shell) -> Result<(), String> {
         return Err("status takes one argument\n".to_string());
     } else {
         for arg in args {
-            match *arg {
+            match &**arg {
                 "--help" => flags |= Flags::HELP,
                 "--is-login" => flags |= Flags::LOGIN_SHELL,
                 "--is-interactive" => flags |= Flags::INTERACTIVE,
diff --git a/src/lib/builtins/test.rs b/src/lib/builtins/test.rs
index 5189cefa..19615b06 100644
--- a/src/lib/builtins/test.rs
+++ b/src/lib/builtins/test.rs
@@ -4,14 +4,14 @@ use std::{
     fs, os::unix::fs::{FileTypeExt, MetadataExt, PermissionsExt}, path::Path, time::SystemTime,
 };
 
-pub(crate) fn test(args: &[&str]) -> Result<bool, String> {
+pub(crate) fn test(args: &[String]) -> Result<bool, String> {
     let arguments = &args[1..];
     evaluate_arguments(arguments)
 }
 
-fn evaluate_arguments(arguments: &[&str]) -> Result<bool, String> {
+fn evaluate_arguments(arguments: &[String]) -> Result<bool, String> {
     match arguments.first() {
-        Some(&s) if s.starts_with("-") && s[1..].starts_with(char::is_alphabetic) => {
+        Some(ref s) if s.starts_with("-") && s[1..].starts_with(char::is_alphabetic) => {
             // Access the second character in the flag string: this will be type of the
             // flag. If no flag was given, return `SUCCESS`
             s.chars().nth(1).map_or(Ok(true), |flag| {
@@ -23,7 +23,7 @@ fn evaluate_arguments(arguments: &[&str]) -> Result<bool, String> {
                 })
             })
         }
-        Some(&s) if s == "--help" => {
+        Some(ref s) if *s == "--help" => {
             // "--help" only makes sense if it is the first option. Only look for it
             // in the first position.
             print_man(MAN_TEST);
diff --git a/src/lib/shell/history.rs b/src/lib/shell/history.rs
index 2510a1e2..b187c6a9 100644
--- a/src/lib/shell/history.rs
+++ b/src/lib/shell/history.rs
@@ -37,7 +37,7 @@ impl IgnoreSetting {
 pub(crate) trait ShellHistory {
     /// Prints the commands contained within the history buffers to standard
     /// output.
-    fn print_history(&self, _arguments: &[&str]) -> i32;
+    fn print_history(&self, _arguments: &[String]) -> i32;
 
     /// Sets the history size for the shell context equal to the HISTORY_SIZE shell variable if
     /// it
@@ -134,7 +134,7 @@ impl ShellHistory for Shell {
         }
     }
 
-    fn print_history(&self, _arguments: &[&str]) -> i32 {
+    fn print_history(&self, _arguments: &[String]) -> i32 {
         if let Some(context) = self.context.as_ref() {
             let mut buffer = Vec::with_capacity(8 * 1024);
             for command in &context.history.buffers {
diff --git a/src/lib/shell/job.rs b/src/lib/shell/job.rs
index fc482c8e..d40debbf 100644
--- a/src/lib/shell/job.rs
+++ b/src/lib/shell/job.rs
@@ -192,12 +192,6 @@ macro_rules! set_field {
     };
 }
 
-fn collect_args(args: &[String]) -> SmallVec<[&str; 16]> {
-    args.iter()
-        .map(|x| x as &str)
-        .collect::<SmallVec<[&str; 16]>>()
-}
-
 impl RefinedJob {
     /// Returns a long description of this job: the commands and arguments
     pub(crate) fn long(&self) -> String {
@@ -242,8 +236,7 @@ impl RefinedJob {
                 ref stdout,
                 ref stderr,
             } => {
-                let args = collect_args(&args);
-                shell.exec_builtin(main, &args, stdout, stderr, stdin)
+                shell.exec_builtin(main, args, stdout, stderr, stdin)
             }
             RefinedJob::Function {
                 ref name,
diff --git a/src/lib/shell/mod.rs b/src/lib/shell/mod.rs
index 97c845ed..b7271b4a 100644
--- a/src/lib/shell/mod.rs
+++ b/src/lib/shell/mod.rs
@@ -281,8 +281,7 @@ impl<'a> Shell {
                     Some(SUCCESS)
                 } else {
                     let borrowed = &pipeline.items[0].job.args;
-                    let small: SmallVec<[&str; 4]> = borrowed.iter().map(|x| x as &str).collect();
-                    Some(main(&small, self))
+                    Some(main(&borrowed, self))
                 }
             } else {
                 Some(self.execute_pipeline(pipeline))
diff --git a/src/lib/shell/pipe_exec/mod.rs b/src/lib/shell/pipe_exec/mod.rs
index 22a12a21..898db64f 100644
--- a/src/lib/shell/pipe_exec/mod.rs
+++ b/src/lib/shell/pipe_exec/mod.rs
@@ -382,7 +382,7 @@ pub(crate) trait PipelineExecution {
     fn exec_builtin(
         &mut self,
         main: BuiltinFunction,
-        args: &[&str],
+        args: &[String],
         stdout: &Option<File>,
         stderr: &Option<File>,
         stdin: &Option<File>,
@@ -604,7 +604,7 @@ impl PipelineExecution for Shell {
     fn exec_builtin(
         &mut self,
         main: BuiltinFunction,
-        args: &[&str],
+        args: &[String],
         stdout: &Option<File>,
         stderr: &Option<File>,
         stdin: &Option<File>,
@@ -975,7 +975,6 @@ fn spawn_proc(
             ref stderr,
             ref stdin,
         } => {
-            let args: Vec<&str> = args.iter().map(|x| x as &str).collect();
             match unsafe { sys::fork() } {
                 Ok(0) => {
                     prepare_child(block_child, pgid);
diff --git a/src/lib/sys/unix/mod.rs b/src/lib/sys/unix/mod.rs
index 71da582c..38a05643 100644
--- a/src/lib/sys/unix/mod.rs
+++ b/src/lib/sys/unix/mod.rs
@@ -216,7 +216,7 @@ pub(crate) fn fork_and_exec<F: Fn()>(
     }
 }
 
-pub(crate) fn execve(prog: &str, args: &[&str], clear_env: bool) -> io::Error {
+pub(crate) fn execve(prog: &str, args: &[String], clear_env: bool) -> io::Error {
     let prog_str = match CString::new(prog) {
         Ok(prog) => prog,
         Err(_) => {
@@ -227,8 +227,8 @@ pub(crate) fn execve(prog: &str, args: &[&str], clear_env: bool) -> io::Error {
     // Create a vector of null-terminated strings.
     let mut cvt_args: Vec<CString> = Vec::new();
     cvt_args.push(prog_str.clone());
-    for &arg in args.iter() {
-        match CString::new(arg) {
+    for arg in args.iter() {
+        match CString::new(&**arg) {
             Ok(arg) => cvt_args.push(arg),
             Err(_) => {
                 return io::Error::last_os_error();
-- 
GitLab