Skip to content

Commit

Permalink
Auto merge of rust-lang#61258 - Centril:rollup-l2mof9t, r=Centril
Browse files Browse the repository at this point in the history
Rollup of 9 pull requests

Successful merges:

 - rust-lang#61084 (Clarify docs for unreachable! macro)
 - rust-lang#61220 (Added error message for E0284)
 - rust-lang#61227 (Use .await syntax instead of await!)
 - rust-lang#61230 (avoid creating Boxes of uninitalized values in RawVec)
 - rust-lang#61237 (Updated the Iterator docs with information about overriding methods.)
 - rust-lang#61241 (Check place iterative)
 - rust-lang#61242 (Make dest_needs_borrow iterate instead of recurse)
 - rust-lang#61247 (Make eval_place iterate instead of recurse)
 - rust-lang#61248 (Use Place::local)

Failed merges:

r? @ghost
  • Loading branch information
bors committed May 28, 2019
2 parents 837b72c + 149c53f commit 7da1185
Show file tree
Hide file tree
Showing 15 changed files with 168 additions and 110 deletions.
16 changes: 9 additions & 7 deletions src/liballoc/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,11 +395,10 @@ impl<T: Clone> Clone for Box<T> {
#[stable(feature = "box_slice_clone", since = "1.3.0")]
impl Clone for Box<str> {
fn clone(&self) -> Self {
let len = self.len();
let buf = RawVec::with_capacity(len);
// this makes a copy of the data
let buf: Box<[u8]> = self.as_bytes().into();
unsafe {
ptr::copy_nonoverlapping(self.as_ptr(), buf.ptr(), len);
from_boxed_utf8_unchecked(buf.into_box())
from_boxed_utf8_unchecked(buf)
}
}
}
Expand Down Expand Up @@ -546,9 +545,12 @@ impl<T: Copy> From<&[T]> for Box<[T]> {
/// println!("{:?}", boxed_slice);
/// ```
fn from(slice: &[T]) -> Box<[T]> {
let mut boxed = unsafe { RawVec::with_capacity(slice.len()).into_box() };
boxed.copy_from_slice(slice);
boxed
let len = slice.len();
let buf = RawVec::with_capacity(len);
unsafe {
ptr::copy_nonoverlapping(slice.as_ptr(), buf.ptr(), len);
buf.into_box()
}
}
}

Expand Down
10 changes: 6 additions & 4 deletions src/liballoc/raw_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -685,12 +685,14 @@ impl<T, A: Alloc> RawVec<T, A> {
impl<T> RawVec<T, Global> {
/// Converts the entire buffer into `Box<[T]>`.
///
/// While it is not *strictly* Undefined Behavior to call
/// this procedure while some of the RawVec is uninitialized,
/// it certainly makes it trivial to trigger it.
///
/// Note that this will correctly reconstitute any `cap` changes
/// that may have been performed. (see description of type for details)
///
/// # Undefined Behavior
///
/// All elements of `RawVec<T, Global>` must be initialized. Notice that
/// the rules around uninitialized boxed values are not finalized yet,
/// but until they are, it is advisable to avoid them.
pub unsafe fn into_box(self) -> Box<[T]> {
// NOTE: not calling `cap()` here, actually using the real `cap` field!
let slice = slice::from_raw_parts_mut(self.ptr(), self.cap);
Expand Down
2 changes: 1 addition & 1 deletion src/libcore/future/future.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::task::{Context, Poll};
/// task.
///
/// When using a future, you generally won't call `poll` directly, but instead
/// `await!` the value.
/// `.await` the value.
#[doc(spotlight)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[stable(feature = "futures_api", since = "1.36.0")]
Expand Down
5 changes: 5 additions & 0 deletions src/libcore/iter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,11 @@
//! call `next()` on your iterator, until it reaches `None`. Let's go over that
//! next.
//!
//! Also note that `Iterator` provides a default implementation of methods such as `nth` and `fold`
//! which call `next` internally. However, it is also possible to write a custom implementation of
//! methods like `nth` and `fold` if an iterator can compute them more efficiently without calling
//! `next`.
//!
//! # for Loops and IntoIterator
//!
//! Rust's `for` loop syntax is actually sugar for iterators. Here's a basic
Expand Down
1 change: 1 addition & 0 deletions src/libcore/iter/traits/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -964,6 +964,7 @@ pub trait Iterator {
/// Creates an iterator that skips the first `n` elements.
///
/// After they have been consumed, the rest of the elements are yielded.
/// Rather than overriding this method directly, instead override the `nth` method.
///
/// # Examples
///
Expand Down
7 changes: 4 additions & 3 deletions src/libcore/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,9 +445,10 @@ macro_rules! writeln {
/// * Iterators that dynamically terminate.
///
/// If the determination that the code is unreachable proves incorrect, the
/// program immediately terminates with a [`panic!`]. The function [`unreachable_unchecked`],
/// which belongs to the [`std::hint`] module, informs the compiler to
/// optimize the code out of the release version entirely.
/// program immediately terminates with a [`panic!`].
///
/// The unsafe counterpart of this macro is the [`unreachable_unchecked`] function, which
/// will cause undefined behavior if the code is reached.
///
/// [`panic!`]: ../std/macro.panic.html
/// [`unreachable_unchecked`]: ../std/hint/fn.unreachable_unchecked.html
Expand Down
46 changes: 45 additions & 1 deletion src/librustc/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1207,6 +1207,51 @@ fn main() {
```
"##,

E0284: r##"
This error occurs when the compiler is unable to unambiguously infer the
return type of a function or method which is generic on return type, such
as the `collect` method for `Iterator`s.
For example:
```compile_fail,E0284
fn foo() -> Result<bool, ()> {
let results = [Ok(true), Ok(false), Err(())].iter().cloned();
let v: Vec<bool> = results.collect()?;
// Do things with v...
Ok(true)
}
```
Here we have an iterator `results` over `Result<bool, ()>`.
Hence, `results.collect()` can return any type implementing
`FromIterator<Result<bool, ()>>`. On the other hand, the
`?` operator can accept any type implementing `Try`.
The author of this code probably wants `collect()` to return a
`Result<Vec<bool>, ()>`, but the compiler can't be sure
that there isn't another type `T` implementing both `Try` and
`FromIterator<Result<bool, ()>>` in scope such that
`T::Ok == Vec<bool>`. Hence, this code is ambiguous and an error
is returned.
To resolve this error, use a concrete type for the intermediate expression:
```
fn foo() -> Result<bool, ()> {
let results = [Ok(true), Ok(false), Err(())].iter().cloned();
let v = {
let temp: Result<Vec<bool>, ()> = results.collect();
temp?
};
// Do things with v...
Ok(true)
}
```
Note that the type of `v` can now be inferred from the type of `temp`.
"##,

E0308: r##"
This error occurs when the compiler was unable to infer the concrete type of a
variable. It can occur for several cases, the most common of which is a
Expand Down Expand Up @@ -2158,7 +2203,6 @@ register_diagnostics! {
E0278, // requirement is not satisfied
E0279, // requirement is not satisfied
E0280, // requirement is not satisfied
E0284, // cannot resolve type
// E0285, // overflow evaluation builtin bounds
// E0296, // replaced with a generic attribute input check
// E0300, // unexpanded macro
Expand Down
10 changes: 3 additions & 7 deletions src/librustc_mir/build/expr/as_rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -528,13 +528,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
}) => {
// Not projected from the implicit `self` in a closure.
debug_assert!(
match *base {
Place::Base(PlaceBase::Local(local)) => local == Local::new(1),
Place::Projection(box Projection {
ref base,
elem: ProjectionElem::Deref,
}) => *base == Place::Base(PlaceBase::Local(Local::new(1))),
_ => false,
match base.local() {
Some(local) => local == Local::new(1),
None => false,
},
"Unexpected capture place"
);
Expand Down
79 changes: 41 additions & 38 deletions src/librustc_mir/transform/const_prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,47 +296,50 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {

fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
trace!("eval_place(place={:?})", place);
match *place {
Place::Base(PlaceBase::Local(loc)) => self.places[loc].clone(),
Place::Projection(ref proj) => match proj.elem {
ProjectionElem::Field(field, _) => {
trace!("field proj on {:?}", proj.base);
let base = self.eval_place(&proj.base, source_info)?;
place.iterate(|place_base, place_projection| {
let mut eval = match place_base {
PlaceBase::Local(loc) => self.places[*loc].clone()?,
PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted), ..}) => {
let generics = self.tcx.generics_of(self.source.def_id());
if generics.requires_monomorphization(self.tcx) {
// FIXME: can't handle code with generics
return None;
}
let substs = InternalSubsts::identity_for_item(self.tcx, self.source.def_id());
let instance = Instance::new(self.source.def_id(), substs);
let cid = GlobalId {
instance,
promoted: Some(*promoted),
};
// cannot use `const_eval` here, because that would require having the MIR
// for the current function available, but we're producing said MIR right now
let res = self.use_ecx(source_info, |this| {
this.ecx.operand_field(base, field.index() as u64)
let mir = &this.promoted[*promoted];
eval_promoted(this.tcx, cid, mir, this.param_env)
})?;
Some(res)
},
// We could get more projections by using e.g., `operand_projection`,
// but we do not even have the stack frame set up properly so
// an `Index` projection would throw us off-track.
_ => None,
},
Place::Base(
PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted), ..})
) => {
let generics = self.tcx.generics_of(self.source.def_id());
if generics.requires_monomorphization(self.tcx) {
// FIXME: can't handle code with generics
return None;
trace!("evaluated promoted {:?} to {:?}", promoted, res);
res.into()
}
let substs = InternalSubsts::identity_for_item(self.tcx, self.source.def_id());
let instance = Instance::new(self.source.def_id(), substs);
let cid = GlobalId {
instance,
promoted: Some(promoted),
};
// cannot use `const_eval` here, because that would require having the MIR
// for the current function available, but we're producing said MIR right now
let res = self.use_ecx(source_info, |this| {
let mir = &this.promoted[promoted];
eval_promoted(this.tcx, cid, mir, this.param_env)
})?;
trace!("evaluated promoted {:?} to {:?}", promoted, res);
Some(res.into())
},
_ => None,
}
_ => return None,
};

for proj in place_projection {
match proj.elem {
ProjectionElem::Field(field, _) => {
trace!("field proj on {:?}", proj.base);
eval = self.use_ecx(source_info, |this| {
this.ecx.operand_field(eval, field.index() as u64)
})?;
},
// We could get more projections by using e.g., `operand_projection`,
// but we do not even have the stack frame set up properly so
// an `Index` projection would throw us off-track.
_ => return None,
}
}

Some(eval)
})
}

fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
Expand Down
23 changes: 13 additions & 10 deletions src/librustc_mir/transform/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,19 +440,22 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
// writes to `i`. To prevent this we need to create a temporary
// borrow of the place and pass the destination as `*temp` instead.
fn dest_needs_borrow(place: &Place<'_>) -> bool {
match *place {
Place::Projection(ref p) => {
match p.elem {
place.iterate(|place_base, place_projection| {
for proj in place_projection {
match proj.elem {
ProjectionElem::Deref |
ProjectionElem::Index(_) => true,
_ => dest_needs_borrow(&p.base)
ProjectionElem::Index(_) => return true,
_ => {}
}
}
// Static variables need a borrow because the callee
// might modify the same static.
Place::Base(PlaceBase::Static(_)) => true,
_ => false
}

match place_base {
// Static variables need a borrow because the callee
// might modify the same static.
PlaceBase::Static(_) => true,
_ => false
}
})
}

let dest = if dest_needs_borrow(&destination.0) {
Expand Down
Loading

0 comments on commit 7da1185

Please sign in to comment.