Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 8 pull requests #61044

Merged
merged 17 commits into from
May 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 22 additions & 24 deletions src/libcore/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,26 @@
//! mutability:
//!
//! ```
//! use std::cell::{RefCell, RefMut};
//! use std::collections::HashMap;
//! use std::cell::RefCell;
//! use std::rc::Rc;
//!
//! fn main() {
//! let shared_map: Rc<RefCell<_>> = Rc::new(RefCell::new(HashMap::new()));
//! shared_map.borrow_mut().insert("africa", 92388);
//! shared_map.borrow_mut().insert("kyoto", 11837);
//! shared_map.borrow_mut().insert("piccadilly", 11826);
//! shared_map.borrow_mut().insert("marbles", 38);
//! // Create a new block to limit the scope of the dynamic borrow
//! {
//! let mut map: RefMut<_> = shared_map.borrow_mut();
//! map.insert("africa", 92388);
//! map.insert("kyoto", 11837);
//! map.insert("piccadilly", 11826);
//! map.insert("marbles", 38);
//! }
//!
//! // Note that if we had not let the previous borrow of the cache fall out
//! // of scope then the subsequent borrow would cause a dynamic thread panic.
//! // This is the major hazard of using `RefCell`.
//! let total: i32 = shared_map.borrow().values().sum();
//! println!("{}", total);
//! }
//! ```
//!
Expand All @@ -102,27 +112,15 @@
//!
//! impl Graph {
//! fn minimum_spanning_tree(&self) -> Vec<(i32, i32)> {
//! // Create a new scope to contain the lifetime of the
//! // dynamic borrow
//! {
//! // Take a reference to the inside of cache cell
//! let mut cache = self.span_tree_cache.borrow_mut();
//! if cache.is_some() {
//! return cache.as_ref().unwrap().clone();
//! }
//!
//! let span_tree = self.calc_span_tree();
//! *cache = Some(span_tree);
//! }
//! self.span_tree_cache.borrow_mut()
//! .get_or_insert_with(|| self.calc_span_tree())
//! .clone()
//! }
//!
//! // Recursive call to return the just-cached value.
//! // Note that if we had not let the previous borrow
//! // of the cache fall out of scope then the subsequent
//! // recursive borrow would cause a dynamic thread panic.
//! // This is the major hazard of using `RefCell`.
//! self.minimum_spanning_tree()
//! fn calc_span_tree(&self) -> Vec<(i32, i32)> {
//! // Expensive computation goes here
//! vec![]
//! }
//! # fn calc_span_tree(&self) -> Vec<(i32, i32)> { vec![] }
//! }
//! ```
//!
Expand Down
1 change: 1 addition & 0 deletions src/libcore/num/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ assert_eq!(size_of::<Option<core::num::", stringify!($Ty), ">>(), size_of::<", s
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
#[cfg_attr(not(stage0), rustc_nonnull_optimization_guaranteed)]
pub struct $Ty($Int);
}

Expand Down
1 change: 1 addition & 0 deletions src/libcore/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2938,6 +2938,7 @@ impl<'a, T: ?Sized> From<NonNull<T>> for Unique<T> {
#[stable(feature = "nonnull", since = "1.25.0")]
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
#[cfg_attr(not(stage0), rustc_nonnull_optimization_guaranteed)]
pub struct NonNull<T: ?Sized> {
pointer: *const T,
}
Expand Down
85 changes: 68 additions & 17 deletions src/librustc/traits/auto_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -700,22 +700,64 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
}
}

// We can only call poly_project_and_unify_type when our predicate's
// Ty contains an inference variable - otherwise, there won't be anything to
// unify
if p.ty().skip_binder().has_infer_types() {
debug!("Projecting and unifying projection predicate {:?}",
predicate);
match poly_project_and_unify_type(select, &obligation.with(p)) {
Err(e) => {
debug!(
"evaluate_nested_obligations: Unable to unify predicate \
'{:?}' '{:?}', bailing out",
ty, e
);
return false;
}
Ok(Some(v)) => {
// There are three possible cases when we project a predicate:
//
// 1. We encounter an error. This means that it's impossible for
// our current type to implement the auto trait - there's bound
// that we could add to our ParamEnv that would 'fix' this kind
// of error, as it's not caused by an unimplemented type.
//
// 2. We succesfully project the predicate (Ok(Some(_))), generating
// some subobligations. We then process these subobligations
// like any other generated sub-obligations.
//
// 3. We receieve an 'ambiguous' result (Ok(None))
// If we were actually trying to compile a crate,
// we would need to re-process this obligation later.
// However, all we care about is finding out what bounds
// are needed for our type to implement a particular auto trait.
// We've already added this obligation to our computed ParamEnv
// above (if it was necessary). Therefore, we don't need
// to do any further processing of the obligation.
//
// Note that we *must* try to project *all* projection predicates
// we encounter, even ones without inference variable.
// This ensures that we detect any projection errors,
// which indicate that our type can *never* implement the given
// auto trait. In that case, we will generate an explicit negative
// impl (e.g. 'impl !Send for MyType'). However, we don't
// try to process any of the generated subobligations -
// they contain no new information, since we already know
// that our type implements the projected-through trait,
// and can lead to weird region issues.
//
// Normally, we'll generate a negative impl as a result of encountering
// a type with an explicit negative impl of an auto trait
// (for example, raw pointers have !Send and !Sync impls)
// However, through some **interesting** manipulations of the type
// system, it's actually possible to write a type that never
// implements an auto trait due to a projection error, not a normal
// negative impl error. To properly handle this case, we need
// to ensure that we catch any potential projection errors,
// and turn them into an explicit negative impl for our type.
debug!("Projecting and unifying projection predicate {:?}",
predicate);

match poly_project_and_unify_type(select, &obligation.with(p)) {
Err(e) => {
debug!(
"evaluate_nested_obligations: Unable to unify predicate \
'{:?}' '{:?}', bailing out",
ty, e
);
return false;
}
Ok(Some(v)) => {
// We only care about sub-obligations
// when we started out trying to unify
// some inference variables. See the comment above
// for more infomration
if p.ty().skip_binder().has_infer_types() {
if !self.evaluate_nested_obligations(
ty,
v.clone().iter().cloned(),
Expand All @@ -728,7 +770,16 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
return false;
}
}
Ok(None) => {
}
Ok(None) => {
// It's ok not to make progress when hvave no inference variables -
// in that case, we were only performing unifcation to check if an
// error occured (which would indicate that it's impossible for our
// type to implement the auto trait).
// However, we should always make progress (either by generating
// subobligations or getting an error) when we started off with
// inference variables
if p.ty().skip_binder().has_infer_types() {
panic!("Unexpected result when selecting {:?} {:?}", ty, obligation)
}
}
Expand Down
70 changes: 36 additions & 34 deletions src/librustc_codegen_ssa/mir/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,45 +380,47 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
) -> Option<OperandRef<'tcx, Bx::Value>> {
debug!("maybe_codegen_consume_direct(place={:?})", place);

// watch out for locals that do not have an
// alloca; they are handled somewhat differently
if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
match self.locals[index] {
LocalRef::Operand(Some(o)) => {
return Some(o);
}
LocalRef::Operand(None) => {
bug!("use of {:?} before def", place);
}
LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => {
// use path below
}
}
}
place.iterate(|place_base, place_projection| {
if let mir::PlaceBase::Local(index) = place_base {
match self.locals[*index] {
LocalRef::Operand(Some(mut o)) => {
// Moves out of scalar and scalar pair fields are trivial.
for proj in place_projection {
match proj.elem {
mir::ProjectionElem::Field(ref f, _) => {
o = o.extract_field(bx, f.index());
}
mir::ProjectionElem::Index(_) |
mir::ProjectionElem::ConstantIndex { .. } => {
// ZSTs don't require any actual memory access.
// FIXME(eddyb) deduplicate this with the identical
// checks in `codegen_consume` and `extract_field`.
let elem = o.layout.field(bx.cx(), 0);
if elem.is_zst() {
o = OperandRef::new_zst(bx, elem);
} else {
return None;
}
}
_ => return None,
}
}

// Moves out of scalar and scalar pair fields are trivial.
if let &mir::Place::Projection(ref proj) = place {
if let Some(o) = self.maybe_codegen_consume_direct(bx, &proj.base) {
match proj.elem {
mir::ProjectionElem::Field(ref f, _) => {
return Some(o.extract_field(bx, f.index()));
Some(o)
}
mir::ProjectionElem::Index(_) |
mir::ProjectionElem::ConstantIndex { .. } => {
// ZSTs don't require any actual memory access.
// FIXME(eddyb) deduplicate this with the identical
// checks in `codegen_consume` and `extract_field`.
let elem = o.layout.field(bx.cx(), 0);
if elem.is_zst() {
return Some(OperandRef::new_zst(bx, elem));
}
LocalRef::Operand(None) => {
bug!("use of {:?} before def", place);
}
LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => {
// watch out for locals that do not have an
// alloca; they are handled somewhat differently
None
}
_ => {}
}
} else {
None
}
}

None
})
}

pub fn codegen_consume(
Expand Down
Loading