Skip to content

Commit a03d184

Browse files
authored
Merge branch 'master' into rustup
2 parents d5820d4 + 8359898 commit a03d184

28 files changed

+331
-158
lines changed

.travis.yml

Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,51 +12,22 @@ os:
1212
dist: xenial
1313

1414
before_script:
15-
# install extra stuff for cross-compilation
15+
# Linux: install extra stuff for cross-compilation
1616
- if [[ "$TRAVIS_OS_NAME" == linux ]]; then sudo apt update && sudo apt install gcc-multilib; fi
17-
# macOS weirdness (https://github.com/travis-ci/travis-ci/issues/6307, https://github.com/travis-ci/travis-ci/issues/10165)
18-
- if [[ "$TRAVIS_OS_NAME" == osx ]]; then rvm get stable; fi
1917
# Compute the rust version we use. We do not use "language: rust" to have more control here.
2018
- |
2119
if [[ "$TRAVIS_EVENT_TYPE" == cron ]]; then
2220
RUST_TOOLCHAIN=nightly
2321
else
2422
RUST_TOOLCHAIN=$(cat rust-version)
2523
fi
26-
- |
27-
if [ "$TRAVIS_OS_NAME" == osx ]; then
28-
export MIRI_SYSROOT_BASE=~/Library/Caches/miri.miri.miri/
29-
else
30-
export MIRI_SYSROOT_BASE=~/.cache/miri/
31-
fi
32-
- |
33-
if [[ "$TRAVIS_OS_NAME" == osx ]]; then
34-
FOREIGN_TARGET=i686-apple-darwin
35-
else
36-
FOREIGN_TARGET=i686-unknown-linux-gnu
37-
fi
3824
# install Rust
3925
- curl https://build.travis-ci.org/files/rustup-init.sh -sSf | sh -s -- -y --default-toolchain "$RUST_TOOLCHAIN"
4026
- export PATH=$HOME/.cargo/bin:$PATH
4127
- rustc --version
4228

4329
script:
44-
- set -e
45-
- |
46-
# Build and install miri
47-
cargo build --release --all-features --all-targets &&
48-
cargo install --all-features --force --path .
49-
- |
50-
# Get ourselves a MIR-full libstd for the host and a foreign architecture
51-
cargo miri setup &&
52-
cargo miri setup --target "$FOREIGN_TARGET"
53-
- |
54-
# Test miri with full MIR, on the host and other architectures
55-
MIRI_SYSROOT=$MIRI_SYSROOT_BASE/HOST cargo test --release --all-features &&
56-
MIRI_SYSROOT=$MIRI_SYSROOT_BASE MIRI_TARGET=$FOREIGN_TARGET cargo test --release --all-features
57-
- |
58-
# Test cargo integration
59-
(cd test-cargo-miri && MIRI_SYSROOT=$MIRI_SYSROOT_BASE/HOST ./run-test.py)
30+
- ./travis.sh
6031

6132
notifications:
6233
email:
@@ -67,3 +38,4 @@ branches:
6738
env:
6839
global:
6940
- RUST_TEST_NOCAPTURE=1
41+
- RUST_BACKTRACE=1

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ directories = { version = "1.0", optional = true }
3939
rustc_version = { version = "0.2.3", optional = true }
4040
env_logger = "0.5"
4141
log = "0.4"
42+
# A noop dependency that changes in the Rust repository, it's a bit of a hack.
43+
# See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust`
44+
# for more information.
45+
rustc-workspace-hack = "1.0.0"
4246

4347
[build-dependencies]
4448
vergen = "3"

README.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,28 @@ example above), overriding it in your project directory as well, or use `rustup
3939
default nightly` (or `rustup default nightly-YYYY-MM-DD`) to globally make
4040
`nightly` the default toolchain.
4141

42-
Now you can run your project in miri:
42+
Now you can run your project in Miri:
4343

4444
1. Run `cargo clean` to eliminate any cached dependencies. Miri needs your
4545
dependencies to be compiled the right way, that would not happen if they have
4646
previously already been compiled.
4747
2. To run all tests in your project through Miri, use `cargo +nightly miri test`.
48-
**NOTE**: This is currently broken, see the discussion in
49-
[#479](https://github.com/solson/miri/issues/479).
5048
3. If you have a binary project, you can run it through Miri using `cargo
5149
+nightly miri run`.
5250

51+
When running code via `cargo miri`, the `cargo-miri` feature is set. You can
52+
use this to exclude test cases that will fail under Miri because they do things
53+
Miri does not support:
54+
55+
```rust
56+
#[cfg(not(feature = "cargo-miri"))]
57+
#[test]
58+
fn does_not_work_on_miri() {
59+
let x = 0u8;
60+
assert!(&x as *const _ as usize % 4 < 4);
61+
}
62+
```
63+
5364
### Common Problems
5465

5566
When using the above instructions, you may encounter a number of confusing compiler

appveyor.yml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,19 @@ install:
2525
build: false
2626

2727
test_script:
28-
- set RUSTFLAGS=-g
28+
- set RUST_TEST_NOCAPTURE=1
2929
- set RUST_BACKTRACE=1
30-
# Build miri
30+
# Build and install miri
3131
- cargo build --release --all-features --all-targets
32+
- cargo install --all-features --force --path .
3233
# Get ourselves a MIR-full libstd, and use it henceforth
33-
- cargo run --release --all-features --bin cargo-miri -- miri setup
34+
- cargo miri setup
3435
- set MIRI_SYSROOT=%USERPROFILE%\AppData\Local\miri\miri\cache\HOST
3536
# Test miri
3637
- cargo test --release --all-features
38+
# Test cargo integration
39+
- cd test-cargo-miri
40+
- python3 run-test.py
3741

3842
notifications:
3943
- provider: Email

rust-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
nightly-2018-12-08
1+
nightly-2018-12-18

src/bin/cargo-miri.rs

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
extern crate cargo_metadata;
44

55
use std::path::{PathBuf, Path};
6-
use std::io::{self, Write};
6+
use std::io::{self, Write, BufRead};
77
use std::process::Command;
88
use std::fs::{self, File};
99

@@ -114,6 +114,42 @@ fn list_targets() -> impl Iterator<Item=cargo_metadata::Target> {
114114
package.targets.into_iter()
115115
}
116116

117+
fn xargo_version() -> Option<(u32, u32, u32)> {
118+
let out = Command::new("xargo").arg("--version").output().ok()?;
119+
if !out.status.success() {
120+
return None;
121+
}
122+
// Parse output. The first line looks like "xargo 0.3.12 (b004f1c 2018-12-13)".
123+
let line = out.stderr.lines().nth(0)
124+
.expect("malformed `xargo --version` output: not at least one line")
125+
.expect("malformed `xargo --version` output: error reading first line");
126+
let (name, version) = {
127+
let mut split = line.split(' ');
128+
(split.next().expect("malformed `xargo --version` output: empty"),
129+
split.next().expect("malformed `xargo --version` output: not at least two words"))
130+
};
131+
if name != "xargo" {
132+
panic!("malformed `xargo --version` output: application name is not `xargo`");
133+
}
134+
let mut version_pieces = version.split('.');
135+
let major = version_pieces.next()
136+
.expect("malformed `xargo --version` output: not a major version piece")
137+
.parse()
138+
.expect("malformed `xargo --version` output: major version is not an integer");
139+
let minor = version_pieces.next()
140+
.expect("malformed `xargo --version` output: not a minor version piece")
141+
.parse()
142+
.expect("malformed `xargo --version` output: minor version is not an integer");
143+
let patch = version_pieces.next()
144+
.expect("malformed `xargo --version` output: not a patch version piece")
145+
.parse()
146+
.expect("malformed `xargo --version` output: patch version is not an integer");
147+
if !version_pieces.next().is_none() {
148+
panic!("malformed `xargo --version` output: more than three pieces in version");
149+
}
150+
Some((major, minor, patch))
151+
}
152+
117153
fn ask(question: &str) {
118154
let mut buf = String::new();
119155
print!("{} [Y/n] ", question);
@@ -134,14 +170,14 @@ fn setup(ask_user: bool) {
134170
}
135171

136172
// First, we need xargo
137-
if Command::new("xargo").arg("--version").output().is_err()
138-
{
173+
let xargo = xargo_version();
174+
if xargo.map_or(true, |v| v < (0, 3, 13)) {
139175
if ask_user {
140-
ask("It seems you do not have xargo installed. I will run `cargo install xargo`. Proceed?");
176+
ask("It seems you do not have a recent enough xargo installed. I will run `cargo install xargo -f`. Proceed?");
141177
} else {
142-
println!("Installing xargo: `cargo install xargo`");
178+
println!("Installing xargo: `cargo install xargo -f`");
143179
}
144-
if !Command::new("cargo").args(&["install", "xargo"]).status().unwrap().success() {
180+
if !Command::new("cargo").args(&["install", "xargo", "-f"]).status().unwrap().success() {
145181
show_error(format!("Failed to install xargo"));
146182
}
147183
}
@@ -279,9 +315,8 @@ fn main() {
279315
(MiriCommand::Test, "lib") => {
280316
// For libraries we call `cargo rustc -- --test <rustc args>`
281317
// Notice now that `--test` is a rustc arg rather than a cargo arg. This tells
282-
// rustc to build a test harness which calls all #[test] functions. We don't
283-
// use the harness since we execute each #[test] function's MIR ourselves before
284-
// compilation even completes, but this option is necessary to build the library.
318+
// rustc to build a test harness which calls all #[test] functions.
319+
// We then execute that harness just like any other binary.
285320
if let Err(code) = process(
286321
vec!["--".to_string(), "--test".to_string()].into_iter().chain(
287322
args,
@@ -305,8 +340,8 @@ fn main() {
305340
_ => {}
306341
}
307342
}
308-
} else {
309-
// This arm is executed when cargo-miri runs `cargo rustc` with the `RUSTC` env var set to itself:
343+
} else if let Some("rustc") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) {
344+
// This arm is executed when cargo-miri runs `cargo rustc` with the `RUSTC_WRAPPER` env var set to itself:
310345
// Dependencies get dispatched to rustc, the final test/binary to miri.
311346

312347
let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
@@ -332,11 +367,11 @@ fn main() {
332367

333368
// this conditional check for the --sysroot flag is there so users can call `cargo-miri` directly
334369
// without having to pass --sysroot or anything
370+
let rustc_args = std::env::args().skip(2);
335371
let mut args: Vec<String> = if std::env::args().any(|s| s == "--sysroot") {
336-
std::env::args().skip(1).collect()
372+
rustc_args.collect()
337373
} else {
338-
std::env::args()
339-
.skip(1)
374+
rustc_args
340375
.chain(Some("--sysroot".to_owned()))
341376
.chain(Some(sys_root))
342377
.collect()
@@ -365,6 +400,8 @@ fn main() {
365400
Err(ref e) if miri_enabled => panic!("error during miri run: {:?}", e),
366401
Err(ref e) => panic!("error during rustc call: {:?}", e),
367402
}
403+
} else {
404+
show_error(format!("Must be called with either `miri` or `rustc` as first argument."))
368405
}
369406
}
370407

@@ -383,13 +420,11 @@ where
383420
args.push("--".to_owned());
384421
}
385422
args.push("--emit=dep-info,metadata".to_owned());
386-
args.push("--cfg".to_owned());
387-
args.push(r#"feature="cargo-miri""#.to_owned());
388423

389424
let path = std::env::current_exe().expect("current executable path invalid");
390425
let exit_status = Command::new("cargo")
391426
.args(&args)
392-
.env("RUSTC", path)
427+
.env("RUSTC_WRAPPER", path)
393428
.spawn()
394429
.expect("could not run cargo")
395430
.wait()

src/bin/miri.rs

Lines changed: 6 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ use rustc_metadata::cstore::CStore;
2323
use rustc_driver::{Compilation, CompilerCalls, RustcDefaultCalls};
2424
use rustc_driver::driver::{CompileState, CompileController};
2525
use rustc::session::config::{self, Input, ErrorOutputType};
26-
use rustc::hir::{self, itemlikevisit};
27-
use rustc::ty::TyCtxt;
2826
use rustc_codegen_utils::codegen_backend::CodegenBackend;
2927
use syntax::ast;
3028

@@ -115,43 +113,12 @@ fn after_analysis<'a, 'tcx>(
115113

116114
let tcx = state.tcx.unwrap();
117115

118-
if std::env::args().any(|arg| arg == "--test") {
119-
struct Visitor<'a, 'tcx: 'a> {
120-
tcx: TyCtxt<'a, 'tcx, 'tcx>,
121-
state: &'a CompileState<'a, 'tcx>,
122-
validate: bool,
123-
};
124-
impl<'a, 'tcx: 'a, 'hir> itemlikevisit::ItemLikeVisitor<'hir> for Visitor<'a, 'tcx> {
125-
fn visit_item(&mut self, i: &'hir hir::Item) {
126-
if let hir::ItemKind::Fn(.., body_id) = i.node {
127-
if i.attrs.iter().any(|attr| {
128-
attr.name() == "test"
129-
})
130-
{
131-
let did = self.tcx.hir().body_owner_def_id(body_id);
132-
println!(
133-
"running test: {}",
134-
self.tcx.def_path_debug_str(did),
135-
);
136-
miri::eval_main(self.tcx, did, self.validate);
137-
self.state.session.abort_if_errors();
138-
}
139-
}
140-
}
141-
fn visit_trait_item(&mut self, _trait_item: &'hir hir::TraitItem) {}
142-
fn visit_impl_item(&mut self, _impl_item: &'hir hir::ImplItem) {}
143-
}
144-
state.hir_crate.unwrap().visit_all_item_likes(
145-
&mut Visitor { tcx, state, validate }
146-
);
147-
} else if let Some((entry_node_id, _, _)) = *state.session.entry_fn.borrow() {
148-
let entry_def_id = tcx.hir().local_def_id(entry_node_id);
149-
miri::eval_main(tcx, entry_def_id, validate);
150-
151-
state.session.abort_if_errors();
152-
} else {
153-
println!("no main function found, assuming auxiliary build");
154-
}
116+
let (entry_node_id, _, _) = state.session.entry_fn.borrow().expect("no main function found!");
117+
let entry_def_id = tcx.hir().local_def_id(entry_node_id);
118+
119+
miri::eval_main(tcx, entry_def_id, validate);
120+
121+
state.session.abort_if_errors();
155122
}
156123

157124
fn init_early_loggers() {

0 commit comments

Comments
 (0)