Skip to content

Commit 11f01bf

Browse files
committed
Auto merge of #61044 - Centril:rollup-ztsgb9p, r=Centril
Rollup of 8 pull requests Successful merges: - #60300 (Allow null-pointer-optimized enums in FFI if their underlying representation is FFI safe) - #60773 (Always try to project predicates when finding auto traits in rustdoc) - #60809 (Add FAQ for NLL migration) - #61023 (Migrate from recursion to iterate on qualify consts visitor impl) - #61029 (Simplify RefCell minimum_spanning_tree example) - #61030 (Make maybe_codegen_consume_direct iterate instead of doing recursion) - #61034 (rustc_metadata: parametrize schema::CrateRoot by 'tcx and rip out old unused incremental infra.) - #61037 (Update clippy submodule) Failed merges: r? @ghost
2 parents 37ff5d3 + 6806517 commit 11f01bf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+582
-838
lines changed

src/libcore/cell.rs

+22-24
Original file line numberDiff line numberDiff line change
@@ -67,16 +67,26 @@
6767
//! mutability:
6868
//!
6969
//! ```
70+
//! use std::cell::{RefCell, RefMut};
7071
//! use std::collections::HashMap;
71-
//! use std::cell::RefCell;
7272
//! use std::rc::Rc;
7373
//!
7474
//! fn main() {
7575
//! let shared_map: Rc<RefCell<_>> = Rc::new(RefCell::new(HashMap::new()));
76-
//! shared_map.borrow_mut().insert("africa", 92388);
77-
//! shared_map.borrow_mut().insert("kyoto", 11837);
78-
//! shared_map.borrow_mut().insert("piccadilly", 11826);
79-
//! shared_map.borrow_mut().insert("marbles", 38);
76+
//! // Create a new block to limit the scope of the dynamic borrow
77+
//! {
78+
//! let mut map: RefMut<_> = shared_map.borrow_mut();
79+
//! map.insert("africa", 92388);
80+
//! map.insert("kyoto", 11837);
81+
//! map.insert("piccadilly", 11826);
82+
//! map.insert("marbles", 38);
83+
//! }
84+
//!
85+
//! // Note that if we had not let the previous borrow of the cache fall out
86+
//! // of scope then the subsequent borrow would cause a dynamic thread panic.
87+
//! // This is the major hazard of using `RefCell`.
88+
//! let total: i32 = shared_map.borrow().values().sum();
89+
//! println!("{}", total);
8090
//! }
8191
//! ```
8292
//!
@@ -102,27 +112,15 @@
102112
//!
103113
//! impl Graph {
104114
//! fn minimum_spanning_tree(&self) -> Vec<(i32, i32)> {
105-
//! // Create a new scope to contain the lifetime of the
106-
//! // dynamic borrow
107-
//! {
108-
//! // Take a reference to the inside of cache cell
109-
//! let mut cache = self.span_tree_cache.borrow_mut();
110-
//! if cache.is_some() {
111-
//! return cache.as_ref().unwrap().clone();
112-
//! }
113-
//!
114-
//! let span_tree = self.calc_span_tree();
115-
//! *cache = Some(span_tree);
116-
//! }
115+
//! self.span_tree_cache.borrow_mut()
116+
//! .get_or_insert_with(|| self.calc_span_tree())
117+
//! .clone()
118+
//! }
117119
//!
118-
//! // Recursive call to return the just-cached value.
119-
//! // Note that if we had not let the previous borrow
120-
//! // of the cache fall out of scope then the subsequent
121-
//! // recursive borrow would cause a dynamic thread panic.
122-
//! // This is the major hazard of using `RefCell`.
123-
//! self.minimum_spanning_tree()
120+
//! fn calc_span_tree(&self) -> Vec<(i32, i32)> {
121+
//! // Expensive computation goes here
122+
//! vec![]
124123
//! }
125-
//! # fn calc_span_tree(&self) -> Vec<(i32, i32)> { vec![] }
126124
//! }
127125
//! ```
128126
//!

src/libcore/num/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ assert_eq!(size_of::<Option<core::num::", stringify!($Ty), ">>(), size_of::<", s
5050
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
5151
#[repr(transparent)]
5252
#[rustc_layout_scalar_valid_range_start(1)]
53+
#[cfg_attr(not(stage0), rustc_nonnull_optimization_guaranteed)]
5354
pub struct $Ty($Int);
5455
}
5556

src/libcore/ptr.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2938,6 +2938,7 @@ impl<'a, T: ?Sized> From<NonNull<T>> for Unique<T> {
29382938
#[stable(feature = "nonnull", since = "1.25.0")]
29392939
#[repr(transparent)]
29402940
#[rustc_layout_scalar_valid_range_start(1)]
2941+
#[cfg_attr(not(stage0), rustc_nonnull_optimization_guaranteed)]
29412942
pub struct NonNull<T: ?Sized> {
29422943
pointer: *const T,
29432944
}

src/librustc/traits/auto_trait.rs

+68-17
Original file line numberDiff line numberDiff line change
@@ -700,22 +700,64 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
700700
}
701701
}
702702

703-
// We can only call poly_project_and_unify_type when our predicate's
704-
// Ty contains an inference variable - otherwise, there won't be anything to
705-
// unify
706-
if p.ty().skip_binder().has_infer_types() {
707-
debug!("Projecting and unifying projection predicate {:?}",
708-
predicate);
709-
match poly_project_and_unify_type(select, &obligation.with(p)) {
710-
Err(e) => {
711-
debug!(
712-
"evaluate_nested_obligations: Unable to unify predicate \
713-
'{:?}' '{:?}', bailing out",
714-
ty, e
715-
);
716-
return false;
717-
}
718-
Ok(Some(v)) => {
703+
// There are three possible cases when we project a predicate:
704+
//
705+
// 1. We encounter an error. This means that it's impossible for
706+
// our current type to implement the auto trait - there's bound
707+
// that we could add to our ParamEnv that would 'fix' this kind
708+
// of error, as it's not caused by an unimplemented type.
709+
//
710+
// 2. We succesfully project the predicate (Ok(Some(_))), generating
711+
// some subobligations. We then process these subobligations
712+
// like any other generated sub-obligations.
713+
//
714+
// 3. We receieve an 'ambiguous' result (Ok(None))
715+
// If we were actually trying to compile a crate,
716+
// we would need to re-process this obligation later.
717+
// However, all we care about is finding out what bounds
718+
// are needed for our type to implement a particular auto trait.
719+
// We've already added this obligation to our computed ParamEnv
720+
// above (if it was necessary). Therefore, we don't need
721+
// to do any further processing of the obligation.
722+
//
723+
// Note that we *must* try to project *all* projection predicates
724+
// we encounter, even ones without inference variable.
725+
// This ensures that we detect any projection errors,
726+
// which indicate that our type can *never* implement the given
727+
// auto trait. In that case, we will generate an explicit negative
728+
// impl (e.g. 'impl !Send for MyType'). However, we don't
729+
// try to process any of the generated subobligations -
730+
// they contain no new information, since we already know
731+
// that our type implements the projected-through trait,
732+
// and can lead to weird region issues.
733+
//
734+
// Normally, we'll generate a negative impl as a result of encountering
735+
// a type with an explicit negative impl of an auto trait
736+
// (for example, raw pointers have !Send and !Sync impls)
737+
// However, through some **interesting** manipulations of the type
738+
// system, it's actually possible to write a type that never
739+
// implements an auto trait due to a projection error, not a normal
740+
// negative impl error. To properly handle this case, we need
741+
// to ensure that we catch any potential projection errors,
742+
// and turn them into an explicit negative impl for our type.
743+
debug!("Projecting and unifying projection predicate {:?}",
744+
predicate);
745+
746+
match poly_project_and_unify_type(select, &obligation.with(p)) {
747+
Err(e) => {
748+
debug!(
749+
"evaluate_nested_obligations: Unable to unify predicate \
750+
'{:?}' '{:?}', bailing out",
751+
ty, e
752+
);
753+
return false;
754+
}
755+
Ok(Some(v)) => {
756+
// We only care about sub-obligations
757+
// when we started out trying to unify
758+
// some inference variables. See the comment above
759+
// for more infomration
760+
if p.ty().skip_binder().has_infer_types() {
719761
if !self.evaluate_nested_obligations(
720762
ty,
721763
v.clone().iter().cloned(),
@@ -728,7 +770,16 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
728770
return false;
729771
}
730772
}
731-
Ok(None) => {
773+
}
774+
Ok(None) => {
775+
// It's ok not to make progress when hvave no inference variables -
776+
// in that case, we were only performing unifcation to check if an
777+
// error occured (which would indicate that it's impossible for our
778+
// type to implement the auto trait).
779+
// However, we should always make progress (either by generating
780+
// subobligations or getting an error) when we started off with
781+
// inference variables
782+
if p.ty().skip_binder().has_infer_types() {
732783
panic!("Unexpected result when selecting {:?} {:?}", ty, obligation)
733784
}
734785
}

src/librustc_codegen_ssa/mir/operand.rs

+36-34
Original file line numberDiff line numberDiff line change
@@ -380,45 +380,47 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
380380
) -> Option<OperandRef<'tcx, Bx::Value>> {
381381
debug!("maybe_codegen_consume_direct(place={:?})", place);
382382

383-
// watch out for locals that do not have an
384-
// alloca; they are handled somewhat differently
385-
if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
386-
match self.locals[index] {
387-
LocalRef::Operand(Some(o)) => {
388-
return Some(o);
389-
}
390-
LocalRef::Operand(None) => {
391-
bug!("use of {:?} before def", place);
392-
}
393-
LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => {
394-
// use path below
395-
}
396-
}
397-
}
383+
place.iterate(|place_base, place_projection| {
384+
if let mir::PlaceBase::Local(index) = place_base {
385+
match self.locals[*index] {
386+
LocalRef::Operand(Some(mut o)) => {
387+
// Moves out of scalar and scalar pair fields are trivial.
388+
for proj in place_projection {
389+
match proj.elem {
390+
mir::ProjectionElem::Field(ref f, _) => {
391+
o = o.extract_field(bx, f.index());
392+
}
393+
mir::ProjectionElem::Index(_) |
394+
mir::ProjectionElem::ConstantIndex { .. } => {
395+
// ZSTs don't require any actual memory access.
396+
// FIXME(eddyb) deduplicate this with the identical
397+
// checks in `codegen_consume` and `extract_field`.
398+
let elem = o.layout.field(bx.cx(), 0);
399+
if elem.is_zst() {
400+
o = OperandRef::new_zst(bx, elem);
401+
} else {
402+
return None;
403+
}
404+
}
405+
_ => return None,
406+
}
407+
}
398408

399-
// Moves out of scalar and scalar pair fields are trivial.
400-
if let &mir::Place::Projection(ref proj) = place {
401-
if let Some(o) = self.maybe_codegen_consume_direct(bx, &proj.base) {
402-
match proj.elem {
403-
mir::ProjectionElem::Field(ref f, _) => {
404-
return Some(o.extract_field(bx, f.index()));
409+
Some(o)
405410
}
406-
mir::ProjectionElem::Index(_) |
407-
mir::ProjectionElem::ConstantIndex { .. } => {
408-
// ZSTs don't require any actual memory access.
409-
// FIXME(eddyb) deduplicate this with the identical
410-
// checks in `codegen_consume` and `extract_field`.
411-
let elem = o.layout.field(bx.cx(), 0);
412-
if elem.is_zst() {
413-
return Some(OperandRef::new_zst(bx, elem));
414-
}
411+
LocalRef::Operand(None) => {
412+
bug!("use of {:?} before def", place);
413+
}
414+
LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => {
415+
// watch out for locals that do not have an
416+
// alloca; they are handled somewhat differently
417+
None
415418
}
416-
_ => {}
417419
}
420+
} else {
421+
None
418422
}
419-
}
420-
421-
None
423+
})
422424
}
423425

424426
pub fn codegen_consume(

0 commit comments

Comments
 (0)