Skip to content

Rollup of 9 pull requests #61258

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

Merged
merged 23 commits into from
May 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
941ca6f
Clarify docs for unreachable! macro
blkerby May 23, 2019
27c7537
Remove phrase "instead of a panic!"
blkerby May 23, 2019
03cce1d
Added error message for E0284
imbrem May 26, 2019
5c5f08a
Use .await syntax instead of await!
diwic May 27, 2019
a23a77f
avoid materializing unintialized Boxes in RawVec
matklad May 27, 2019
b560b9c
Updated the Iterator docs with information about overriding methods.
May 27, 2019
0653e78
make Box<str>::clone simpler & safer
matklad May 27, 2019
fe31ad3
Update src/liballoc/boxed.rs
matklad May 27, 2019
acaf284
Remove unused tcx and mir params
spastorino May 27, 2019
b922e8a
Make dest_needs_borrow iterate instead of recurse
spastorino May 27, 2019
fb4b62b
Make check_place iterate instead of recurse
spastorino May 27, 2019
c3e71f2
Make eval_place iterate instead of recurse
spastorino May 27, 2019
38ecea4
Use Place::local
spastorino May 27, 2019
b348012
Incorporated suggested changes
imbrem May 27, 2019
08f7724
Rollup merge of #61084 - blkerby:unreachable_doc, r=KodrAus
Centril May 28, 2019
3b51579
Rollup merge of #61220 - imbrem:error_explanations, r=estebank
Centril May 28, 2019
c48835b
Rollup merge of #61227 - diwic:patch-2, r=Centril
Centril May 28, 2019
460e626
Rollup merge of #61230 - matklad:ub-comment, r=RalfJung
Centril May 28, 2019
a449bc3
Rollup merge of #61237 - DevQps:expand-iterator-docs, r=Mark-Simulacrum
Centril May 28, 2019
c33b349
Rollup merge of #61241 - spastorino:check-place-iterative, r=oli-obk
Centril May 28, 2019
ffb4ceb
Rollup merge of #61242 - spastorino:dest-needs-borrow-iterate, r=oli-obk
Centril May 28, 2019
1dc9bbb
Rollup merge of #61247 - spastorino:eval-place-iterate, r=wesleywiser
Centril May 28, 2019
149c53f
Rollup merge of #61248 - spastorino:use-place-local-fn, r=oli-obk
Centril May 28, 2019
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
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