diff --git a/.travis.yml b/.travis.yml index 5f4724a89e..d42ef2287a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,6 +36,9 @@ script: notifications: email: on_success: never +branches: + only: + - master env: global: - RUST_TEST_NOCAPTURE=1 diff --git a/miri/bin/miri.rs b/miri/bin/miri.rs index 337a723a40..9b8790379d 100644 --- a/miri/bin/miri.rs +++ b/miri/bin/miri.rs @@ -131,7 +131,7 @@ fn after_analysis<'a, 'tcx>(state: &mut CompileState<'a, 'tcx>) { ); } else if let Some((entry_node_id, _)) = *state.session.entry_fn.borrow() { let entry_def_id = tcx.hir.local_def_id(entry_node_id); - let start_wrapper = tcx.lang_items.start_fn().and_then(|start_fn| { + let start_wrapper = tcx.lang_items().start_fn().and_then(|start_fn| { if tcx.is_mir_available(start_fn) { Some(start_fn) } else { diff --git a/miri/fn_call.rs b/miri/fn_call.rs index a74a53fa75..d64b254e7e 100644 --- a/miri/fn_call.rs +++ b/miri/fn_call.rs @@ -96,11 +96,11 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator> dest_ty: Ty<'tcx>, dest_block: mir::BasicBlock, ) -> EvalResult<'tcx> { - let name = self.tcx.item_name(def_id); let attrs = self.tcx.get_attrs(def_id); - let link_name = attr::first_attr_value_str_by_name(&attrs, "link_name") - .unwrap_or(name) - .as_str(); + let link_name = match attr::first_attr_value_str_by_name(&attrs, "link_name") { + Some(name) => name.as_str(), + None => self.tcx.item_name(def_id), + }; match &link_name[..] { "malloc" => { @@ -477,28 +477,26 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator> /// Get an instance for a path. fn resolve_path(&self, path: &[&str]) -> EvalResult<'tcx, ty::Instance<'tcx>> { - let cstore = &self.tcx.sess.cstore; - - let crates = cstore.crates(); - crates + self.tcx + .crates() .iter() - .find(|&&krate| cstore.crate_name(krate) == path[0]) + .find(|&&krate| self.tcx.original_crate_name(krate) == path[0]) .and_then(|krate| { let krate = DefId { krate: *krate, index: CRATE_DEF_INDEX, }; - let mut items = cstore.item_children(krate, self.tcx.sess); + let mut items = self.tcx.item_children(krate); let mut path_it = path.iter().skip(1).peekable(); while let Some(segment) = path_it.next() { - for item in &mem::replace(&mut items, vec![]) { + for item in mem::replace(&mut items, Default::default()).iter() { if item.ident.name == *segment { if path_it.peek().is_none() { return Some(ty::Instance::mono(self.tcx, item.def.def_id())); } - items = cstore.item_children(item.def.def_id(), self.tcx.sess); + items = self.tcx.item_children(item.def.def_id()); break; } } diff --git a/miri/intrinsic.rs b/miri/intrinsic.rs index 693a478c2d..bcff3b4aa9 100644 --- a/miri/intrinsic.rs +++ b/miri/intrinsic.rs @@ -32,7 +32,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator> ) -> EvalResult<'tcx> { let substs = instance.substs; - let intrinsic_name = &self.tcx.item_name(instance.def_id()).as_str()[..]; + let intrinsic_name = &self.tcx.item_name(instance.def_id())[..]; match intrinsic_name { "align_offset" => { // FIXME: return a real value in case the target allocation has an diff --git a/rustc_tests/src/main.rs b/rustc_tests/src/main.rs index ea699833f6..d1f2f07aaa 100644 --- a/rustc_tests/src/main.rs +++ b/rustc_tests/src/main.rs @@ -100,7 +100,7 @@ fn after_analysis<'a, 'tcx>(state: &mut CompileState<'a, 'tcx>) { state.hir_crate.unwrap().visit_all_item_likes(&mut Visitor(limits, tcx, state)); } else if let Some((entry_node_id, _)) = *state.session.entry_fn.borrow() { let entry_def_id = tcx.hir.local_def_id(entry_node_id); - let start_wrapper = tcx.lang_items.start_fn().and_then(|start_fn| + let start_wrapper = tcx.lang_items().start_fn().and_then(|start_fn| if tcx.is_mir_available(start_fn) { Some(start_fn) } else { None }); miri::eval_main(tcx, entry_def_id, start_wrapper, limits); diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index bc227fcc39..bd7a42cca1 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -508,8 +508,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { stmt: 0, }); - let cur_frame = self.cur_frame(); - self.memory.set_cur_frame(cur_frame); + self.memory.cur_frame = self.cur_frame(); if self.stack.len() > self.stack_limit { err!(StackFrameLimitReached) @@ -520,14 +519,13 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { pub(super) fn pop_stack_frame(&mut self) -> EvalResult<'tcx> { ::log_settings::settings().indentation -= 1; - self.memory.locks_lifetime_ended(None); + self.end_region(None)?; let frame = self.stack.pop().expect( "tried to pop a stack frame, but there were none", ); if !self.stack.is_empty() { - // TODO: IS this the correct time to start considering these accesses as originating from the returned-to stack frame? - let cur_frame = self.cur_frame(); - self.memory.set_cur_frame(cur_frame); + // TODO: Is this the correct time to start considering these accesses as originating from the returned-to stack frame? + self.memory.cur_frame = self.cur_frame(); } match frame.return_to_block { StackPopCleanup::MarkStatic(mutable) => { @@ -2267,7 +2265,7 @@ fn fn_once_adapter_instance<'a, 'tcx>( substs: ty::ClosureSubsts<'tcx>, ) -> ty::Instance<'tcx> { debug!("fn_once_adapter_shim({:?}, {:?})", closure_did, substs); - let fn_once = tcx.lang_items.fn_once_trait().unwrap(); + let fn_once = tcx.lang_items().fn_once_trait().unwrap(); let call_once = tcx.associated_items(fn_once) .find(|it| it.kind == ty::AssociatedKind::Method) .unwrap() @@ -2346,7 +2344,7 @@ pub fn resolve<'a, 'tcx>( ty::InstanceDef::Intrinsic(def_id) } _ => { - if Some(def_id) == tcx.lang_items.drop_in_place_fn() { + if Some(def_id) == tcx.lang_items().drop_in_place_fn() { let ty = substs.type_at(0); if needs_drop_glue(tcx, ty) { debug!(" => nontrivial drop glue"); @@ -2440,7 +2438,7 @@ fn resolve_associated_item<'a, 'tcx>( } } ::rustc::traits::VtableClosure(closure_data) => { - let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_id).unwrap(); + let trait_closure_kind = tcx.lang_items().fn_trait_kind(trait_id).unwrap(); resolve_closure( tcx, closure_data.closure_def_id, @@ -2461,7 +2459,7 @@ fn resolve_associated_item<'a, 'tcx>( substs: rcvr_substs, } } - ::rustc::traits::VtableBuiltin(..) if Some(trait_id) == tcx.lang_items.clone_trait() => { + ::rustc::traits::VtableBuiltin(..) if Some(trait_id) == tcx.lang_items().clone_trait() => { ty::Instance { def: ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty()), substs: rcvr_substs diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 7454f1c908..9a99f50cdf 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -268,7 +268,7 @@ pub struct Memory<'a, 'tcx, M: Machine<'tcx>> { writes_are_aligned: Cell, /// The current stack frame. Used to check accesses against locks. - cur_frame: usize, + pub(super) cur_frame: usize, } impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { @@ -530,10 +530,6 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { } Ok(()) } - - pub(crate) fn set_cur_frame(&mut self, cur_frame: usize) { - self.cur_frame = cur_frame; - } } /// Locking diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index e7d5a83532..3dc74368fe 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -164,7 +164,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { } } EndRegion(ce) => { - self.end_region(ce)?; + self.end_region(Some(ce))?; } // Defined to do nothing. These are added by optimization passes, to avoid changing the diff --git a/src/librustc_mir/interpret/validation.rs b/src/librustc_mir/interpret/validation.rs index 7dfc781520..9a16a4ec15 100644 --- a/src/librustc_mir/interpret/validation.rs +++ b/src/librustc_mir/interpret/validation.rs @@ -45,6 +45,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { if self.tcx.sess.opts.debugging_opts.mir_emit_validate == 0 { return Ok(()); } + debug_assert!(self.memory.cur_frame == self.cur_frame()); // HACK: Determine if this method is whitelisted and hence we do not perform any validation. // We currently insta-UB on anything passing around uninitialized memory, so we have to whitelist @@ -55,17 +56,17 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { use regex::Regex; lazy_static! { static ref RE: Regex = Regex::new("^(\ - std::mem::uninitialized::|\ - std::mem::forget::|\ + (std|alloc::heap::__core)::mem::uninitialized::|\ + (std|alloc::heap::__core)::mem::forget::|\ <(std|alloc)::heap::Heap as (std::heap|alloc::allocator)::Alloc>::|\ - ><.*>::new$|\ - as std::ops::DerefMut><.*>::deref_mut$|\ - std::ptr::read::|\ + <(std|alloc::heap::__core)::mem::ManuallyDrop><.*>::new$|\ + <(std|alloc::heap::__core)::mem::ManuallyDrop as std::ops::DerefMut><.*>::deref_mut$|\ + (std|alloc::heap::__core)::ptr::read::|\ \ ><.*>::inner$|\ ><.*>::drop_slow$|\ (std::heap|alloc::allocator)::Layout::for_value::|\ - std::mem::(size|align)_of_val::\ + (std|alloc::heap::__core)::mem::(size|align)_of_val::\ )").unwrap(); } // Now test @@ -93,7 +94,8 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { if query.mutbl == MutMutable { let lft = DynamicLifetime { frame: self.cur_frame(), - region: Some(scope), + region: Some(scope), // Notably, we only ever suspend things for given regions. + // Suspending for the entire function does not make any sense. }; trace!("Suspending {:?} until {:?}", query, scope); self.suspended.entry(lft).or_insert_with(Vec::new).push( @@ -106,17 +108,30 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { self.validate(query, mode) } - pub(crate) fn end_region(&mut self, scope: region::Scope) -> EvalResult<'tcx> { - self.memory.locks_lifetime_ended(Some(scope)); - // Recover suspended lvals - let lft = DynamicLifetime { - frame: self.cur_frame(), - region: Some(scope), - }; - if let Some(queries) = self.suspended.remove(&lft) { - for query in queries { - trace!("Recovering {:?} from suspension", query); - self.validate(query, ValidationMode::Recover(scope))?; + /// Release locks and executes suspensions of the given region (or the entire fn, in case of None). + pub(crate) fn end_region(&mut self, scope: Option) -> EvalResult<'tcx> { + debug_assert!(self.memory.cur_frame == self.cur_frame()); + self.memory.locks_lifetime_ended(scope); + match scope { + Some(scope) => { + // Recover suspended lvals + let lft = DynamicLifetime { + frame: self.cur_frame(), + region: Some(scope), + }; + if let Some(queries) = self.suspended.remove(&lft) { + for query in queries { + trace!("Recovering {:?} from suspension", query); + self.validate(query, ValidationMode::Recover(scope))?; + } + } + } + None => { + // Clean suspension table of current frame + let cur_frame = self.cur_frame(); + self.suspended.retain(|lft, _| { + lft.frame != cur_frame // keep only what is in the other (lower) frames + }); } } Ok(()) @@ -543,7 +558,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> { Ok(()) } TyAdt(adt, subst) => { - if Some(adt.did) == self.tcx.lang_items.unsafe_cell_type() && + if Some(adt.did) == self.tcx.lang_items().unsafe_cell_type() && query.mutbl == MutImmutable { // No locks for shared unsafe cells. Also no other validation, the only field is private anyway. diff --git a/tests/compile-fail/deallocate-bad-alignment.rs b/tests/compile-fail/deallocate-bad-alignment.rs index a0bcffa47d..c1ae7477c8 100644 --- a/tests/compile-fail/deallocate-bad-alignment.rs +++ b/tests/compile-fail/deallocate-bad-alignment.rs @@ -7,7 +7,6 @@ use alloc::allocator::*; // error-pattern: tried to deallocate or reallocate using incorrect alignment or size -use alloc::heap::*; fn main() { unsafe { let x = Heap.alloc(Layout::from_size_align_unchecked(1, 1)).unwrap(); diff --git a/tests/compile-fail/deallocate-bad-size.rs b/tests/compile-fail/deallocate-bad-size.rs index d8c4493043..5577f10736 100644 --- a/tests/compile-fail/deallocate-bad-size.rs +++ b/tests/compile-fail/deallocate-bad-size.rs @@ -7,7 +7,6 @@ use alloc::allocator::*; // error-pattern: tried to deallocate or reallocate using incorrect alignment or size -use alloc::heap::*; fn main() { unsafe { let x = Heap.alloc(Layout::from_size_align_unchecked(1, 1)).unwrap(); diff --git a/tests/compile-fail/deallocate-twice.rs b/tests/compile-fail/deallocate-twice.rs index fd3cccfd53..e11df0eb41 100644 --- a/tests/compile-fail/deallocate-twice.rs +++ b/tests/compile-fail/deallocate-twice.rs @@ -7,7 +7,6 @@ use alloc::allocator::*; // error-pattern: tried to deallocate dangling pointer -use alloc::heap::*; fn main() { unsafe { let x = Heap.alloc(Layout::from_size_align_unchecked(1, 1)).unwrap(); diff --git a/tests/compile-fail/reallocate-bad-alignment-2.rs b/tests/compile-fail/reallocate-bad-alignment-2.rs index 41da885a2c..cd6214440f 100644 --- a/tests/compile-fail/reallocate-bad-alignment-2.rs +++ b/tests/compile-fail/reallocate-bad-alignment-2.rs @@ -7,7 +7,6 @@ use alloc::allocator::*; // error-pattern: tried to deallocate or reallocate using incorrect alignment or size -use alloc::heap::*; fn main() { unsafe { let x = Heap.alloc(Layout::from_size_align_unchecked(1, 1)).unwrap(); diff --git a/tests/compile-fail/reallocate-bad-alignment.rs b/tests/compile-fail/reallocate-bad-alignment.rs index be4bc5589c..da5fe1d819 100644 --- a/tests/compile-fail/reallocate-bad-alignment.rs +++ b/tests/compile-fail/reallocate-bad-alignment.rs @@ -7,7 +7,6 @@ use alloc::allocator::*; // error-pattern: tried to deallocate or reallocate using incorrect alignment or size -use alloc::heap::*; fn main() { unsafe { let x = Heap.alloc(Layout::from_size_align_unchecked(1, 2)).unwrap(); diff --git a/tests/compile-fail/reallocate-bad-size.rs b/tests/compile-fail/reallocate-bad-size.rs index 2e5a641838..953178742c 100644 --- a/tests/compile-fail/reallocate-bad-size.rs +++ b/tests/compile-fail/reallocate-bad-size.rs @@ -7,7 +7,6 @@ use alloc::allocator::*; // error-pattern: tried to deallocate or reallocate using incorrect alignment or size -use alloc::heap::*; fn main() { unsafe { let x = Heap.alloc(Layout::from_size_align_unchecked(1, 1)).unwrap(); diff --git a/tests/compile-fail/reallocate-dangling.rs b/tests/compile-fail/reallocate-dangling.rs index 54636b5d20..6225879a5a 100644 --- a/tests/compile-fail/reallocate-dangling.rs +++ b/tests/compile-fail/reallocate-dangling.rs @@ -7,7 +7,6 @@ use alloc::allocator::*; // error-pattern: dangling pointer was dereferenced -use alloc::heap::*; fn main() { unsafe { let x = Heap.alloc(Layout::from_size_align_unchecked(1, 1)).unwrap(); diff --git a/tests/run-pass-fullmir/u128.rs b/tests/run-pass-fullmir/u128.rs index a1fb96ef4a..a05308acbe 100644 --- a/tests/run-pass-fullmir/u128.rs +++ b/tests/run-pass-fullmir/u128.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Zmir-emit-validate=0 - #![feature(i128_type)] fn b(t: T) -> T { t } diff --git a/tests/run-pass-fullmir/unsized-tuple-impls.rs b/tests/run-pass-fullmir/unsized-tuple-impls.rs index acaedebbf9..ccb6883e87 100644 --- a/tests/run-pass-fullmir/unsized-tuple-impls.rs +++ b/tests/run-pass-fullmir/unsized-tuple-impls.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Zmir-emit-validate=0 - #![feature(unsized_tuple_coercion)] use std::mem; diff --git a/tests/run-pass/dst-field-align.rs b/tests/run-pass/dst-field-align.rs index fd44e04ee2..5631b65ed9 100644 --- a/tests/run-pass/dst-field-align.rs +++ b/tests/run-pass/dst-field-align.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// FIXME: Broken by #296 -// compile-flags: -Zmir-emit-validate=0 - #![allow(dead_code)] struct Foo { diff --git a/tests/run-pass/mir_coercions.rs b/tests/run-pass/mir_coercions.rs index 194bc9be0a..36155297e3 100644 --- a/tests/run-pass/mir_coercions.rs +++ b/tests/run-pass/mir_coercions.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// FIXME: investigate again once #296 is fixed -// compile-flags: -Zmir-emit-validate=0 - #![feature(coerce_unsized, unsize)] use std::ops::CoerceUnsized; diff --git a/tests/run-pass/non_capture_closure_to_fn_ptr.rs b/tests/run-pass/non_capture_closure_to_fn_ptr.rs index 0578ecbbb1..c9daff9c9f 100644 --- a/tests/run-pass/non_capture_closure_to_fn_ptr.rs +++ b/tests/run-pass/non_capture_closure_to_fn_ptr.rs @@ -1,6 +1,3 @@ -// FIXME: investigate again once #296 is fixed -// compile-flags: -Zmir-emit-validate=0 - // allow(const_err) to work around a bug in warnings #[allow(const_err)] static FOO: fn() = || { assert_ne!(42, 43) }; diff --git a/tests/run-pass/pointers.rs b/tests/run-pass/pointers.rs index 7d34d564ea..f3ae3ab913 100644 --- a/tests/run-pass/pointers.rs +++ b/tests/run-pass/pointers.rs @@ -1,5 +1,3 @@ -// compile-flags: -Zmir-emit-validate=0 - fn one_line_ref() -> i16 { *&1 } diff --git a/tests/run-pass/subslice_array.rs b/tests/run-pass/subslice_array.rs index ae4a9eb5cf..468cc9f094 100644 --- a/tests/run-pass/subslice_array.rs +++ b/tests/run-pass/subslice_array.rs @@ -1,6 +1,3 @@ -// FIXME: investigate again once #296 is fixed -// compile-flags: -Zmir-emit-validate=0 - #![feature(advanced_slice_patterns)] #![feature(slice_patterns)] diff --git a/tests/run-pass/tuple_like_enum_variant_constructor_pointer_opt.rs b/tests/run-pass/tuple_like_enum_variant_constructor_pointer_opt.rs index 426e1360a3..fb57d4f4c1 100644 --- a/tests/run-pass/tuple_like_enum_variant_constructor_pointer_opt.rs +++ b/tests/run-pass/tuple_like_enum_variant_constructor_pointer_opt.rs @@ -1,6 +1,3 @@ -// FIXME: investigate again once #296 is fixed -// compile-flags: -Zmir-emit-validate=0 - fn main() { let x = 5; assert_eq!(Some(&x).map(Some), Some(Some(&x)));