about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jsgf@fb.com>2019-08-19 19:02:12 -0700
committerJeremy Fitzhardinge <jsgf@fb.com>2019-08-20 12:34:14 -0700
commitd9497749a87440d836495da6d40a5ce667a67ccb (patch)
tree14627dbe922e215f02d4914ab54b3dcc1ca91efc
parentd2219c2e2e287d50c0f9761203d26d5fe3b0e639 (diff)
downloadrust-d9497749a87440d836495da6d40a5ce667a67ccb.tar.gz
rust-d9497749a87440d836495da6d40a5ce667a67ccb.zip
Move argfile expansion into run_compiler
This will make @path work with miri and other non-standard entrypoints.

Also since this simplifies librustc_driver::args, move it into a simple source file. Also
remove the tests since they're doing nothing more than checking `str::lines` has the right
behaviour.
-rw-r--r--src/librustc_driver/args.rs53
-rw-r--r--src/librustc_driver/args/mod.rs84
-rw-r--r--src/librustc_driver/args/tests.rs145
-rw-r--r--src/librustc_driver/lib.rs20
-rw-r--r--src/test/ui/commandline-argfile-badutf8.rs1
-rw-r--r--src/test/ui/commandline-argfile-badutf8.stderr2
-rw-r--r--src/test/ui/commandline-argfile-missing.rs2
-rw-r--r--src/test/ui/commandline-argfile-missing.stderr2
8 files changed, 70 insertions, 239 deletions
diff --git a/src/librustc_driver/args.rs b/src/librustc_driver/args.rs
new file mode 100644
index 00000000000..0906d358bad
--- /dev/null
+++ b/src/librustc_driver/args.rs
@@ -0,0 +1,53 @@
+use std::error;
+use std::fmt;
+use std::fs;
+use std::io;
+use std::str;
+use std::sync::atomic::{AtomicBool, Ordering};
+
+static USED_ARGSFILE_FEATURE: AtomicBool = AtomicBool::new(false);
+
+pub fn used_unstable_argsfile() -> bool {
+    USED_ARGSFILE_FEATURE.load(Ordering::Relaxed)
+}
+
+pub fn arg_expand(arg: String) -> Result<Vec<String>, Error> {
+    if arg.starts_with("@") {
+        let path = &arg[1..];
+        let file = match fs::read_to_string(path) {
+            Ok(file) => {
+                USED_ARGSFILE_FEATURE.store(true, Ordering::Relaxed);
+                file
+            }
+            Err(ref err) if err.kind() == io::ErrorKind::InvalidData => {
+                return Err(Error::Utf8Error(Some(path.to_string())));
+            }
+            Err(err) => return Err(Error::IOError(path.to_string(), err)),
+        };
+        Ok(file.lines().map(ToString::to_string).collect())
+    } else {
+        Ok(vec![arg])
+    }
+}
+
+#[derive(Debug)]
+pub enum Error {
+    Utf8Error(Option<String>),
+    IOError(String, io::Error),
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Error::Utf8Error(None) => write!(fmt, "Utf8 error"),
+            Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {}", path),
+            Error::IOError(path, err) => write!(fmt, "IO Error: {}: {}", path, err),
+        }
+    }
+}
+
+impl error::Error for Error {
+    fn description(&self) -> &'static str {
+        "argument error"
+    }
+}
diff --git a/src/librustc_driver/args/mod.rs b/src/librustc_driver/args/mod.rs
deleted file mode 100644
index a59f9afd8be..00000000000
--- a/src/librustc_driver/args/mod.rs
+++ /dev/null
@@ -1,84 +0,0 @@
-use std::env;
-use std::error;
-use std::fmt;
-use std::fs;
-use std::io;
-use std::str;
-use std::sync::atomic::{AtomicBool, Ordering};
-
-#[cfg(test)]
-mod tests;
-
-static USED_ARGSFILE_FEATURE: AtomicBool = AtomicBool::new(false);
-
-pub fn used_unstable_argsfile() -> bool {
-    USED_ARGSFILE_FEATURE.load(Ordering::Relaxed)
-}
-
-pub struct ArgsIter {
-    base: env::ArgsOs,
-    file: std::vec::IntoIter<String>,
-}
-
-impl ArgsIter {
-    pub fn new() -> Self {
-        ArgsIter { base: env::args_os(), file: vec![].into_iter() }
-    }
-}
-
-impl Iterator for ArgsIter {
-    type Item = Result<String, Error>;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        loop {
-            if let Some(line) = self.file.next() {
-                return Some(Ok(line));
-            }
-
-            let arg =
-                self.base.next().map(|arg| arg.into_string().map_err(|_| Error::Utf8Error(None)));
-            match arg {
-                Some(Err(err)) => return Some(Err(err)),
-                Some(Ok(ref arg)) if arg.starts_with("@") => {
-                    let path = &arg[1..];
-                    let file = match fs::read_to_string(path) {
-                        Ok(file) => {
-                            USED_ARGSFILE_FEATURE.store(true, Ordering::Relaxed);
-                            file
-                        }
-                        Err(ref err) if err.kind() == io::ErrorKind::InvalidData => {
-                            return Some(Err(Error::Utf8Error(Some(path.to_string()))));
-                        }
-                        Err(err) => return Some(Err(Error::IOError(path.to_string(), err))),
-                    };
-                    self.file =
-                        file.lines().map(ToString::to_string).collect::<Vec<_>>().into_iter();
-                }
-                Some(Ok(arg)) => return Some(Ok(arg)),
-                None => return None,
-            }
-        }
-    }
-}
-
-#[derive(Debug)]
-pub enum Error {
-    Utf8Error(Option<String>),
-    IOError(String, io::Error),
-}
-
-impl fmt::Display for Error {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Error::Utf8Error(None) => write!(fmt, "Utf8 error"),
-            Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {}", path),
-            Error::IOError(path, err) => write!(fmt, "IO Error: {}: {}", path, err),
-        }
-    }
-}
-
-impl error::Error for Error {
-    fn description(&self) -> &'static str {
-        "argument error"
-    }
-}
diff --git a/src/librustc_driver/args/tests.rs b/src/librustc_driver/args/tests.rs
deleted file mode 100644
index 080dd5cb746..00000000000
--- a/src/librustc_driver/args/tests.rs
+++ /dev/null
@@ -1,145 +0,0 @@
-use super::*;
-
-use std::str;
-
-fn want_args(v: impl IntoIterator<Item = &'static str>) -> Vec<String> {
-    v.into_iter().map(String::from).collect()
-}
-
-fn got_args(file: &[u8]) -> Result<Vec<String>, Error> {
-    let ret = str::from_utf8(file)
-        .map_err(|_| Error::Utf8Error(None))?
-        .lines()
-        .map(ToString::to_string)
-        .collect::<Vec<_>>();
-    Ok(ret)
-}
-
-#[test]
-fn nothing() {
-    let file = b"";
-
-    assert_eq!(got_args(file).unwrap(), want_args(vec![]));
-}
-
-#[test]
-fn empty() {
-    let file = b"\n";
-
-    assert_eq!(got_args(file).unwrap(), want_args(vec![""]));
-}
-
-#[test]
-fn simple() {
-    let file = b"foo";
-
-    assert_eq!(got_args(file).unwrap(), want_args(vec!["foo"]));
-}
-
-#[test]
-fn simple_eol() {
-    let file = b"foo\n";
-
-    assert_eq!(got_args(file).unwrap(), want_args(vec!["foo"]));
-}
-
-#[test]
-fn multi() {
-    let file = b"foo\nbar";
-
-    assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar"]));
-}
-
-#[test]
-fn multi_eol() {
-    let file = b"foo\nbar\n";
-
-    assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar"]));
-}
-
-#[test]
-fn multi_empty() {
-    let file = b"foo\n\nbar";
-
-    assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "", "bar"]));
-}
-
-#[test]
-fn multi_empty_eol() {
-    let file = b"foo\n\nbar\n";
-
-    assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "", "bar"]));
-}
-
-#[test]
-fn multi_empty_start() {
-    let file = b"\nfoo\nbar";
-
-    assert_eq!(got_args(file).unwrap(), want_args(vec!["", "foo", "bar"]));
-}
-
-#[test]
-fn multi_empty_end() {
-    let file = b"foo\nbar\n\n";
-
-    assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar", ""]));
-}
-
-#[test]
-fn simple_eol_crlf() {
-    let file = b"foo\r\n";
-
-    assert_eq!(got_args(file).unwrap(), want_args(vec!["foo"]));
-}
-
-#[test]
-fn multi_crlf() {
-    let file = b"foo\r\nbar";
-
-    assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar"]));
-}
-
-#[test]
-fn multi_eol_crlf() {
-    let file = b"foo\r\nbar\r\n";
-
-    assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar"]));
-}
-
-#[test]
-fn multi_empty_crlf() {
-    let file = b"foo\r\n\r\nbar";
-
-    assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "", "bar"]));
-}
-
-#[test]
-fn multi_empty_eol_crlf() {
-    let file = b"foo\r\n\r\nbar\r\n";
-
-    assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "", "bar"]));
-}
-
-#[test]
-fn multi_empty_start_crlf() {
-    let file = b"\r\nfoo\r\nbar";
-
-    assert_eq!(got_args(file).unwrap(), want_args(vec!["", "foo", "bar"]));
-}
-
-#[test]
-fn multi_empty_end_crlf() {
-    let file = b"foo\r\nbar\r\n\r\n";
-
-    assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar", ""]));
-}
-
-#[test]
-fn bad_utf8() {
-    let file = b"foo\x80foo";
-
-    match got_args(file).unwrap_err() {
-        Error::Utf8Error(_) => (),
-        bad => panic!("bad err: {:?}", bad),
-    }
-}
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 4843c1a951b..2cec404c3d7 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -140,14 +140,22 @@ impl Callbacks for TimePassesCallbacks {
 // See comments on CompilerCalls below for details about the callbacks argument.
 // The FileLoader provides a way to load files from sources other than the file system.
 pub fn run_compiler(
-    args: &[String],
+    at_args: &[String],
     callbacks: &mut (dyn Callbacks + Send),
     file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
     emitter: Option<Box<dyn Write + Send>>
 ) -> interface::Result<()> {
+    let mut args = Vec::new();
+    for arg in at_args {
+        match args::arg_expand(arg.clone()) {
+            Ok(arg) => args.extend(arg),
+            Err(err) => early_error(ErrorOutputType::default(),
+                &format!("Failed to load argument file: {}", err)),
+        }
+    }
     let diagnostic_output = emitter.map(|emitter| DiagnosticOutput::Raw(emitter))
                                    .unwrap_or(DiagnosticOutput::Default);
-    let matches = match handle_options(args) {
+    let matches = match handle_options(&args) {
         Some(matches) => matches,
         None => return Ok(()),
     };
@@ -1199,10 +1207,10 @@ pub fn main() {
     init_rustc_env_logger();
     let mut callbacks = TimePassesCallbacks::default();
     let result = report_ices_to_stderr_if_any(|| {
-        let args = args::ArgsIter::new().enumerate()
-            .map(|(i, arg)| arg.unwrap_or_else(|err| {
-                early_error(ErrorOutputType::default(),
-                            &format!("Argument {} is not valid: {}", i, err))
+        let args = env::args_os().enumerate()
+            .map(|(i, arg)| arg.into_string().unwrap_or_else(|arg| {
+                    early_error(ErrorOutputType::default(),
+                            &format!("Argument {} is not valid Unicode: {:?}", i, arg))
             }))
             .collect::<Vec<_>>();
         run_compiler(&args, &mut callbacks, None, None)
diff --git a/src/test/ui/commandline-argfile-badutf8.rs b/src/test/ui/commandline-argfile-badutf8.rs
index c017e7b5ea6..161715685b5 100644
--- a/src/test/ui/commandline-argfile-badutf8.rs
+++ b/src/test/ui/commandline-argfile-badutf8.rs
@@ -1,7 +1,6 @@
 // Check to see if we can get parameters from an @argsfile file
 //
 // build-fail
-// normalize-stderr-test: "Argument \d+" -> "Argument $$N"
 // compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-badutf8.args
 
 #[cfg(not(cmdline_set))]
diff --git a/src/test/ui/commandline-argfile-badutf8.stderr b/src/test/ui/commandline-argfile-badutf8.stderr
index cd8a03e34ea..9af6fc0a518 100644
--- a/src/test/ui/commandline-argfile-badutf8.stderr
+++ b/src/test/ui/commandline-argfile-badutf8.stderr
@@ -1,2 +1,2 @@
-error: Argument $N is not valid: Utf8 error in $DIR/commandline-argfile-badutf8.args
+error: Failed to load argument file: Utf8 error in $DIR/commandline-argfile-badutf8.args
 
diff --git a/src/test/ui/commandline-argfile-missing.rs b/src/test/ui/commandline-argfile-missing.rs
index 34faf076335..a29b4ab062d 100644
--- a/src/test/ui/commandline-argfile-missing.rs
+++ b/src/test/ui/commandline-argfile-missing.rs
@@ -1,7 +1,7 @@
 // Check to see if we can get parameters from an @argsfile file
 //
+// ignore-tidy-linelength
 // build-fail
-// normalize-stderr-test: "Argument \d+" -> "Argument $$N"
 // normalize-stderr-test: "os error \d+" -> "os error $$ERR"
 // normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING "
 // compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-missing.args
diff --git a/src/test/ui/commandline-argfile-missing.stderr b/src/test/ui/commandline-argfile-missing.stderr
index c0017782f2e..179ad831004 100644
--- a/src/test/ui/commandline-argfile-missing.stderr
+++ b/src/test/ui/commandline-argfile-missing.stderr
@@ -1,2 +1,2 @@
-error: Argument $N is not valid: IO Error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR)
+error: Failed to load argument file: IO Error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR)