diff --git a/src/main.rs b/src/main.rs
index f6b0f7dc04059d336ca641e707624d8eef27963f..bef24f5b2672c9970b8cc9652f81546f5b789252 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -23,11 +23,11 @@ extern crate calc;
 #[cfg(all(unix, not(target_os = "redox")))] extern crate users as users_unix;
 #[cfg(target_os = "redox")] extern crate syscall;
 
+#[macro_use] mod types;
 #[macro_use] mod parser;
 mod builtins;
 mod shell;
 mod ascii_helpers;
-mod types;
 
 use std::io::{stderr, Write, ErrorKind};
 
diff --git a/src/parser/pipelines.rs b/src/parser/pipelines.rs
index 8c7d5249abdd7b5448d156c8f66ba28c67023950..e6d444ab9a4170ff00d555246038a7141dc9048c 100644
--- a/src/parser/pipelines.rs
+++ b/src/parser/pipelines.rs
@@ -304,7 +304,7 @@ mod tests {
     use shell::flow_control::Statement;
     use parser::peg::{parse, Pipeline, RedirectFrom, Redirection};
     use shell::{Job, JobKind};
-    use types::*;
+    use types::Array;
 
     #[test]
     fn stderr_redirection() {
@@ -552,8 +552,8 @@ mod tests {
         if let Statement::Pipeline(pipeline) = parse("echo one && echo two") {
             let jobs = pipeline.jobs;
             assert_eq!(JobKind::And, jobs[0].kind);
-            assert_eq!(Array::from_vec(vec![String::from("echo"), String::from("one")]), jobs[0].args);
-            assert_eq!(Array::from_vec(vec![String::from("echo"), String::from("two")]), jobs[1].args);
+            assert_eq!(array!["echo", "one"], jobs[0].args);
+            assert_eq!(array!["echo", "two"], jobs[1].args);
         } else {
             assert!(false);
         }
@@ -657,11 +657,9 @@ mod tests {
         let input = "cat | echo hello | cat < stuff ^>> other";
         let expected = Pipeline {
             jobs: vec![
-                Job::new(Array::from_vec(vec!["cat".into()]),
-                         JobKind::Pipe(RedirectFrom::Stdout)),
-                Job::new(Array::from_vec(vec!["echo".into(), "hello".into()]),
-                         JobKind::Pipe(RedirectFrom::Stdout)),
-                Job::new(Array::from_vec(vec!["cat".into()]), JobKind::Last)
+                Job::new(array!["cat"], JobKind::Pipe(RedirectFrom::Stdout)),
+                Job::new(array!["echo", "hello"], JobKind::Pipe(RedirectFrom::Stdout)),
+                Job::new(array!["cat"], JobKind::Last)
             ],
             stdin: Some(Redirection {
                 from: RedirectFrom::Stdout,
@@ -682,11 +680,9 @@ mod tests {
         let input = "cat | echo hello | cat < stuff &>> other";
         let expected = Pipeline {
             jobs: vec![
-                Job::new(Array::from_vec(vec!["cat".into()]),
-                         JobKind::Pipe(RedirectFrom::Stdout)),
-                Job::new(Array::from_vec(vec!["echo".into(), "hello".into()]),
-                         JobKind::Pipe(RedirectFrom::Stdout)),
-                Job::new(Array::from_vec(vec!["cat".into()]), JobKind::Last)
+                Job::new(array!["cat"], JobKind::Pipe(RedirectFrom::Stdout)),
+                Job::new(array!["echo", "hello"], JobKind::Pipe(RedirectFrom::Stdout)),
+                Job::new(array!["cat"], JobKind::Last)
             ],
             stdin: Some(Redirection {
                 from: RedirectFrom::Stdout,
@@ -754,7 +750,7 @@ mod tests {
         let input = "echo zardoz >> foo\\'bar";
         let expected = Pipeline {
             jobs: vec![
-                Job::new(Array::from_vec(vec!["echo".into(), "zardoz".into()]), JobKind::Last),
+                Job::new(array!["echo", "zardoz"], JobKind::Last),
             ],
             stdin: None,
             stdout: Some(Redirection {
diff --git a/src/parser/shell_expand/mod.rs b/src/parser/shell_expand/mod.rs
index c168c4878d7e24ae1c0210b15bc94d2de25fa637..aaf8687f12f47a82daf4c82bec54b916fa89866a 100644
--- a/src/parser/shell_expand/mod.rs
+++ b/src/parser/shell_expand/mod.rs
@@ -340,7 +340,7 @@ pub fn expand_tokens<'a>(token_buffer: &[WordToken], expand_func: &'a ExpanderFu
                     } else {
                         let mut output = String::new();
                         array_method.handle(&mut output, expand_func);
-                        Array::from_vec(vec![output])
+                        array!(output)
                     };
                 },
                 _ => ()
@@ -530,7 +530,7 @@ mod test {
         let input = "$FOO:NOT:$BAR";
         let expected = "FOO:NOT:BAR";
         let expanded = expand_string(input, &functions!(), false);
-        assert_eq!(Array::from_vec(vec![expected.to_owned()]), expanded);
+        assert_eq!(array![expected], expanded);
     }
 
     #[test]
@@ -549,19 +549,19 @@ mod test {
     #[test]
     fn expand_variables_with_colons() {
         let expanded = expand_string("$FOO:$BAR", &functions!(), false);
-        assert_eq!(Array::from_vec(vec!["FOO:BAR".to_owned()]), expanded);
+        assert_eq!(array!["FOO:BAR"], expanded);
     }
 
     #[test]
     fn expand_multiple_variables() {
         let expanded = expand_string("${B}${C}...${D}", &functions!(), false);
-        assert_eq!(Array::from_vec(vec!["testing...1 2 3".to_owned()]), expanded);
+        assert_eq!(array!["testing...1 2 3"], expanded);
     }
 
     #[test]
     fn expand_variable_alongside_braces() {
         let line = "$A{1,2}";
-        let expected = Array::from_vec(vec!["11".to_owned(), "12".to_owned()]);
+        let expected = array!["11", "12"];
         let expanded = expand_string(line, &functions!(), false);
         assert_eq!(expected, expanded);
     }
@@ -569,7 +569,7 @@ mod test {
     #[test]
     fn expand_variable_within_braces() {
         let line = "1{$A,2}";
-        let expected = Array::from_vec(vec!["11".to_owned(), "12".to_owned()]);
+        let expected = array!["11", "12"];
         let expanded = expand_string(line, &functions!(), false);
         assert_eq!(&expected, &expanded);
     }
@@ -579,14 +579,14 @@ mod test {
         let base = |idx : &str| format!("[1 2 3][{}]", idx);
         let expander = functions!();
         {
-            let expected = Array::from_vec(vec!["1".to_owned()]);
+            let expected = array!["1"];
             let idxs = vec!["-3", "0", "..-2"];
             for idx in idxs {
                 assert_eq!(expected, expand_string(&base(idx), &expander, false));
             }
         }
         {
-            let expected = Array::from_vec(vec!["2".to_owned(), "3".to_owned()]);
+            let expected = array!["2", "3"];
             let idxs = vec!["1...2", "1...-1"];
             for idx in idxs {
                 assert_eq!(expected, expand_string(&base(idx), &expander, false));
@@ -605,24 +605,24 @@ mod test {
     fn embedded_array_expansion() {
         let line = |idx : &str| format!("[[foo bar] [baz bat] [bing crosby]][{}]", idx);
         let expander = functions!();
-        let cases : Vec<(Vec<String>, &str)> = vec![
-            (vec!["foo".into()], "0"),
-            (vec!["baz".into()], "2"),
-            (vec!["bat".into()], "-3"),
-            (vec!["bar".into(), "baz".into(), "bat".into()], "1...3")
+        let cases = vec![
+            (array!["foo"], "0"),
+            (array!["baz"], "2"),
+            (array!["bat"], "-3"),
+            (array!["bar", "baz", "bat"], "1...3")
         ];
         for (expected, idx) in cases {
-            assert_eq!(Array::from_vec(expected), expand_string(&line(idx), &expander, false));
+            assert_eq!(expected, expand_string(&line(idx), &expander, false));
         }
     }
 
     #[test]
     fn arith_expression() {
         let line = "$((A * A - (A + A)))";
-        let expected = Array::from_vec(vec!["-1".to_owned()]);
+        let expected = array!["-1"];
         assert_eq!(expected, expand_string(line, &functions!(), false));
         let line = "$((3 * 10 - 27))";
-        let expected = Array::from_vec(vec!["3".to_owned()]);
+        let expected = array!["3"];
         assert_eq!(expected, expand_string(line, &functions!(), false));
     }
 }
diff --git a/src/parser/shell_expand/words.rs b/src/parser/shell_expand/words.rs
index cec56c3804b9c0ccade949875cbd964915fb10d4..34ad5b4088410603386e73a47a9b1cecf32ac1a6 100644
--- a/src/parser/shell_expand/words.rs
+++ b/src/parser/shell_expand/words.rs
@@ -1370,7 +1370,7 @@ mod tests {
             pattern: Pattern::Whitespace,
             selection: Select::Index(Index::Forward(3))
         };
-        let expected = Array::from_vec(vec!["é".into()]);
+        let expected = array!["é"];
         assert_eq!(method.handle_as_array(&expanders), expected);
         let method = ArrayMethod {
             method: "chars",
@@ -1378,7 +1378,7 @@ mod tests {
             pattern: Pattern::Whitespace,
             selection: Select::Index(Index::Forward(3))
         };
-        let expected = Array::from_vec(vec!["e".into()]);
+        let expected = array!["e"];
         assert_eq!(method.handle_as_array(&expanders), expected);
         let method = ArrayMethod {
             method: "bytes",
@@ -1386,7 +1386,7 @@ mod tests {
             pattern: Pattern::Whitespace,
             selection: Select::Index(Index::Forward(1))
         };
-        let expected = Array::from_vec(vec!["111".into()]);
+        let expected = array!["111"];
         assert_eq!(method.handle_as_array(&expanders), expected);
     }
 
diff --git a/src/types.rs b/src/types.rs
index e5fcf4b2390c337632cf1fa28f816e8a09544aa2..4a31477f002494a9756214b56599fee4f3e54380 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -7,3 +7,29 @@ pub type Identifier = SmallString;
 pub type Value = String;
 pub type VariableContext = FnvHashMap<Identifier, Value>;
 pub type ArrayVariableContext = FnvHashMap<Identifier, Array>;
+
+/// Construct a new Array containing the given arguments
+///
+/// `array!` acts like the standard library's `vec!` macro, and can be thought
+/// of as a shorthand for:
+/// ```ignore,rust
+/// Array::from_vec(vec![...])
+/// ```
+/// Additionally it will call `Into::into` on each of its members so that one
+/// can pass in any type with some `To<SmallString>` implementation; they will
+/// automatically be converted to owned SmallStrings.
+/// ```
+/// let verbose = Array::from_vec(vec!["foo".into(), "bar".into(),
+///                                    "baz".into(), "zar".into(),
+///                                    "doz".into()]);
+/// let concise = array!["foo", "bar", "baz", "zar", "doz"];
+/// assert_eq!(verbose, concise);
+/// ```
+#[macro_export]
+macro_rules! array [
+    ( $($x:expr), *) => ({
+        let mut _arr = Array::new();
+        $(_arr.push($x.into());)*
+        _arr
+    })
+];