commit
965160d4d7
18
README.md
18
README.md
@ -55,7 +55,11 @@ Install Miri via `rustup`:
|
||||
rustup component add miri
|
||||
```
|
||||
|
||||
If `rustup` says the `miri` component is unavailable, that's because not all nightly releases come with all tools. Check out [this website](https://rust-lang.github.io/rustup-components-history) to determine a nightly version that comes with Miri and install that, e.g. using `rustup install nightly-2019-03-28`.
|
||||
If `rustup` says the `miri` component is unavailable, that's because not all
|
||||
nightly releases come with all tools. Check out
|
||||
[this website](https://rust-lang.github.io/rustup-components-history) to
|
||||
determine a nightly version that comes with Miri and install that, e.g. using
|
||||
`rustup install nightly-2019-03-28`.
|
||||
|
||||
Now you can run your project in Miri:
|
||||
|
||||
@ -131,7 +135,17 @@ able to just `cargo build` Miri.
|
||||
In case this fails, your nightly might be incompatible with Miri master. The
|
||||
`rust-version` file contains the commit hash of rustc that Miri is currently
|
||||
tested against; you can use that to find a nightly that works or you might have
|
||||
to wait for the next nightly to get released.
|
||||
to wait for the next nightly to get released. You can also use
|
||||
[`rustup-toolchain-install-master`](https://github.com/kennytm/rustup-toolchain-install-master)
|
||||
to install that exact version of rustc as a toolchain:
|
||||
```
|
||||
rustup-toolchain-install-master $(cat rust-version) -c rust-src
|
||||
```
|
||||
|
||||
Another common problem is outdated dependencies: Miri does not come with a
|
||||
lockfile (it cannot, due to how it gets embedded into the rustc build). So you
|
||||
have to run `cargo update` every now and then yourself to make sure you are
|
||||
using the latest versions of everything (which is what gets tested on CI).
|
||||
|
||||
### Testing the Miri driver
|
||||
[testing-miri]: #testing-the-miri-driver
|
||||
|
@ -1 +1 @@
|
||||
8e948df707ea8a3c88c65bf2ffdcb2f1cf5491be
|
||||
d8f50ab0ea6c529c24e575279acc72093caeb679
|
||||
|
@ -43,8 +43,8 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
|
||||
compiler.session().abort_if_errors();
|
||||
compiler.global_ctxt().unwrap().peek_mut().enter(|tcx| {
|
||||
if std::env::args().any(|arg| arg == "--test") {
|
||||
struct Visitor<'a, 'tcx: 'a>(TyCtxt<'a, 'tcx, 'tcx>);
|
||||
impl<'a, 'tcx: 'a, 'hir> itemlikevisit::ItemLikeVisitor<'hir> for Visitor<'a, 'tcx> {
|
||||
struct Visitor<'tcx>(TyCtxt<'tcx, 'tcx>);
|
||||
impl<'tcx, 'hir> itemlikevisit::ItemLikeVisitor<'hir> for Visitor<'tcx> {
|
||||
fn visit_item(&mut self, i: &'hir hir::Item) {
|
||||
if let hir::ItemKind::Fn(.., body_id) = i.node {
|
||||
if i.attrs.iter().any(|attr| attr.check_name(syntax::symbol::sym::test)) {
|
||||
|
@ -9,8 +9,8 @@ use rand::RngCore;
|
||||
|
||||
use crate::*;
|
||||
|
||||
impl<'a, 'mir, 'tcx> EvalContextExt<'a, 'mir, 'tcx> for crate::MiriEvalContext<'a, 'mir, 'tcx> {}
|
||||
pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'a, 'mir, 'tcx> {
|
||||
impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
|
||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
|
||||
fn find_fn(
|
||||
&mut self,
|
||||
instance: ty::Instance<'tcx>,
|
||||
@ -930,8 +930,8 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
|
||||
}
|
||||
}
|
||||
|
||||
fn gen_random<'a, 'mir, 'tcx>(
|
||||
this: &mut MiriEvalContext<'a, 'mir, 'tcx>,
|
||||
fn gen_random<'mir, 'tcx>(
|
||||
this: &mut MiriEvalContext<'mir, 'tcx>,
|
||||
len: usize,
|
||||
dest: Scalar<Tag>,
|
||||
) -> InterpResult<'tcx> {
|
||||
|
@ -5,9 +5,9 @@ use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
|
||||
|
||||
use crate::*;
|
||||
|
||||
impl<'a, 'mir, 'tcx> EvalContextExt<'a, 'mir, 'tcx> for crate::MiriEvalContext<'a, 'mir, 'tcx> {}
|
||||
impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
|
||||
|
||||
pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'a, 'mir, 'tcx> {
|
||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
|
||||
/// Gets an instance for a path.
|
||||
fn resolve_path(&self, path: &[&str]) -> InterpResult<'tcx, ty::Instance<'tcx>> {
|
||||
let this = self.eval_context_ref();
|
||||
@ -119,24 +119,24 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
|
||||
|
||||
/// Visiting the memory covered by a `MemPlace`, being aware of
|
||||
/// whether we are inside an `UnsafeCell` or not.
|
||||
struct UnsafeCellVisitor<'ecx, 'a, 'mir, 'tcx, F>
|
||||
struct UnsafeCellVisitor<'ecx, 'mir, 'tcx, F>
|
||||
where F: FnMut(MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
|
||||
{
|
||||
ecx: &'ecx MiriEvalContext<'a, 'mir, 'tcx>,
|
||||
ecx: &'ecx MiriEvalContext<'mir, 'tcx>,
|
||||
unsafe_cell_action: F,
|
||||
}
|
||||
|
||||
impl<'ecx, 'a, 'mir, 'tcx, F>
|
||||
ValueVisitor<'a, 'mir, 'tcx, Evaluator<'tcx>>
|
||||
impl<'ecx, 'mir, 'tcx, F>
|
||||
ValueVisitor<'mir, 'tcx, Evaluator<'tcx>>
|
||||
for
|
||||
UnsafeCellVisitor<'ecx, 'a, 'mir, 'tcx, F>
|
||||
UnsafeCellVisitor<'ecx, 'mir, 'tcx, F>
|
||||
where
|
||||
F: FnMut(MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
|
||||
{
|
||||
type V = MPlaceTy<'tcx, Tag>;
|
||||
|
||||
#[inline(always)]
|
||||
fn ecx(&self) -> &MiriEvalContext<'a, 'mir, 'tcx> {
|
||||
fn ecx(&self) -> &MiriEvalContext<'mir, 'tcx> {
|
||||
&self.ecx
|
||||
}
|
||||
|
||||
|
@ -9,8 +9,8 @@ use crate::{
|
||||
OperatorEvalContextExt
|
||||
};
|
||||
|
||||
impl<'a, 'mir, 'tcx> EvalContextExt<'a, 'mir, 'tcx> for crate::MiriEvalContext<'a, 'mir, 'tcx> {}
|
||||
pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, 'mir, 'tcx> {
|
||||
impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
|
||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
|
||||
fn call_intrinsic(
|
||||
&mut self,
|
||||
instance: ty::Instance<'tcx>,
|
||||
|
46
src/lib.rs
46
src/lib.rs
@ -71,11 +71,11 @@ pub struct MiriConfig {
|
||||
}
|
||||
|
||||
// Used by priroda.
|
||||
pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
pub fn create_ecx<'mir, 'tcx: 'mir>(
|
||||
tcx: TyCtxt<'tcx, 'tcx>,
|
||||
main_id: DefId,
|
||||
config: MiriConfig,
|
||||
) -> InterpResult<'tcx, InterpretCx<'a, 'mir, 'tcx, Evaluator<'tcx>>> {
|
||||
) -> InterpResult<'tcx, InterpretCx<'mir, 'tcx, Evaluator<'tcx>>> {
|
||||
let mut ecx = InterpretCx::new(
|
||||
tcx.at(syntax::source_map::DUMMY_SP),
|
||||
ty::ParamEnv::reveal_all(),
|
||||
@ -211,8 +211,8 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
|
||||
Ok(ecx)
|
||||
}
|
||||
|
||||
pub fn eval_main<'a, 'tcx: 'a>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
pub fn eval_main<'tcx>(
|
||||
tcx: TyCtxt<'tcx, 'tcx>,
|
||||
main_id: DefId,
|
||||
config: MiriConfig,
|
||||
) {
|
||||
@ -364,25 +364,25 @@ impl<'tcx> Evaluator<'tcx> {
|
||||
|
||||
// FIXME: rustc issue <https://github.com/rust-lang/rust/issues/47131>.
|
||||
#[allow(dead_code)]
|
||||
type MiriEvalContext<'a, 'mir, 'tcx> = InterpretCx<'a, 'mir, 'tcx, Evaluator<'tcx>>;
|
||||
type MiriEvalContext<'mir, 'tcx> = InterpretCx<'mir, 'tcx, Evaluator<'tcx>>;
|
||||
|
||||
// A little trait that's useful to be inherited by extension traits.
|
||||
pub trait MiriEvalContextExt<'a, 'mir, 'tcx> {
|
||||
fn eval_context_ref(&self) -> &MiriEvalContext<'a, 'mir, 'tcx>;
|
||||
fn eval_context_mut(&mut self) -> &mut MiriEvalContext<'a, 'mir, 'tcx>;
|
||||
pub trait MiriEvalContextExt<'mir, 'tcx> {
|
||||
fn eval_context_ref(&self) -> &MiriEvalContext<'mir, 'tcx>;
|
||||
fn eval_context_mut(&mut self) -> &mut MiriEvalContext<'mir, 'tcx>;
|
||||
}
|
||||
impl<'a, 'mir, 'tcx> MiriEvalContextExt<'a, 'mir, 'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
|
||||
impl<'mir, 'tcx> MiriEvalContextExt<'mir, 'tcx> for MiriEvalContext<'mir, 'tcx> {
|
||||
#[inline(always)]
|
||||
fn eval_context_ref(&self) -> &MiriEvalContext<'a, 'mir, 'tcx> {
|
||||
fn eval_context_ref(&self) -> &MiriEvalContext<'mir, 'tcx> {
|
||||
self
|
||||
}
|
||||
#[inline(always)]
|
||||
fn eval_context_mut(&mut self) -> &mut MiriEvalContext<'a, 'mir, 'tcx> {
|
||||
fn eval_context_mut(&mut self) -> &mut MiriEvalContext<'mir, 'tcx> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
|
||||
impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
|
||||
type MemoryKinds = MiriMemoryKind;
|
||||
|
||||
type FrameExtra = stacked_borrows::CallId;
|
||||
@ -395,14 +395,14 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
|
||||
const STATIC_KIND: Option<MiriMemoryKind> = Some(MiriMemoryKind::Static);
|
||||
|
||||
#[inline(always)]
|
||||
fn enforce_validity(ecx: &InterpretCx<'a, 'mir, 'tcx, Self>) -> bool {
|
||||
fn enforce_validity(ecx: &InterpretCx<'mir, 'tcx, Self>) -> bool {
|
||||
ecx.machine.validate
|
||||
}
|
||||
|
||||
/// Returns `Ok()` when the function was handled; fail otherwise.
|
||||
#[inline(always)]
|
||||
fn find_fn(
|
||||
ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
|
||||
ecx: &mut InterpretCx<'mir, 'tcx, Self>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: Option<PlaceTy<'tcx, Tag>>,
|
||||
@ -413,7 +413,7 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
|
||||
|
||||
#[inline(always)]
|
||||
fn call_intrinsic(
|
||||
ecx: &mut rustc_mir::interpret::InterpretCx<'a, 'mir, 'tcx, Self>,
|
||||
ecx: &mut rustc_mir::interpret::InterpretCx<'mir, 'tcx, Self>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: PlaceTy<'tcx, Tag>,
|
||||
@ -423,7 +423,7 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
|
||||
|
||||
#[inline(always)]
|
||||
fn ptr_op(
|
||||
ecx: &rustc_mir::interpret::InterpretCx<'a, 'mir, 'tcx, Self>,
|
||||
ecx: &rustc_mir::interpret::InterpretCx<'mir, 'tcx, Self>,
|
||||
bin_op: mir::BinOp,
|
||||
left: ImmTy<'tcx, Tag>,
|
||||
right: ImmTy<'tcx, Tag>,
|
||||
@ -432,7 +432,7 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
|
||||
}
|
||||
|
||||
fn box_alloc(
|
||||
ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
|
||||
ecx: &mut InterpretCx<'mir, 'tcx, Self>,
|
||||
dest: PlaceTy<'tcx, Tag>,
|
||||
) -> InterpResult<'tcx> {
|
||||
trace!("box_alloc for {:?}", dest.layout.ty);
|
||||
@ -475,7 +475,7 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
|
||||
|
||||
fn find_foreign_static(
|
||||
def_id: DefId,
|
||||
tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
|
||||
tcx: TyCtxtAt<'tcx, 'tcx>,
|
||||
) -> InterpResult<'tcx, Cow<'tcx, Allocation>> {
|
||||
let attrs = tcx.get_attrs(def_id);
|
||||
let link_name = match attr::first_attr_value_str_by_name(&attrs, sym::link_name) {
|
||||
@ -498,7 +498,7 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn before_terminator(_ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>) -> InterpResult<'tcx>
|
||||
fn before_terminator(_ecx: &mut InterpretCx<'mir, 'tcx, Self>) -> InterpResult<'tcx>
|
||||
{
|
||||
// We are not interested in detecting loops.
|
||||
Ok(())
|
||||
@ -550,7 +550,7 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
|
||||
|
||||
#[inline(always)]
|
||||
fn retag(
|
||||
ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
|
||||
ecx: &mut InterpretCx<'mir, 'tcx, Self>,
|
||||
kind: mir::RetagKind,
|
||||
place: PlaceTy<'tcx, Tag>,
|
||||
) -> InterpResult<'tcx> {
|
||||
@ -568,14 +568,14 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
|
||||
|
||||
#[inline(always)]
|
||||
fn stack_push(
|
||||
ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
|
||||
ecx: &mut InterpretCx<'mir, 'tcx, Self>,
|
||||
) -> InterpResult<'tcx, stacked_borrows::CallId> {
|
||||
Ok(ecx.memory().extra.borrow_mut().new_call())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn stack_pop(
|
||||
ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
|
||||
ecx: &mut InterpretCx<'mir, 'tcx, Self>,
|
||||
extra: stacked_borrows::CallId,
|
||||
) -> InterpResult<'tcx> {
|
||||
Ok(ecx.memory().extra.borrow_mut().end_call(extra))
|
||||
|
@ -33,7 +33,7 @@ pub trait EvalContextExt<'tcx> {
|
||||
) -> InterpResult<'tcx, Scalar<Tag>>;
|
||||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, 'tcx> {
|
||||
impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'mir, 'tcx> {
|
||||
fn ptr_op(
|
||||
&self,
|
||||
bin_op: mir::BinOp,
|
||||
|
@ -519,8 +519,8 @@ impl AllocationExtra<Tag> for Stacks {
|
||||
|
||||
/// Retagging/reborrowing. There is some policy in here, such as which permissions
|
||||
/// to grant for which references, and when to add protectors.
|
||||
impl<'a, 'mir, 'tcx> EvalContextPrivExt<'a, 'mir, 'tcx> for crate::MiriEvalContext<'a, 'mir, 'tcx> {}
|
||||
trait EvalContextPrivExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, 'mir, 'tcx> {
|
||||
impl<'mir, 'tcx> EvalContextPrivExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
|
||||
trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
|
||||
fn reborrow(
|
||||
&mut self,
|
||||
place: MPlaceTy<'tcx, Tag>,
|
||||
@ -599,8 +599,8 @@ trait EvalContextPrivExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a,
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx> EvalContextExt<'a, 'mir, 'tcx> for crate::MiriEvalContext<'a, 'mir, 'tcx> {}
|
||||
pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, 'mir, 'tcx> {
|
||||
impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
|
||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
|
||||
fn retag(
|
||||
&mut self,
|
||||
kind: RetagKind,
|
||||
@ -643,19 +643,19 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a,
|
||||
visitor.visit_value(place)?;
|
||||
|
||||
// The actual visitor.
|
||||
struct RetagVisitor<'ecx, 'a, 'mir, 'tcx> {
|
||||
ecx: &'ecx mut MiriEvalContext<'a, 'mir, 'tcx>,
|
||||
struct RetagVisitor<'ecx, 'mir, 'tcx> {
|
||||
ecx: &'ecx mut MiriEvalContext<'mir, 'tcx>,
|
||||
kind: RetagKind,
|
||||
}
|
||||
impl<'ecx, 'a, 'mir, 'tcx>
|
||||
MutValueVisitor<'a, 'mir, 'tcx, Evaluator<'tcx>>
|
||||
impl<'ecx, 'mir, 'tcx>
|
||||
MutValueVisitor<'mir, 'tcx, Evaluator<'tcx>>
|
||||
for
|
||||
RetagVisitor<'ecx, 'a, 'mir, 'tcx>
|
||||
RetagVisitor<'ecx, 'mir, 'tcx>
|
||||
{
|
||||
type V = MPlaceTy<'tcx, Tag>;
|
||||
|
||||
#[inline(always)]
|
||||
fn ecx(&mut self) -> &mut MiriEvalContext<'a, 'mir, 'tcx> {
|
||||
fn ecx(&mut self) -> &mut MiriEvalContext<'mir, 'tcx> {
|
||||
&mut self.ecx
|
||||
}
|
||||
|
||||
|
@ -129,8 +129,8 @@ impl<'tcx> TlsData<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx> EvalContextExt<'a, 'mir, 'tcx> for crate::MiriEvalContext<'a, 'mir, 'tcx> {}
|
||||
pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, 'mir, 'tcx> {
|
||||
impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
|
||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
|
||||
fn run_tls_dtors(&mut self) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let mut dtor = this.machine.tls.fetch_tls_dtor(None, &*this.tcx);
|
||||
|
Loading…
x
Reference in New Issue
Block a user