Skip to content

Commit 05de9f3

Browse files
committed
Auto merge of #61258 - Centril:rollup-l2mof9t, r=Centril
Rollup of 9 pull requests Successful merges: - #61084 (Clarify docs for unreachable! macro) - #61220 (Added error message for E0284) - #61227 (Use .await syntax instead of await!) - #61230 (avoid creating Boxes of uninitalized values in RawVec) - #61237 (Updated the Iterator docs with information about overriding methods.) - #61241 (Check place iterative) - #61242 (Make dest_needs_borrow iterate instead of recurse) - #61247 (Make eval_place iterate instead of recurse) - #61248 (Use Place::local) Failed merges: r? @ghost
2 parents 837b72c + 149c53f commit 05de9f3

15 files changed

+168
-110
lines changed

src/liballoc/boxed.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -395,11 +395,10 @@ impl<T: Clone> Clone for Box<T> {
395395
#[stable(feature = "box_slice_clone", since = "1.3.0")]
396396
impl Clone for Box<str> {
397397
fn clone(&self) -> Self {
398-
let len = self.len();
399-
let buf = RawVec::with_capacity(len);
398+
// this makes a copy of the data
399+
let buf: Box<[u8]> = self.as_bytes().into();
400400
unsafe {
401-
ptr::copy_nonoverlapping(self.as_ptr(), buf.ptr(), len);
402-
from_boxed_utf8_unchecked(buf.into_box())
401+
from_boxed_utf8_unchecked(buf)
403402
}
404403
}
405404
}
@@ -546,9 +545,12 @@ impl<T: Copy> From<&[T]> for Box<[T]> {
546545
/// println!("{:?}", boxed_slice);
547546
/// ```
548547
fn from(slice: &[T]) -> Box<[T]> {
549-
let mut boxed = unsafe { RawVec::with_capacity(slice.len()).into_box() };
550-
boxed.copy_from_slice(slice);
551-
boxed
548+
let len = slice.len();
549+
let buf = RawVec::with_capacity(len);
550+
unsafe {
551+
ptr::copy_nonoverlapping(slice.as_ptr(), buf.ptr(), len);
552+
buf.into_box()
553+
}
552554
}
553555
}
554556

src/liballoc/raw_vec.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -685,12 +685,14 @@ impl<T, A: Alloc> RawVec<T, A> {
685685
impl<T> RawVec<T, Global> {
686686
/// Converts the entire buffer into `Box<[T]>`.
687687
///
688-
/// While it is not *strictly* Undefined Behavior to call
689-
/// this procedure while some of the RawVec is uninitialized,
690-
/// it certainly makes it trivial to trigger it.
691-
///
692688
/// Note that this will correctly reconstitute any `cap` changes
693689
/// that may have been performed. (see description of type for details)
690+
///
691+
/// # Undefined Behavior
692+
///
693+
/// All elements of `RawVec<T, Global>` must be initialized. Notice that
694+
/// the rules around uninitialized boxed values are not finalized yet,
695+
/// but until they are, it is advisable to avoid them.
694696
pub unsafe fn into_box(self) -> Box<[T]> {
695697
// NOTE: not calling `cap()` here, actually using the real `cap` field!
696698
let slice = slice::from_raw_parts_mut(self.ptr(), self.cap);

src/libcore/future/future.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use crate::task::{Context, Poll};
2121
/// task.
2222
///
2323
/// When using a future, you generally won't call `poll` directly, but instead
24-
/// `await!` the value.
24+
/// `.await` the value.
2525
#[doc(spotlight)]
2626
#[must_use = "futures do nothing unless you `.await` or poll them"]
2727
#[stable(feature = "futures_api", since = "1.36.0")]

src/libcore/iter/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,11 @@
140140
//! call `next()` on your iterator, until it reaches `None`. Let's go over that
141141
//! next.
142142
//!
143+
//! Also note that `Iterator` provides a default implementation of methods such as `nth` and `fold`
144+
//! which call `next` internally. However, it is also possible to write a custom implementation of
145+
//! methods like `nth` and `fold` if an iterator can compute them more efficiently without calling
146+
//! `next`.
147+
//!
143148
//! # for Loops and IntoIterator
144149
//!
145150
//! Rust's `for` loop syntax is actually sugar for iterators. Here's a basic

src/libcore/iter/traits/iterator.rs

+1
Original file line numberDiff line numberDiff line change
@@ -964,6 +964,7 @@ pub trait Iterator {
964964
/// Creates an iterator that skips the first `n` elements.
965965
///
966966
/// After they have been consumed, the rest of the elements are yielded.
967+
/// Rather than overriding this method directly, instead override the `nth` method.
967968
///
968969
/// # Examples
969970
///

src/libcore/macros.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -445,9 +445,10 @@ macro_rules! writeln {
445445
/// * Iterators that dynamically terminate.
446446
///
447447
/// If the determination that the code is unreachable proves incorrect, the
448-
/// program immediately terminates with a [`panic!`]. The function [`unreachable_unchecked`],
449-
/// which belongs to the [`std::hint`] module, informs the compiler to
450-
/// optimize the code out of the release version entirely.
448+
/// program immediately terminates with a [`panic!`].
449+
///
450+
/// The unsafe counterpart of this macro is the [`unreachable_unchecked`] function, which
451+
/// will cause undefined behavior if the code is reached.
451452
///
452453
/// [`panic!`]: ../std/macro.panic.html
453454
/// [`unreachable_unchecked`]: ../std/hint/fn.unreachable_unchecked.html

src/librustc/error_codes.rs

+45-1
Original file line numberDiff line numberDiff line change
@@ -1207,6 +1207,51 @@ fn main() {
12071207
```
12081208
"##,
12091209

1210+
E0284: r##"
1211+
This error occurs when the compiler is unable to unambiguously infer the
1212+
return type of a function or method which is generic on return type, such
1213+
as the `collect` method for `Iterator`s.
1214+
1215+
For example:
1216+
1217+
```compile_fail,E0284
1218+
fn foo() -> Result<bool, ()> {
1219+
let results = [Ok(true), Ok(false), Err(())].iter().cloned();
1220+
let v: Vec<bool> = results.collect()?;
1221+
// Do things with v...
1222+
Ok(true)
1223+
}
1224+
```
1225+
1226+
Here we have an iterator `results` over `Result<bool, ()>`.
1227+
Hence, `results.collect()` can return any type implementing
1228+
`FromIterator<Result<bool, ()>>`. On the other hand, the
1229+
`?` operator can accept any type implementing `Try`.
1230+
1231+
The author of this code probably wants `collect()` to return a
1232+
`Result<Vec<bool>, ()>`, but the compiler can't be sure
1233+
that there isn't another type `T` implementing both `Try` and
1234+
`FromIterator<Result<bool, ()>>` in scope such that
1235+
`T::Ok == Vec<bool>`. Hence, this code is ambiguous and an error
1236+
is returned.
1237+
1238+
To resolve this error, use a concrete type for the intermediate expression:
1239+
1240+
```
1241+
fn foo() -> Result<bool, ()> {
1242+
let results = [Ok(true), Ok(false), Err(())].iter().cloned();
1243+
let v = {
1244+
let temp: Result<Vec<bool>, ()> = results.collect();
1245+
temp?
1246+
};
1247+
// Do things with v...
1248+
Ok(true)
1249+
}
1250+
```
1251+
1252+
Note that the type of `v` can now be inferred from the type of `temp`.
1253+
"##,
1254+
12101255
E0308: r##"
12111256
This error occurs when the compiler was unable to infer the concrete type of a
12121257
variable. It can occur for several cases, the most common of which is a
@@ -2158,7 +2203,6 @@ register_diagnostics! {
21582203
E0278, // requirement is not satisfied
21592204
E0279, // requirement is not satisfied
21602205
E0280, // requirement is not satisfied
2161-
E0284, // cannot resolve type
21622206
// E0285, // overflow evaluation builtin bounds
21632207
// E0296, // replaced with a generic attribute input check
21642208
// E0300, // unexpanded macro

src/librustc_mir/build/expr/as_rvalue.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -528,13 +528,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
528528
}) => {
529529
// Not projected from the implicit `self` in a closure.
530530
debug_assert!(
531-
match *base {
532-
Place::Base(PlaceBase::Local(local)) => local == Local::new(1),
533-
Place::Projection(box Projection {
534-
ref base,
535-
elem: ProjectionElem::Deref,
536-
}) => *base == Place::Base(PlaceBase::Local(Local::new(1))),
537-
_ => false,
531+
match base.local() {
532+
Some(local) => local == Local::new(1),
533+
None => false,
538534
},
539535
"Unexpected capture place"
540536
);

src/librustc_mir/transform/const_prop.rs

+41-38
Original file line numberDiff line numberDiff line change
@@ -296,47 +296,50 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
296296

297297
fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
298298
trace!("eval_place(place={:?})", place);
299-
match *place {
300-
Place::Base(PlaceBase::Local(loc)) => self.places[loc].clone(),
301-
Place::Projection(ref proj) => match proj.elem {
302-
ProjectionElem::Field(field, _) => {
303-
trace!("field proj on {:?}", proj.base);
304-
let base = self.eval_place(&proj.base, source_info)?;
299+
place.iterate(|place_base, place_projection| {
300+
let mut eval = match place_base {
301+
PlaceBase::Local(loc) => self.places[*loc].clone()?,
302+
PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted), ..}) => {
303+
let generics = self.tcx.generics_of(self.source.def_id());
304+
if generics.requires_monomorphization(self.tcx) {
305+
// FIXME: can't handle code with generics
306+
return None;
307+
}
308+
let substs = InternalSubsts::identity_for_item(self.tcx, self.source.def_id());
309+
let instance = Instance::new(self.source.def_id(), substs);
310+
let cid = GlobalId {
311+
instance,
312+
promoted: Some(*promoted),
313+
};
314+
// cannot use `const_eval` here, because that would require having the MIR
315+
// for the current function available, but we're producing said MIR right now
305316
let res = self.use_ecx(source_info, |this| {
306-
this.ecx.operand_field(base, field.index() as u64)
317+
let mir = &this.promoted[*promoted];
318+
eval_promoted(this.tcx, cid, mir, this.param_env)
307319
})?;
308-
Some(res)
309-
},
310-
// We could get more projections by using e.g., `operand_projection`,
311-
// but we do not even have the stack frame set up properly so
312-
// an `Index` projection would throw us off-track.
313-
_ => None,
314-
},
315-
Place::Base(
316-
PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted), ..})
317-
) => {
318-
let generics = self.tcx.generics_of(self.source.def_id());
319-
if generics.requires_monomorphization(self.tcx) {
320-
// FIXME: can't handle code with generics
321-
return None;
320+
trace!("evaluated promoted {:?} to {:?}", promoted, res);
321+
res.into()
322322
}
323-
let substs = InternalSubsts::identity_for_item(self.tcx, self.source.def_id());
324-
let instance = Instance::new(self.source.def_id(), substs);
325-
let cid = GlobalId {
326-
instance,
327-
promoted: Some(promoted),
328-
};
329-
// cannot use `const_eval` here, because that would require having the MIR
330-
// for the current function available, but we're producing said MIR right now
331-
let res = self.use_ecx(source_info, |this| {
332-
let mir = &this.promoted[promoted];
333-
eval_promoted(this.tcx, cid, mir, this.param_env)
334-
})?;
335-
trace!("evaluated promoted {:?} to {:?}", promoted, res);
336-
Some(res.into())
337-
},
338-
_ => None,
339-
}
323+
_ => return None,
324+
};
325+
326+
for proj in place_projection {
327+
match proj.elem {
328+
ProjectionElem::Field(field, _) => {
329+
trace!("field proj on {:?}", proj.base);
330+
eval = self.use_ecx(source_info, |this| {
331+
this.ecx.operand_field(eval, field.index() as u64)
332+
})?;
333+
},
334+
// We could get more projections by using e.g., `operand_projection`,
335+
// but we do not even have the stack frame set up properly so
336+
// an `Index` projection would throw us off-track.
337+
_ => return None,
338+
}
339+
}
340+
341+
Some(eval)
342+
})
340343
}
341344

342345
fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {

src/librustc_mir/transform/inline.rs

+13-10
Original file line numberDiff line numberDiff line change
@@ -440,19 +440,22 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
440440
// writes to `i`. To prevent this we need to create a temporary
441441
// borrow of the place and pass the destination as `*temp` instead.
442442
fn dest_needs_borrow(place: &Place<'_>) -> bool {
443-
match *place {
444-
Place::Projection(ref p) => {
445-
match p.elem {
443+
place.iterate(|place_base, place_projection| {
444+
for proj in place_projection {
445+
match proj.elem {
446446
ProjectionElem::Deref |
447-
ProjectionElem::Index(_) => true,
448-
_ => dest_needs_borrow(&p.base)
447+
ProjectionElem::Index(_) => return true,
448+
_ => {}
449449
}
450450
}
451-
// Static variables need a borrow because the callee
452-
// might modify the same static.
453-
Place::Base(PlaceBase::Static(_)) => true,
454-
_ => false
455-
}
451+
452+
match place_base {
453+
// Static variables need a borrow because the callee
454+
// might modify the same static.
455+
PlaceBase::Static(_) => true,
456+
_ => false
457+
}
458+
})
456459
}
457460

458461
let dest = if dest_needs_borrow(&destination.0) {

0 commit comments

Comments
 (0)