From 7d623f73cc5c592c703f68d8079f78055841e113 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Mon, 26 Nov 2018 15:31:53 +0100 Subject: [PATCH 01/18] do not use 'let _', it is strange --- tests/compile-fail-fullmir/ptr_offset_overflow.rs | 2 +- tests/compile-fail/invalid_enum_discriminant.rs | 2 +- tests/compile-fail/pointer_byte_read_1.rs | 2 +- tests/compile-fail/pointer_byte_read_2.rs | 2 +- tests/compile-fail/ptr_bitops2.rs | 2 +- tests/compile-fail/ptr_int_cast.rs | 2 +- tests/compile-fail/ptr_offset_int_plus_int.rs | 2 +- tests/compile-fail/ptr_offset_int_plus_ptr.rs | 2 +- tests/compile-fail/ptr_rem.rs | 2 +- tests/compile-fail/ptr_wrapping_offset_int_plus_ptr.rs | 2 +- tests/compile-fail/transmute_fat1.rs | 2 +- tests/compile-fail/validity/invalid_char.rs | 2 +- tests/compile-fail/zst.rs | 2 +- tests/run-pass-fullmir/catch.rs | 2 +- tests/run-pass-fullmir/from_utf8.rs | 2 +- tests/run-pass-fullmir/threads.rs | 6 +++--- tests/run-pass/closure-drop.rs | 2 +- tests/run-pass/drop_empty_slice.rs | 2 +- tests/run-pass/issue-20575.rs | 2 +- tests/run-pass/issue-26709.rs | 2 +- tests/run-pass/issue-33387.rs | 2 +- tests/run-pass/issue-miri-184.rs | 2 +- tests/run-pass/sendable-class.rs | 4 ++-- tests/run-pass/slices.rs | 4 ++-- 24 files changed, 28 insertions(+), 28 deletions(-) diff --git a/tests/compile-fail-fullmir/ptr_offset_overflow.rs b/tests/compile-fail-fullmir/ptr_offset_overflow.rs index 32ab2daebf0..babd0246e7e 100644 --- a/tests/compile-fail-fullmir/ptr_offset_overflow.rs +++ b/tests/compile-fail-fullmir/ptr_offset_overflow.rs @@ -2,5 +2,5 @@ fn main() { let v = [1i8, 2]; let x = &v[1] as *const i8; - let _ = unsafe { x.offset(isize::min_value()) }; + let _val = unsafe { x.offset(isize::min_value()) }; } diff --git a/tests/compile-fail/invalid_enum_discriminant.rs b/tests/compile-fail/invalid_enum_discriminant.rs index bd5cb55b6c9..c1b8727c129 100644 --- a/tests/compile-fail/invalid_enum_discriminant.rs +++ b/tests/compile-fail/invalid_enum_discriminant.rs @@ -12,5 +12,5 @@ pub enum Foo { fn main() { let f = unsafe { std::mem::transmute::<i32, Foo>(42) }; - let _ = mem::discriminant(&f); + let _val = mem::discriminant(&f); } diff --git a/tests/compile-fail/pointer_byte_read_1.rs b/tests/compile-fail/pointer_byte_read_1.rs index b25f09d485f..a584863654c 100644 --- a/tests/compile-fail/pointer_byte_read_1.rs +++ b/tests/compile-fail/pointer_byte_read_1.rs @@ -3,5 +3,5 @@ fn main() { let y = &x; let z = &y as *const &i32 as *const usize; let ptr_bytes = unsafe { *z }; // the actual deref is fine, because we read the entire pointer at once - let _ = ptr_bytes / 432; //~ ERROR invalid arithmetic on pointers that would leak base addresses + let _val = ptr_bytes / 432; //~ ERROR invalid arithmetic on pointers that would leak base addresses } diff --git a/tests/compile-fail/pointer_byte_read_2.rs b/tests/compile-fail/pointer_byte_read_2.rs index 5df8c4782c7..ddb9bc1f995 100644 --- a/tests/compile-fail/pointer_byte_read_2.rs +++ b/tests/compile-fail/pointer_byte_read_2.rs @@ -3,5 +3,5 @@ fn main() { let y = &x; let z = &y as *const &i32 as *const u8; // the deref fails, because we are reading only a part of the pointer - let _ = unsafe { *z }; //~ ERROR tried to access part of a pointer value as raw bytes + let _val = unsafe { *z }; //~ ERROR tried to access part of a pointer value as raw bytes } diff --git a/tests/compile-fail/ptr_bitops2.rs b/tests/compile-fail/ptr_bitops2.rs index 233c9a733c9..5d5eab15508 100644 --- a/tests/compile-fail/ptr_bitops2.rs +++ b/tests/compile-fail/ptr_bitops2.rs @@ -1,5 +1,5 @@ fn main() { let val = 13usize; let addr = &val as *const _ as usize; - let _ = addr & 13; //~ ERROR access part of a pointer value as raw bytes + let _val = addr & 13; //~ ERROR access part of a pointer value as raw bytes } diff --git a/tests/compile-fail/ptr_int_cast.rs b/tests/compile-fail/ptr_int_cast.rs index 576f0c333d1..a823a0f49b6 100644 --- a/tests/compile-fail/ptr_int_cast.rs +++ b/tests/compile-fail/ptr_int_cast.rs @@ -4,5 +4,5 @@ fn main() { let x = x as *const i32; let x = x as u8; //~ ERROR a raw memory access tried to access part of a pointer value as raw bytes let x = x as *const i32; - let _ = unsafe { *x }; + let _val = unsafe { *x }; } diff --git a/tests/compile-fail/ptr_offset_int_plus_int.rs b/tests/compile-fail/ptr_offset_int_plus_int.rs index fa4efa32365..d0273961081 100644 --- a/tests/compile-fail/ptr_offset_int_plus_int.rs +++ b/tests/compile-fail/ptr_offset_int_plus_int.rs @@ -3,6 +3,6 @@ fn main() { // Can't offset an integer pointer by non-zero offset. unsafe { - let _ = (1 as *mut u8).offset(1); + let _val = (1 as *mut u8).offset(1); } } diff --git a/tests/compile-fail/ptr_offset_int_plus_ptr.rs b/tests/compile-fail/ptr_offset_int_plus_ptr.rs index b4554893580..b49c758c72f 100644 --- a/tests/compile-fail/ptr_offset_int_plus_ptr.rs +++ b/tests/compile-fail/ptr_offset_int_plus_ptr.rs @@ -4,6 +4,6 @@ fn main() { let ptr = Box::into_raw(Box::new(0u32)); // Can't start with an integer pointer and get to something usable unsafe { - let _ = (1 as *mut u8).offset(ptr as isize); + let _val = (1 as *mut u8).offset(ptr as isize); } } diff --git a/tests/compile-fail/ptr_rem.rs b/tests/compile-fail/ptr_rem.rs index 8a3665872f7..dfc91e9dc1b 100644 --- a/tests/compile-fail/ptr_rem.rs +++ b/tests/compile-fail/ptr_rem.rs @@ -1,5 +1,5 @@ fn main() { let val = 13usize; let addr = &val as *const _ as usize; - let _ = addr % 16; //~ ERROR access part of a pointer value as raw bytes + let _val = addr % 16; //~ ERROR access part of a pointer value as raw bytes } diff --git a/tests/compile-fail/ptr_wrapping_offset_int_plus_ptr.rs b/tests/compile-fail/ptr_wrapping_offset_int_plus_ptr.rs index b3dda27fad1..eacb9f07fff 100644 --- a/tests/compile-fail/ptr_wrapping_offset_int_plus_ptr.rs +++ b/tests/compile-fail/ptr_wrapping_offset_int_plus_ptr.rs @@ -4,5 +4,5 @@ fn main() { let ptr = Box::into_raw(Box::new(0u32)); // Can't start with an integer pointer and get to something usable let ptr = (1 as *mut u8).wrapping_offset(ptr as isize); - let _ = unsafe { *ptr }; + let _val = unsafe { *ptr }; } diff --git a/tests/compile-fail/transmute_fat1.rs b/tests/compile-fail/transmute_fat1.rs index ede0486be41..ddc78c8bf1d 100644 --- a/tests/compile-fail/transmute_fat1.rs +++ b/tests/compile-fail/transmute_fat1.rs @@ -10,5 +10,5 @@ fn main() { let bad = unsafe { std::mem::transmute::<&[u8], [u8; 8]>(&[1u8]) }; - let _ = bad[0] + bad[bad.len()-1]; //~ ERROR a raw memory access tried to access part of a pointer value as raw bytes + let _val = bad[0] + bad[bad.len()-1]; //~ ERROR a raw memory access tried to access part of a pointer value as raw bytes } diff --git a/tests/compile-fail/validity/invalid_char.rs b/tests/compile-fail/validity/invalid_char.rs index 0d75ad9d289..a3f90703634 100644 --- a/tests/compile-fail/validity/invalid_char.rs +++ b/tests/compile-fail/validity/invalid_char.rs @@ -1,6 +1,6 @@ fn main() { assert!(std::char::from_u32(-1_i32 as u32).is_none()); - let _ = match unsafe { std::mem::transmute::<i32, char>(-1) } { //~ ERROR encountered 4294967295, but expected something less or equal to 1114111 + let _val = match unsafe { std::mem::transmute::<i32, char>(-1) } { //~ ERROR encountered 4294967295, but expected something less or equal to 1114111 'a' => {true}, 'b' => {false}, _ => {true}, diff --git a/tests/compile-fail/zst.rs b/tests/compile-fail/zst.rs index 544d65a1bff..0488926870a 100644 --- a/tests/compile-fail/zst.rs +++ b/tests/compile-fail/zst.rs @@ -1,4 +1,4 @@ fn main() { let x = &() as *const () as *const i32; - let _ = unsafe { *x }; //~ ERROR access memory with alignment 1, but alignment 4 is required + let _val = unsafe { *x }; //~ ERROR access memory with alignment 1, but alignment 4 is required } diff --git a/tests/run-pass-fullmir/catch.rs b/tests/run-pass-fullmir/catch.rs index 960297daa7e..aa7bccaa5ff 100644 --- a/tests/run-pass-fullmir/catch.rs +++ b/tests/run-pass-fullmir/catch.rs @@ -3,6 +3,6 @@ use std::panic::{catch_unwind, AssertUnwindSafe}; fn main() { let mut i = 3; - let _ = catch_unwind(AssertUnwindSafe(|| {i -= 2;} )); + let _val = catch_unwind(AssertUnwindSafe(|| {i -= 2;} )); println!("{}", i); } diff --git a/tests/run-pass-fullmir/from_utf8.rs b/tests/run-pass-fullmir/from_utf8.rs index 69e6c521af6..ce59e60a932 100644 --- a/tests/run-pass-fullmir/from_utf8.rs +++ b/tests/run-pass-fullmir/from_utf8.rs @@ -1,3 +1,3 @@ fn main() { - let _ = ::std::str::from_utf8(b"a"); + let _val = ::std::str::from_utf8(b"a"); } diff --git a/tests/run-pass-fullmir/threads.rs b/tests/run-pass-fullmir/threads.rs index f920bc52edd..dad47d85a24 100644 --- a/tests/run-pass-fullmir/threads.rs +++ b/tests/run-pass-fullmir/threads.rs @@ -5,15 +5,15 @@ use std::sync; fn main() { let m = sync::Mutex::new(0); - let _ = m.lock(); + drop(m.lock()); drop(m); // We don't provide RwLock on Windows #[cfg(not(target_os = "windows"))] { let rw = sync::RwLock::new(0); - let _ = rw.read(); - let _ = rw.write(); + drop(rw.read()); + drop(rw.write()); drop(rw); } } diff --git a/tests/run-pass/closure-drop.rs b/tests/run-pass/closure-drop.rs index f1bdafaeb13..374efb6032b 100644 --- a/tests/run-pass/closure-drop.rs +++ b/tests/run-pass/closure-drop.rs @@ -17,7 +17,7 @@ fn main() { // this closure never by val uses its captures // so it's basically a fn(&self) // the shim used to not drop the `x` - let x = move || { let _ = x; }; + let x = move || { let _val = x; }; f(x); } assert!(ran_drop); diff --git a/tests/run-pass/drop_empty_slice.rs b/tests/run-pass/drop_empty_slice.rs index b21c8a612c5..8b481a0a2dd 100644 --- a/tests/run-pass/drop_empty_slice.rs +++ b/tests/run-pass/drop_empty_slice.rs @@ -3,5 +3,5 @@ fn main() { // With the nested Vec, this is calling Offset(Unique::empty(), 0) on drop. let args : Vec<Vec<i32>> = Vec::new(); - let _ = box args; + let _val = box args; } diff --git a/tests/run-pass/issue-20575.rs b/tests/run-pass/issue-20575.rs index 137d84c256b..01371f5bec6 100644 --- a/tests/run-pass/issue-20575.rs +++ b/tests/run-pass/issue-20575.rs @@ -13,5 +13,5 @@ fn main() { let functions: [Box<Fn() -> Option<()>>; 1] = [Box::new(|| None)]; - let _: Option<Vec<()>> = functions.iter().map(|f| (*f)()).collect(); + let _val: Option<Vec<()>> = functions.iter().map(|f| (*f)()).collect(); } diff --git a/tests/run-pass/issue-26709.rs b/tests/run-pass/issue-26709.rs index 62626d75865..e29e5fbcc40 100644 --- a/tests/run-pass/issue-26709.rs +++ b/tests/run-pass/issue-26709.rs @@ -20,7 +20,7 @@ fn main() { let mut x = 0; { let wrapper = Box::new(Wrapper(&mut x, 123)); - let _: Box<Wrapper<Send>> = wrapper; + let _val: Box<Wrapper<Send>> = wrapper; } assert_eq!(432, x) } diff --git a/tests/run-pass/issue-33387.rs b/tests/run-pass/issue-33387.rs index edbf2b81ce9..62a4263c106 100644 --- a/tests/run-pass/issue-33387.rs +++ b/tests/run-pass/issue-33387.rs @@ -15,5 +15,5 @@ trait Foo {} impl Foo for [u8; 2] {} fn main() { - let _: Arc<Foo + Send> = Arc::new([3, 4]); + let _val: Arc<Foo + Send> = Arc::new([3, 4]); } diff --git a/tests/run-pass/issue-miri-184.rs b/tests/run-pass/issue-miri-184.rs index 24775fe8a2d..39c841403ef 100644 --- a/tests/run-pass/issue-miri-184.rs +++ b/tests/run-pass/issue-miri-184.rs @@ -1,4 +1,4 @@ pub fn main() { let bytes: [u8; 8] = unsafe { ::std::mem::transmute(0u64) }; - let _: &[u8] = &bytes; + let _val: &[u8] = &bytes; } diff --git a/tests/run-pass/sendable-class.rs b/tests/run-pass/sendable-class.rs index 66f0c84e23c..3280c36e0a7 100644 --- a/tests/run-pass/sendable-class.rs +++ b/tests/run-pass/sendable-class.rs @@ -27,6 +27,6 @@ fn foo(i:isize, j: char) -> Foo { pub fn main() { let (tx, rx) = channel(); - let _ = tx.send(foo(42, 'c')); - let _ = rx; + tx.send(foo(42, 'c')).unwrap(); + let _val = rx; } diff --git a/tests/run-pass/slices.rs b/tests/run-pass/slices.rs index 45a2a74db08..4506a72e8dd 100644 --- a/tests/run-pass/slices.rs +++ b/tests/run-pass/slices.rs @@ -4,7 +4,7 @@ fn slice_of_zst() { fn foo<T>(v: &[T]) -> Option<&[T]> { let mut it = v.iter(); for _ in 0..5 { - let _ = it.next(); + it.next(); } Some(it.as_slice()) } @@ -12,7 +12,7 @@ fn slice_of_zst() { fn foo_mut<T>(v: &mut [T]) -> Option<&mut [T]> { let mut it = v.iter_mut(); for _ in 0..5 { - let _ = it.next(); + it.next(); } Some(it.into_slice()) } From 14d58ca8a90677e76908bcaa0df22e1ccbd5909f Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Sun, 25 Nov 2018 15:44:28 +0100 Subject: [PATCH 02/18] fix clippy lint whitelisting --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 10a1405b2a6..78481979479 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ #![feature(rustc_private)] -#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless))] +#![allow(clippy::cast_lossless)] #[macro_use] extern crate log; From 6bd76c7ee1d81f97a797022c0f3cee01769d7178 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Sun, 25 Nov 2018 16:08:24 +0100 Subject: [PATCH 03/18] cargo miri: factor package manifest logic into separate function --- Cargo.toml | 1 + src/bin/cargo-miri.rs | 125 +++++++++++++++++++++++++----------------- 2 files changed, 75 insertions(+), 51 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 94d13a83faf..84080538052 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,6 +42,7 @@ log = "0.4" vergen = "3" [features] +default = ["cargo_miri"] cargo_miri = ["cargo_metadata"] rustc_tests = [] diff --git a/src/bin/cargo-miri.rs b/src/bin/cargo-miri.rs index da4a351368d..19296238e2b 100644 --- a/src/bin/cargo-miri.rs +++ b/src/bin/cargo-miri.rs @@ -1,3 +1,5 @@ +#![feature(inner_deref)] + extern crate cargo_metadata; use std::path::{PathBuf, Path}; @@ -25,6 +27,13 @@ it to configure the resource limits available resource limits are `memory_size`, `step_limit`, `stack_limit` "#; +#[derive(Copy, Clone, Debug)] +enum MiriCommand { + Run, + Test, + Setup, +} + fn show_help() { println!("{}", CARGO_MIRI_HELP); } @@ -34,6 +43,54 @@ fn show_version() { env!("CARGO_PKG_VERSION"), env!("VERGEN_SHA_SHORT"), env!("VERGEN_COMMIT_DATE")); } +fn list_targets(mut args: impl Iterator<Item=String>) -> impl Iterator<Item=cargo_metadata::Target> { + // We need to get the manifest, and then the metadata, to enumerate targets. + let manifest_path_arg = args.find(|val| { + val.starts_with("--manifest-path=") + }); + + let mut metadata = if let Ok(metadata) = cargo_metadata::metadata( + manifest_path_arg.as_ref().map(AsRef::as_ref), + ) + { + metadata + } else { + let _ = std::io::stderr().write_fmt(format_args!( + "error: Could not obtain cargo metadata." + )); + std::process::exit(101); + }; + + let manifest_path = manifest_path_arg.map(|arg| { + PathBuf::from(Path::new(&arg["--manifest-path=".len()..])) + }); + + let current_dir = std::env::current_dir(); + + let package_index = metadata + .packages + .iter() + .position(|package| { + let package_manifest_path = Path::new(&package.manifest_path); + if let Some(ref manifest_path) = manifest_path { + package_manifest_path == manifest_path + } else { + let current_dir = current_dir.as_ref().expect( + "could not read current directory", + ); + let package_manifest_directory = package_manifest_path.parent().expect( + "could not find parent directory of package manifest", + ); + package_manifest_directory == current_dir + } + }) + .expect("could not find matching package"); + let package = metadata.packages.remove(package_index); + + // Finally we got the list of targets to build + package.targets.into_iter() +} + fn main() { // Check for version and help flags even when invoked as 'cargo-miri' if std::env::args().any(|a| a == "--help" || a == "-h") { @@ -51,61 +108,27 @@ fn main() { // binary so that we come back in the other branch, and dispatch // the invocations to rustc and miri, respectively. - let test = std::env::args().nth(2).map_or(false, |text| text == "test"); - let skip = if test { 3 } else { 2 }; - - // We need to get the manifest, and then the metadata, to enumerate targets. - let manifest_path_arg = std::env::args().skip(skip).find(|val| { - val.starts_with("--manifest-path=") - }); - - let mut metadata = if let Ok(metadata) = cargo_metadata::metadata( - manifest_path_arg.as_ref().map(AsRef::as_ref), - ) - { - metadata - } else { - let _ = std::io::stderr().write_fmt(format_args!( - "error: Could not obtain cargo metadata." - )); - std::process::exit(101); + let (subcommand, skip) = match std::env::args().nth(2).deref() { + Some("test") => (MiriCommand::Test, 3), + Some("run") => (MiriCommand::Run, 3), + Some("setup") => (MiriCommand::Setup, 3), + // Default command, if there is an option or nothing + Some(s) if s.starts_with("-") => (MiriCommand::Run, 2), + None => (MiriCommand::Run, 2), + // Unvalid command + Some(s) => { + eprintln!("Unknown command `{}`", s); + std::process::exit(1) + } }; - let manifest_path = manifest_path_arg.map(|arg| { - PathBuf::from(Path::new(&arg["--manifest-path=".len()..])) - }); - - let current_dir = std::env::current_dir(); - - let package_index = metadata - .packages - .iter() - .position(|package| { - let package_manifest_path = Path::new(&package.manifest_path); - if let Some(ref manifest_path) = manifest_path { - package_manifest_path == manifest_path - } else { - let current_dir = current_dir.as_ref().expect( - "could not read current directory", - ); - let package_manifest_directory = package_manifest_path.parent().expect( - "could not find parent directory of package manifest", - ); - package_manifest_directory == current_dir - } - }) - .expect("could not find matching package"); - let package = metadata.packages.remove(package_index); - - // Finally we got the metadata, iterate all targets and see for which ones - // we do anything. - for target in package.targets { + for target in list_targets(std::env::args().skip(skip)) { let args = std::env::args().skip(skip); let kind = target.kind.get(0).expect( "badly formatted cargo metadata: target::kind is an empty array", ); - match (test, &kind[..]) { - (true, "test") => { + match (subcommand, &kind[..]) { + (MiriCommand::Test, "test") => { // For test binaries we call `cargo rustc --test target -- <rustc args>` if let Err(code) = process( vec!["--test".to_string(), target.name].into_iter().chain( @@ -116,7 +139,7 @@ fn main() { std::process::exit(code); } } - (true, "lib") => { + (MiriCommand::Test, "lib") => { // For libraries we call `cargo rustc -- --test <rustc args>` // Notice now that `--test` is a rustc arg rather than a cargo arg. This tells // rustc to build a test harness which calls all #[test] functions. We don't @@ -131,7 +154,7 @@ fn main() { std::process::exit(code); } } - (false, "bin") => { + (MiriCommand::Run, "bin") => { // For ordinary binaries we call `cargo rustc --bin target -- <rustc args>` if let Err(code) = process( vec!["--bin".to_string(), target.name].into_iter().chain( From c945e30d100a79a2d2c73358d54d7545d03093ac Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Sun, 25 Nov 2018 16:30:11 +0100 Subject: [PATCH 04/18] setup routine to install xargo when missing --- src/bin/cargo-miri.rs | 58 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/src/bin/cargo-miri.rs b/src/bin/cargo-miri.rs index 19296238e2b..e39011db5ca 100644 --- a/src/bin/cargo-miri.rs +++ b/src/bin/cargo-miri.rs @@ -3,14 +3,19 @@ extern crate cargo_metadata; use std::path::{PathBuf, Path}; -use std::io::Write; +use std::io::{self, Write}; use std::process::Command; const CARGO_MIRI_HELP: &str = r#"Interprets bin crates Usage: - cargo miri [options] [--] [<opts>...] + cargo miri [subcommand] [options] [--] [<opts>...] + +Subcommands: + run Run binaries (default) + test Run tests + setup Only perform automatic setup, but without asking questions (for getting a proper libstd) Common options: -h, --help Print this message @@ -27,7 +32,7 @@ it to configure the resource limits available resource limits are `memory_size`, `step_limit`, `stack_limit` "#; -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] enum MiriCommand { Run, Test, @@ -43,6 +48,11 @@ fn show_version() { env!("CARGO_PKG_VERSION"), env!("VERGEN_SHA_SHORT"), env!("VERGEN_COMMIT_DATE")); } +fn show_error(msg: String) -> ! { + eprintln!("fatal error: {}", msg); + std::process::exit(1) +} + fn list_targets(mut args: impl Iterator<Item=String>) -> impl Iterator<Item=cargo_metadata::Target> { // We need to get the manifest, and then the metadata, to enumerate targets. let manifest_path_arg = args.find(|val| { @@ -91,6 +101,40 @@ fn list_targets(mut args: impl Iterator<Item=String>) -> impl Iterator<Item=carg package.targets.into_iter() } +fn ask(question: &str) { + let mut buf = String::new(); + print!("{} [Y/n] ", question); + io::stdout().flush().unwrap(); + io::stdin().read_line(&mut buf).unwrap(); + let answer = match buf.trim().to_lowercase().as_ref() { + "" | "y" | "yes" => true, + "n" | "no" => false, + a => show_error(format!("I do not understand `{}`", a)) + }; + if !answer { + show_error(format!("Aborting as per your request")) + } +} + +/// Perform the setup requires to make `cargo miri` work: Getting a custom-built libstd. Then sets MIRI_SYSROOT. +/// Skipped if MIRI_SYSROOT is already set, in that case we expect the user has done all this already. +fn setup(ask_user: bool) { + if std::env::var("MIRI_SYSROOT").is_ok() { + return; + } + + // First, we need xargo + if Command::new("xargo").arg("--version").output().is_err() + { + if ask_user { + ask("It seems you do not have xargo installed. I will run `cargo install xargo`. Proceed?"); + } + if !Command::new("cargo").args(&["install", "xargo"]).status().unwrap().success() { + show_error(format!("Failed to install xargo")); + } + } +} + fn main() { // Check for version and help flags even when invoked as 'cargo-miri' if std::env::args().any(|a| a == "--help" || a == "-h") { @@ -117,11 +161,15 @@ fn main() { None => (MiriCommand::Run, 2), // Unvalid command Some(s) => { - eprintln!("Unknown command `{}`", s); - std::process::exit(1) + show_error(format!("Unknown command `{}`", s)) } }; + // We always setup + let ask = subcommand != MiriCommand::Setup; + setup(ask); + + // Now run the command. for target in list_targets(std::env::args().skip(skip)) { let args = std::env::args().skip(skip); let kind = target.kind.get(0).expect( From 738133b379b172a37f8699085daff62b5a7d16a5 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Sun, 25 Nov 2018 17:09:49 +0100 Subject: [PATCH 05/18] complete setup routine: instal rust-src, build libstd, use it --- Cargo.toml | 3 ++- src/bin/cargo-miri.rs | 55 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 84080538052..111b47a551a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,6 +35,7 @@ required-features = ["rustc_tests"] [dependencies] byteorder = { version = "1.1", features = ["i128"]} cargo_metadata = { version = "0.6", optional = true } +dirs = { version = "1.0.4", optional = true } env_logger = "0.5" log = "0.4" @@ -43,7 +44,7 @@ vergen = "3" [features] default = ["cargo_miri"] -cargo_miri = ["cargo_metadata"] +cargo_miri = ["cargo_metadata", "dirs"] rustc_tests = [] [dev-dependencies] diff --git a/src/bin/cargo-miri.rs b/src/bin/cargo-miri.rs index e39011db5ca..1a5553ca109 100644 --- a/src/bin/cargo-miri.rs +++ b/src/bin/cargo-miri.rs @@ -5,7 +5,7 @@ extern crate cargo_metadata; use std::path::{PathBuf, Path}; use std::io::{self, Write}; use std::process::Command; - +use std::fs::{self, File}; const CARGO_MIRI_HELP: &str = r#"Interprets bin crates @@ -133,6 +133,59 @@ fn setup(ask_user: bool) { show_error(format!("Failed to install xargo")); } } + + // Then, we also need rust-src. Let's see if it is already installed. + let sysroot = Command::new("rustc").args(&["--print", "sysroot"]).output().unwrap().stdout; + let sysroot = std::str::from_utf8(&sysroot[..]).unwrap(); + let src = Path::new(sysroot.trim_end_matches('\n')).join("lib/rustlib/src"); + if !src.exists() { + println!("Could not find {:?}", src); + if ask_user { + ask("It seems you do not have the rust-src component installed. I will run `rustup component add rust-src`. Proceed?"); + } + if !Command::new("rustup").args(&["component", "add", "rust-src"]).status().unwrap().success() { + show_error(format!("Failed to install rust-src component")); + } + } + + // Next, we need our own libstd. We will do this work in ~/.miri. + let dir = dirs::home_dir().unwrap().join(".miri"); + if !dir.exists() { + fs::create_dir(&dir).unwrap(); + } + // The interesting bit: Xargo.toml + File::create(dir.join("Xargo.toml")).unwrap() + .write_all(br#" +[dependencies.std] +features = ["panic_unwind", "backtrace"] + +[dependencies.test] +stage = 1 + "#).unwrap(); + // The boring bits: A dummy project for xargo + File::create(dir.join("Cargo.toml")).unwrap() + .write_all(br#" +[package] +name = "miri-xargo" +description = "A dummy project for building libstd with xargo." +version = "0.0.0" + +[lib] +path = "lib.rs" + "#).unwrap(); + File::create(dir.join("lib.rs")).unwrap(); + // Run xargo + if !Command::new("xargo").arg("build") + .current_dir(&dir) + .env("RUSTFLAGS", miri::miri_default_args().join(" ")) + .env("XARGO_HOME", dir.to_str().unwrap()) + .status().unwrap().success() + { + show_error(format!("Failed to run xargo")); + } + + // That should be it! + std::env::set_var("MIRI_SYSROOT", dir.join("HOST")); } fn main() { From bb47df94ddf8620b10f18b528cb21b1b785f4226 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Sun, 25 Nov 2018 17:17:21 +0100 Subject: [PATCH 06/18] use cargo miri setup for CI --- .travis.yml | 8 +++----- appveyor.yml | 13 ++----------- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/.travis.yml b/.travis.yml index 85dd50cb5e3..e5a47a40a9b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,8 +28,6 @@ before_script: - rustup target add i686-unknown-linux-gnu - rustup target add i686-pc-windows-gnu - rustup target add i686-pc-windows-msvc -- rustup component add rust-src -- cargo install xargo || echo "Skipping xargo install" script: - set -e @@ -39,9 +37,9 @@ script: cargo test --release --all-features && cargo install --all-features --force --path . - | - # get ourselves a MIR-full libstd - xargo/build.sh && - export MIRI_SYSROOT=~/.xargo/HOST + # starting here, use MIR-full libstd + cargo miri setup && + export MIRI_SYSROOT=~/.miri/HOST - | # run all tests with full mir cargo test --release --all-features diff --git a/appveyor.yml b/appveyor.yml index 3dc47f1c67b..5757d1d2796 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -21,16 +21,6 @@ install: - rustup-init.exe -y --default-host %TARGET% --default-toolchain %RUST_TOOLCHAIN% - set PATH=%USERPROFILE%\.cargo\bin;%PATH% - rustc --version - # Customize installation. - - rustup component add rust-src - - cargo install xargo - # Prepare a libstd with MIR (cannot use bash script, obviously). - # The flags here should be kept in sync with `add_miri_default_args` in `src/lib.rs`. - - cd xargo - - set RUSTFLAGS=-Zalways-encode-mir -Zmir-emit-retag -Zmir-opt-level=0 - - xargo build - - set RUSTFLAGS= - - cd .. build: false @@ -39,7 +29,8 @@ test_script: - set RUST_BACKTRACE=1 - cargo build --release --all-features --all-targets - cargo test --release --all-features - - set MIRI_SYSROOT=%USERPROFILE%\.xargo\HOST + - cargo run --release --all-features --bin cargo-miri -- miri setup + - set MIRI_SYSROOT=%USERPROFILE%\.miri\HOST - cargo test --release --all-features notifications: From 16ac7ec1b1a7d07a1806d42e0f350580d537c121 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Sun, 25 Nov 2018 17:30:50 +0100 Subject: [PATCH 07/18] tweak comments, remove debug output --- .travis.yml | 6 +++--- appveyor.yml | 3 +++ src/bin/cargo-miri.rs | 3 +-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index e5a47a40a9b..9a8b8068900 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ os: - osx before_script: -# macOS weirdness (https://github.com/travis-ci/travis-ci/issues/6307) +# macOS weirdness (https://github.com/travis-ci/travis-ci/issues/6307, https://github.com/travis-ci/travis-ci/issues/10165) - if [[ "$TRAVIS_OS_NAME" == osx ]]; then rvm get stable; fi # Compute the rust version we use. We do not use "language: rust" to have more control here. - | @@ -37,11 +37,11 @@ script: cargo test --release --all-features && cargo install --all-features --force --path . - | - # starting here, use MIR-full libstd + # Get ourselves a MIR-full libstd cargo miri setup && export MIRI_SYSROOT=~/.miri/HOST - | - # run all tests with full mir + # Test miri with full MIR cargo test --release --all-features - | # Test cargo integration diff --git a/appveyor.yml b/appveyor.yml index 5757d1d2796..4287a08613f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -27,10 +27,13 @@ build: false test_script: - set RUSTFLAGS=-g - set RUST_BACKTRACE=1 + # Test plain miri - cargo build --release --all-features --all-targets - cargo test --release --all-features + # Get ourselves a MIR-full libstd - cargo run --release --all-features --bin cargo-miri -- miri setup - set MIRI_SYSROOT=%USERPROFILE%\.miri\HOST + # Test miri with full MIR - cargo test --release --all-features notifications: diff --git a/src/bin/cargo-miri.rs b/src/bin/cargo-miri.rs index 1a5553ca109..20d9e9ba71e 100644 --- a/src/bin/cargo-miri.rs +++ b/src/bin/cargo-miri.rs @@ -137,9 +137,8 @@ fn setup(ask_user: bool) { // Then, we also need rust-src. Let's see if it is already installed. let sysroot = Command::new("rustc").args(&["--print", "sysroot"]).output().unwrap().stdout; let sysroot = std::str::from_utf8(&sysroot[..]).unwrap(); - let src = Path::new(sysroot.trim_end_matches('\n')).join("lib/rustlib/src"); + let src = Path::new(sysroot.trim_end_matches('\n')).join("lib").join("rustlib").join("src"); if !src.exists() { - println!("Could not find {:?}", src); if ask_user { ask("It seems you do not have the rust-src component installed. I will run `rustup component add rust-src`. Proceed?"); } From cc4dd29f547ae96d6b6eb76441f166d7b3f734b7 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Sun, 25 Nov 2018 18:27:24 +0100 Subject: [PATCH 08/18] kill xargo dir and update docs --- README.md | 76 +++++++++++-------------------------- cargo-miri-test/run-test.py | 4 +- src/bin/cargo-miri.rs | 2 +- xargo/Cargo.lock | 4 -- xargo/Cargo.toml | 6 --- xargo/Xargo.toml | 5 --- xargo/build.sh | 4 -- xargo/src/lib.rs | 0 8 files changed, 25 insertions(+), 76 deletions(-) delete mode 100644 xargo/Cargo.lock delete mode 100644 xargo/Cargo.toml delete mode 100644 xargo/Xargo.toml delete mode 100755 xargo/build.sh delete mode 100644 xargo/src/lib.rs diff --git a/README.md b/README.md index 5e5a7a23c6a..5dced653bb0 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ in this directory. [rustup]: https://www.rustup.rs -## Running Miri +## Running Miri on tiny examples ```sh cargo +nightly run -- -Zmiri-disable-validation tests/run-pass/vecs.rs # Or whatever test you like. @@ -51,74 +51,42 @@ cargo +nightly run -- -Zmiri-disable-validation tests/run-pass/vecs.rs # Or what We have to disable validation because that can lead to errors when libstd is not compiled the right way. -## Running Miri with full libstd - -Per default libstd does not contain the MIR of non-polymorphic functions, and -also does not contain some extra MIR statements that miri needs for validation. -When Miri hits a call to such a function, execution terminates, and even when -the MIR is present, validation can fail. To fix this, it is possible to compile -libstd with full MIR: - -```sh -rustup component add --toolchain nightly rust-src -cargo +nightly install xargo -rustup run nightly xargo/build.sh -``` - -Now you can run Miri against the libstd compiled by xargo: - -```sh -MIRI_SYSROOT=~/.xargo/HOST cargo +nightly run tests/run-pass-fullmir/hashmap.rs -``` - -Notice that you will have to re-run the last step of the preparations above -(`xargo/build.sh`) when your toolchain changes (e.g., when you update the -nightly). - ## Running Miri on your own project('s test suite) -Install Miri as a cargo subcommand with `cargo +nightly install --all-features ---path .`. Be aware that if you used `rustup override set` to fix a particular -Rust version for the miri directory, that will *not* apply to your own project -directory! You have to use a consistent Rust version for building miri and your -project for this to work, so remember to either always specify the nightly -version manually, overriding it in your project directory as well, or use -`rustup default nightly` (or `rustup default nightly-YYYY-MM-DD`) to globally -make `nightly` the default toolchain. +Install Miri as a cargo subcommand with `cargo +nightly install --path .`. Be +aware that if you used `rustup override set` to fix a particular Rust version +for the miri directory, that will *not* apply to your own project directory! +You have to use a consistent Rust version for building miri and your project for +this to work, so remember to either always specify the nightly version manually, +overriding it in your project directory as well, or use `rustup default nightly` +(or `rustup default nightly-YYYY-MM-DD`) to globally make `nightly` the default +toolchain. -We assume that you have prepared a MIR-enabled libstd as described above. Now -compile your project and its dependencies against that libstd: - -1. Run `cargo clean` to eliminate any cached dependencies that were built against -the non-MIR `libstd`. -2. To run all tests in your project through, Miri, use -`MIRI_SYSROOT=~/.xargo/HOST cargo +nightly miri test`. **NOTE**: This is -currently broken, see the discussion in -[#479](https://github.com/solson/miri/issues/479). -3. If you have a binary project, you can run it through Miri using -`MIRI_SYSROOT=~/.xargo/HOST cargo +nightly miri`. +1. Run `cargo clean` to eliminate any cached dependencies. Miri needs your + dependencies to be compiled the right way, that would not happen if they have + previously already been compiled. +2. To run all tests in your project through Miri, use `cargo +nightly miri test`. + **NOTE**: This is currently broken, see the discussion in + [#479](https://github.com/solson/miri/issues/479). +3. If you have a binary project, you can run it through Miri using `cargo + +nightly miri run`. ### Common Problems When using the above instructions, you may encounter a number of confusing compiler errors. -#### "constant evaluation error: no mir for `<function>`" - -You may have forgotten to set `MIRI_SYSROOT` when calling `cargo miri`, and -your program called into `std` or `core`. Be sure to set `MIRI_SYSROOT=~/.xargo/HOST`. - #### "found possibly newer version of crate `std` which `<dependency>` depends on" -Your build directory may contain artifacts from an earlier build that did/did not -have `MIRI_SYSROOT` set. Run `cargo clean` before switching from non-Miri to Miri -builds and vice-versa. +Your build directory may contain artifacts from an earlier build that have/have +not been built for Miri. Run `cargo clean` before switching from non-Miri to +Miri builds and vice-versa. #### "found crate `std` compiled by an incompatible version of rustc" You may be running `cargo miri` with a different compiler version than the one -used to build the MIR-enabled `std`. Be sure to consistently use the same toolchain, -which should be the toolchain specified in the `rust-version` file. +used to build the custom libstd that Miri uses, and Miri failed to detect that. +Try deleting `~/.miri`. ## Miri `-Z` flags diff --git a/cargo-miri-test/run-test.py b/cargo-miri-test/run-test.py index f686cc47449..42745535e0e 100755 --- a/cargo-miri-test/run-test.py +++ b/cargo-miri-test/run-test.py @@ -8,10 +8,10 @@ and the working directory to contain the cargo-miri-test project. import sys, subprocess def test_cargo_miri(): - print("==> Testing `cargo miri` <==") + print("==> Testing `cargo miri run` <==") ## Call `cargo miri`, capture all output p = subprocess.Popen( - ["cargo", "miri", "-q"], + ["cargo", "miri", "run", "-q"], stdout=subprocess.PIPE, stderr=subprocess.PIPE ) diff --git a/src/bin/cargo-miri.rs b/src/bin/cargo-miri.rs index 20d9e9ba71e..5b6ff084024 100644 --- a/src/bin/cargo-miri.rs +++ b/src/bin/cargo-miri.rs @@ -174,7 +174,7 @@ path = "lib.rs" "#).unwrap(); File::create(dir.join("lib.rs")).unwrap(); // Run xargo - if !Command::new("xargo").arg("build") + if !Command::new("xargo").arg("build").arg("-q") .current_dir(&dir) .env("RUSTFLAGS", miri::miri_default_args().join(" ")) .env("XARGO_HOME", dir.to_str().unwrap()) diff --git a/xargo/Cargo.lock b/xargo/Cargo.lock deleted file mode 100644 index c85820b708b..00000000000 --- a/xargo/Cargo.lock +++ /dev/null @@ -1,4 +0,0 @@ -[[package]] -name = "miri-xargo" -version = "0.0.0" - diff --git a/xargo/Cargo.toml b/xargo/Cargo.toml deleted file mode 100644 index 9129c105b11..00000000000 --- a/xargo/Cargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "miri-xargo" -description = "A dummy project for building libstd with xargo." -version = "0.0.0" - -[dependencies] diff --git a/xargo/Xargo.toml b/xargo/Xargo.toml deleted file mode 100644 index e49b0dbe743..00000000000 --- a/xargo/Xargo.toml +++ /dev/null @@ -1,5 +0,0 @@ -[dependencies.std] -features = ["panic_unwind", "backtrace"] - -[dependencies.test] -stage = 1 diff --git a/xargo/build.sh b/xargo/build.sh deleted file mode 100755 index 25c56d31ab5..00000000000 --- a/xargo/build.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -cd "$(dirname "$0")" -# The flags here should be kept in sync with `add_miri_default_args` in `src/lib.rs`. -RUSTFLAGS='-Zalways-encode-mir -Zmir-emit-retag -Zmir-opt-level=0' xargo build diff --git a/xargo/src/lib.rs b/xargo/src/lib.rs deleted file mode 100644 index e69de29bb2d..00000000000 From 9dd0048e665710fb29e967b3a96c7fbd9d66ee76 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Sun, 25 Nov 2018 22:17:48 +0100 Subject: [PATCH 09/18] install directly from git repo --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5dced653bb0..d33b92f6de4 100644 --- a/README.md +++ b/README.md @@ -53,8 +53,13 @@ compiled the right way. ## Running Miri on your own project('s test suite) -Install Miri as a cargo subcommand with `cargo +nightly install --path .`. Be -aware that if you used `rustup override set` to fix a particular Rust version +Install Miri as a cargo subcommand: + +```sh +cargo +nightly install --git https://github.com/solson/miri/ +``` + +Be aware that if you used `rustup override set` to fix a particular Rust version for the miri directory, that will *not* apply to your own project directory! You have to use a consistent Rust version for building miri and your project for this to work, so remember to either always specify the nightly version manually, From b09dfc14a0e9dc4ace798dbcf9d381159808406b Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Sun, 25 Nov 2018 22:23:54 +0100 Subject: [PATCH 10/18] there are less places now to keep the flags in sync --- src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 78481979479..d2ead2493c0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -54,8 +54,7 @@ pub use crate::stacked_borrows::{Borrow, Stack, Stacks, BorStackItem}; /// set per default, for maximal validation power. pub fn miri_default_args() -> &'static [&'static str] { // The flags here should be kept in sync with what bootstrap adds when `test-miri` is - // set, which happens in `bootstrap/bin/rustc.rs` in the rustc sources; and also - // kept in sync with `xargo/build.sh` in this repo and `appveyor.yml`. + // set, which happens in `bootstrap/bin/rustc.rs` in the rustc sources. &["-Zalways-encode-mir", "-Zmir-emit-retag", "-Zmir-opt-level=0"] } From 82caed1a483f3e02f9e92987b88a87751bde4552 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Sun, 25 Nov 2018 22:29:25 +0100 Subject: [PATCH 11/18] cargo miri setup: print when we are executing commands --- src/bin/cargo-miri.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/bin/cargo-miri.rs b/src/bin/cargo-miri.rs index 5b6ff084024..edc0d35fa8d 100644 --- a/src/bin/cargo-miri.rs +++ b/src/bin/cargo-miri.rs @@ -128,6 +128,8 @@ fn setup(ask_user: bool) { { if ask_user { ask("It seems you do not have xargo installed. I will run `cargo install xargo`. Proceed?"); + } else { + println!("Installing xargo: `cargo install xargo`"); } if !Command::new("cargo").args(&["install", "xargo"]).status().unwrap().success() { show_error(format!("Failed to install xargo")); @@ -141,6 +143,8 @@ fn setup(ask_user: bool) { if !src.exists() { if ask_user { ask("It seems you do not have the rust-src component installed. I will run `rustup component add rust-src`. Proceed?"); + } else { + println!("Installing rust-src component: `rustup component add rust-src`"); } if !Command::new("rustup").args(&["component", "add", "rust-src"]).status().unwrap().success() { show_error(format!("Failed to install rust-src component")); From 58982d655a3544486e8d827035e6acc4da1f0ccd Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Mon, 26 Nov 2018 08:37:31 +0100 Subject: [PATCH 12/18] remove unneeded backtrace feature --- src/bin/cargo-miri.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/cargo-miri.rs b/src/bin/cargo-miri.rs index edc0d35fa8d..28cc9f93084 100644 --- a/src/bin/cargo-miri.rs +++ b/src/bin/cargo-miri.rs @@ -160,7 +160,7 @@ fn setup(ask_user: bool) { File::create(dir.join("Xargo.toml")).unwrap() .write_all(br#" [dependencies.std] -features = ["panic_unwind", "backtrace"] +features = ["panic_unwind"] [dependencies.test] stage = 1 From 07f78a37d4e8d7c55330e90e0a36815bf615a8d9 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Tue, 27 Nov 2018 08:16:52 +0100 Subject: [PATCH 13/18] tweaks --- Cargo.toml | 4 ++-- src/bin/cargo-miri.rs | 16 +++++----------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 111b47a551a..becb5c69e56 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,7 +35,7 @@ required-features = ["rustc_tests"] [dependencies] byteorder = { version = "1.1", features = ["i128"]} cargo_metadata = { version = "0.6", optional = true } -dirs = { version = "1.0.4", optional = true } +directories = { version = "1.0", optional = true } env_logger = "0.5" log = "0.4" @@ -44,7 +44,7 @@ vergen = "3" [features] default = ["cargo_miri"] -cargo_miri = ["cargo_metadata", "dirs"] +cargo_miri = ["cargo_metadata", "directories"] rustc_tests = [] [dev-dependencies] diff --git a/src/bin/cargo-miri.rs b/src/bin/cargo-miri.rs index 28cc9f93084..05d1bf32208 100644 --- a/src/bin/cargo-miri.rs +++ b/src/bin/cargo-miri.rs @@ -65,10 +65,7 @@ fn list_targets(mut args: impl Iterator<Item=String>) -> impl Iterator<Item=carg { metadata } else { - let _ = std::io::stderr().write_fmt(format_args!( - "error: Could not obtain cargo metadata." - )); - std::process::exit(101); + show_error(format!("error: Could not obtain cargo metadata.")); }; let manifest_path = manifest_path_arg.map(|arg| { @@ -106,14 +103,11 @@ fn ask(question: &str) { print!("{} [Y/n] ", question); io::stdout().flush().unwrap(); io::stdin().read_line(&mut buf).unwrap(); - let answer = match buf.trim().to_lowercase().as_ref() { - "" | "y" | "yes" => true, - "n" | "no" => false, + match buf.trim().to_lowercase().as_ref() { + "" | "y" | "yes" => {}, // proceed + "n" | "no" => show_error(format!("Aborting as per your request")), a => show_error(format!("I do not understand `{}`", a)) }; - if !answer { - show_error(format!("Aborting as per your request")) - } } /// Perform the setup requires to make `cargo miri` work: Getting a custom-built libstd. Then sets MIRI_SYSROOT. @@ -152,7 +146,7 @@ fn setup(ask_user: bool) { } // Next, we need our own libstd. We will do this work in ~/.miri. - let dir = dirs::home_dir().unwrap().join(".miri"); + let dir = directories::UserDirs::new().unwrap().home_dir().join(".miri"); if !dir.exists() { fs::create_dir(&dir).unwrap(); } From b91679539e7fbbd4ee4bccbdb5de5589c77cc322 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Tue, 27 Nov 2018 11:26:53 +0100 Subject: [PATCH 14/18] use proper platform cache dir --- src/bin/cargo-miri.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/bin/cargo-miri.rs b/src/bin/cargo-miri.rs index 05d1bf32208..f06bb2d3723 100644 --- a/src/bin/cargo-miri.rs +++ b/src/bin/cargo-miri.rs @@ -145,8 +145,9 @@ fn setup(ask_user: bool) { } } - // Next, we need our own libstd. We will do this work in ~/.miri. - let dir = directories::UserDirs::new().unwrap().home_dir().join(".miri"); + // Next, we need our own libstd. We will do this work in whatever is a good cache dir for this platform. + let dirs = directories::ProjectDirs::from("miri", "miri", "miri").unwrap(); + let dir = dirs.cache_dir(); if !dir.exists() { fs::create_dir(&dir).unwrap(); } From bd7f4076cdac11fb87629cc5aab1ba0fd77a806a Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Tue, 27 Nov 2018 11:43:02 +0100 Subject: [PATCH 15/18] we need to recursively create the dir --- src/bin/cargo-miri.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/cargo-miri.rs b/src/bin/cargo-miri.rs index f06bb2d3723..fb1b97269aa 100644 --- a/src/bin/cargo-miri.rs +++ b/src/bin/cargo-miri.rs @@ -149,7 +149,7 @@ fn setup(ask_user: bool) { let dirs = directories::ProjectDirs::from("miri", "miri", "miri").unwrap(); let dir = dirs.cache_dir(); if !dir.exists() { - fs::create_dir(&dir).unwrap(); + fs::create_dir_all(&dir).unwrap(); } // The interesting bit: Xargo.toml File::create(dir.join("Xargo.toml")).unwrap() From 53196554ec5c96f067611b96ffd3e1409274e4d0 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Tue, 27 Nov 2018 12:08:46 +0100 Subject: [PATCH 16/18] inform the user when and where we are creating a cache dir --- src/bin/cargo-miri.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bin/cargo-miri.rs b/src/bin/cargo-miri.rs index fb1b97269aa..ed4ffa43dbc 100644 --- a/src/bin/cargo-miri.rs +++ b/src/bin/cargo-miri.rs @@ -149,6 +149,7 @@ fn setup(ask_user: bool) { let dirs = directories::ProjectDirs::from("miri", "miri", "miri").unwrap(); let dir = dirs.cache_dir(); if !dir.exists() { + println!("Creating `{}` and using it for miri's build of libstd", dir.display()); fs::create_dir_all(&dir).unwrap(); } // The interesting bit: Xargo.toml From fbd7d119aecca4019467b2b191fcb1d88af2ed81 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Tue, 27 Nov 2018 11:46:09 +0100 Subject: [PATCH 17/18] use new dir for CI and docs --- .travis.yml | 8 ++++++-- README.md | 2 +- appveyor.yml | 4 ++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9a8b8068900..ba3b8d36399 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,9 +37,13 @@ script: cargo test --release --all-features && cargo install --all-features --force --path . - | - # Get ourselves a MIR-full libstd + # Get ourselves a MIR-full libstd, and use it henceforth cargo miri setup && - export MIRI_SYSROOT=~/.miri/HOST + if [ "$TRAVIS_OS_NAME" == osx ]; then + export MIRI_SYSROOT=~/Library/Caches/miri.miri.miri/HOST + else + export MIRI_SYSROOT=~/.cache/miri/HOST + fi - | # Test miri with full MIR cargo test --release --all-features diff --git a/README.md b/README.md index d33b92f6de4..d6e0be40cac 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ Miri builds and vice-versa. You may be running `cargo miri` with a different compiler version than the one used to build the custom libstd that Miri uses, and Miri failed to detect that. -Try deleting `~/.miri`. +Try deleting `~/.cache/miri`. ## Miri `-Z` flags diff --git a/appveyor.yml b/appveyor.yml index 4287a08613f..1f38b848c00 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -30,9 +30,9 @@ test_script: # Test plain miri - cargo build --release --all-features --all-targets - cargo test --release --all-features - # Get ourselves a MIR-full libstd + # Get ourselves a MIR-full libstd, and use it henceforth - cargo run --release --all-features --bin cargo-miri -- miri setup - - set MIRI_SYSROOT=%USERPROFILE%\.miri\HOST + - set MIRI_SYSROOT=%USERPROFILE%\AppData\Local\miri\miri\cache\HOST # Test miri with full MIR - cargo test --release --all-features From b72398de74161c0228d61501680ab653b9019b55 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Tue, 27 Nov 2018 14:48:46 +0100 Subject: [PATCH 18/18] fix README install instructions --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d6e0be40cac..dcf13a8af4a 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ compiled the right way. Install Miri as a cargo subcommand: ```sh -cargo +nightly install --git https://github.com/solson/miri/ +cargo +nightly install --git https://github.com/solson/miri/ miri ``` Be aware that if you used `rustup override set` to fix a particular Rust version