Skip to content

Commit 2268d99

Browse files
committed
Auto merge of #61201 - Centril:rollup-975knrk, r=Centril
Rollup of 9 pull requests Successful merges: - #61087 (Tweak `self` arg not as first argument of a method diagnostic) - #61114 (Vec: avoid creating slices to the elements) - #61144 (Suggest borrowing for loop head on move error) - #61149 (Fix spelling in release notes) - #61161 (MaybeUninit doctest: remove unnecessary type ascription) - #61173 (Auto-derive Encode and Decode implementations of DefPathTable) - #61184 (Add additional trace statements to the const propagator) - #61189 (Turn turbo 🐟 🍨 into an error) - #61193 (Add comment to explain why we change the layout for Projection) Failed merges: r? @ghost
2 parents 572892c + 8d247e7 commit 2268d99

24 files changed

+870
-654
lines changed

RELEASES.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ Libraries
157157
produce a warning if their returning type is unused.
158158
- [The methods `checked_pow`, `saturating_pow`, `wrapping_pow`, and
159159
`overflowing_pow` are now available for all numeric types.][57873] These are
160-
equivalvent to methods such as `wrapping_add` for the `pow` operation.
160+
equivalent to methods such as `wrapping_add` for the `pow` operation.
161161

162162

163163
Stabilized APIs

src/liballoc/tests/vec.rs

+21
Original file line numberDiff line numberDiff line change
@@ -1152,3 +1152,24 @@ fn test_try_reserve_exact() {
11521152
}
11531153

11541154
}
1155+
1156+
#[test]
1157+
fn test_stable_push_pop() {
1158+
// Test that, if we reserved enough space, adding and removing elements does not
1159+
// invalidate references into the vector (such as `v0`). This test also
1160+
// runs in Miri, which would detect such problems.
1161+
let mut v = Vec::with_capacity(10);
1162+
v.push(13);
1163+
1164+
// laundering the lifetime -- we take care that `v` does not reallocate, so that's okay.
1165+
let v0 = unsafe { &*(&v[0] as *const _) };
1166+
1167+
// Now do a bunch of things and occasionally use `v0` again to assert it is still valid.
1168+
v.push(1);
1169+
v.push(2);
1170+
v.insert(1, 1);
1171+
assert_eq!(*v0, 13);
1172+
v.remove(1);
1173+
v.pop().unwrap();
1174+
assert_eq!(*v0, 13);
1175+
}

src/liballoc/vec.rs

+71-7
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,75 @@ impl<T> Vec<T> {
735735
self
736736
}
737737

738+
/// Returns a raw pointer to the vector's buffer.
739+
///
740+
/// The caller must ensure that the vector outlives the pointer this
741+
/// function returns, or else it will end up pointing to garbage.
742+
/// Modifying the vector may cause its buffer to be reallocated,
743+
/// which would also make any pointers to it invalid.
744+
///
745+
/// The caller must also ensure that the memory the pointer (non-transitively) points to
746+
/// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer
747+
/// derived from it. If you need to mutate the contents of the slice, use [`as_mut_ptr`].
748+
///
749+
/// # Examples
750+
///
751+
/// ```
752+
/// let x = vec![1, 2, 4];
753+
/// let x_ptr = x.as_ptr();
754+
///
755+
/// unsafe {
756+
/// for i in 0..x.len() {
757+
/// assert_eq!(*x_ptr.add(i), 1 << i);
758+
/// }
759+
/// }
760+
/// ```
761+
///
762+
/// [`as_mut_ptr`]: #method.as_mut_ptr
763+
#[stable(feature = "vec_as_ptr", since = "1.37.0")]
764+
#[inline]
765+
pub fn as_ptr(&self) -> *const T {
766+
// We shadow the slice method of the same name to avoid going through
767+
// `deref`, which creates an intermediate reference.
768+
let ptr = self.buf.ptr();
769+
unsafe { assume(!ptr.is_null()); }
770+
ptr
771+
}
772+
773+
/// Returns an unsafe mutable pointer to the vector's buffer.
774+
///
775+
/// The caller must ensure that the vector outlives the pointer this
776+
/// function returns, or else it will end up pointing to garbage.
777+
/// Modifying the vector may cause its buffer to be reallocated,
778+
/// which would also make any pointers to it invalid.
779+
///
780+
/// # Examples
781+
///
782+
/// ```
783+
/// // Allocate vector big enough for 4 elements.
784+
/// let size = 4;
785+
/// let mut x: Vec<i32> = Vec::with_capacity(size);
786+
/// let x_ptr = x.as_mut_ptr();
787+
///
788+
/// // Initialize elements via raw pointer writes, then set length.
789+
/// unsafe {
790+
/// for i in 0..size {
791+
/// *x_ptr.add(i) = i as i32;
792+
/// }
793+
/// x.set_len(size);
794+
/// }
795+
/// assert_eq!(&*x, &[0,1,2,3]);
796+
/// ```
797+
#[stable(feature = "vec_as_ptr", since = "1.37.0")]
798+
#[inline]
799+
pub fn as_mut_ptr(&mut self) -> *mut T {
800+
// We shadow the slice method of the same name to avoid going through
801+
// `deref_mut`, which creates an intermediate reference.
802+
let ptr = self.buf.ptr();
803+
unsafe { assume(!ptr.is_null()); }
804+
ptr
805+
}
806+
738807
/// Forces the length of the vector to `new_len`.
739808
///
740809
/// This is a low-level operation that maintains none of the normal
@@ -1706,9 +1775,7 @@ impl<T> ops::Deref for Vec<T> {
17061775

17071776
fn deref(&self) -> &[T] {
17081777
unsafe {
1709-
let p = self.buf.ptr();
1710-
assume(!p.is_null());
1711-
slice::from_raw_parts(p, self.len)
1778+
slice::from_raw_parts(self.as_ptr(), self.len)
17121779
}
17131780
}
17141781
}
@@ -1717,9 +1784,7 @@ impl<T> ops::Deref for Vec<T> {
17171784
impl<T> ops::DerefMut for Vec<T> {
17181785
fn deref_mut(&mut self) -> &mut [T] {
17191786
unsafe {
1720-
let ptr = self.buf.ptr();
1721-
assume(!ptr.is_null());
1722-
slice::from_raw_parts_mut(ptr, self.len)
1787+
slice::from_raw_parts_mut(self.as_mut_ptr(), self.len)
17231788
}
17241789
}
17251790
}
@@ -1754,7 +1819,6 @@ impl<T> IntoIterator for Vec<T> {
17541819
fn into_iter(mut self) -> IntoIter<T> {
17551820
unsafe {
17561821
let begin = self.as_mut_ptr();
1757-
assume(!begin.is_null());
17581822
let end = if mem::size_of::<T>() == 0 {
17591823
arith_offset(begin as *const i8, self.len() as isize) as *const T
17601824
} else {

src/libcore/mem.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -982,7 +982,7 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
982982
/// out.write(vec![1, 2, 3]);
983983
/// }
984984
///
985-
/// let mut v: MaybeUninit<Vec<i32>> = MaybeUninit::uninit();
985+
/// let mut v = MaybeUninit::uninit();
986986
/// unsafe { make_vec(v.as_mut_ptr()); }
987987
/// // Now we know `v` is initialized! This also makes sure the vector gets
988988
/// // properly dropped.
@@ -1071,7 +1071,7 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
10711071
/// optimizations, potentially resulting in a larger size:
10721072
///
10731073
/// ```rust
1074-
/// # use std::mem::{MaybeUninit, size_of, align_of};
1074+
/// # use std::mem::{MaybeUninit, size_of};
10751075
/// assert_eq!(size_of::<Option<bool>>(), 1);
10761076
/// assert_eq!(size_of::<Option<MaybeUninit<bool>>>(), 2);
10771077
/// ```

src/librustc/hir/map/definitions.rs

+1-25
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use crate::ich::Fingerprint;
1010
use rustc_data_structures::fx::FxHashMap;
1111
use rustc_data_structures::indexed_vec::{IndexVec};
1212
use rustc_data_structures::stable_hasher::StableHasher;
13-
use serialize::{Encodable, Decodable, Encoder, Decoder};
1413
use crate::session::CrateDisambiguator;
1514
use std::borrow::Borrow;
1615
use std::fmt::Write;
@@ -25,14 +24,13 @@ use crate::util::nodemap::NodeMap;
2524
/// Internally the DefPathTable holds a tree of DefKeys, where each DefKey
2625
/// stores the DefIndex of its parent.
2726
/// There is one DefPathTable for each crate.
28-
#[derive(Clone, Default)]
27+
#[derive(Clone, Default, RustcDecodable, RustcEncodable)]
2928
pub struct DefPathTable {
3029
index_to_key: Vec<DefKey>,
3130
def_path_hashes: Vec<DefPathHash>,
3231
}
3332

3433
impl DefPathTable {
35-
3634
fn allocate(&mut self,
3735
key: DefKey,
3836
def_path_hash: DefPathHash)
@@ -86,28 +84,6 @@ impl DefPathTable {
8684
}
8785
}
8886

89-
90-
impl Encodable for DefPathTable {
91-
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
92-
// Index to key
93-
self.index_to_key.encode(s)?;
94-
95-
// DefPath hashes
96-
self.def_path_hashes.encode(s)?;
97-
98-
Ok(())
99-
}
100-
}
101-
102-
impl Decodable for DefPathTable {
103-
fn decode<D: Decoder>(d: &mut D) -> Result<DefPathTable, D::Error> {
104-
Ok(DefPathTable {
105-
index_to_key: Decodable::decode(d)?,
106-
def_path_hashes : Decodable::decode(d)?,
107-
})
108-
}
109-
}
110-
11187
/// The definition table containing node definitions.
11288
/// It holds the `DefPathTable` for local `DefId`s/`DefPath`s and it also stores a
11389
/// mapping from `NodeId`s to local `DefId`s.

src/librustc_mir/borrow_check/conflict_errors.rs

+11-13
Original file line numberDiff line numberDiff line change
@@ -158,18 +158,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
158158
span,
159159
format!("value moved{} here, in previous iteration of loop", move_msg),
160160
);
161-
if Some(CompilerDesugaringKind::ForLoop) == span.compiler_desugaring_kind() {
162-
if let Ok(snippet) = self.infcx.tcx.sess.source_map()
163-
.span_to_snippet(span)
164-
{
165-
err.span_suggestion(
166-
move_span,
167-
"consider borrowing this to avoid moving it into the for loop",
168-
format!("&{}", snippet),
169-
Applicability::MaybeIncorrect,
170-
);
171-
}
172-
}
173161
is_loop_move = true;
174162
} else if move_site.traversed_back_edge {
175163
err.span_label(
@@ -185,7 +173,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
185173
&mut err,
186174
format!("variable moved due to use{}", move_spans.describe()),
187175
);
188-
};
176+
}
177+
if Some(CompilerDesugaringKind::ForLoop) == move_span.compiler_desugaring_kind() {
178+
if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
179+
err.span_suggestion(
180+
move_span,
181+
"consider borrowing to avoid moving into the for loop",
182+
format!("&{}", snippet),
183+
Applicability::MaybeIncorrect,
184+
);
185+
}
186+
}
189187
}
190188

191189
use_spans.var_span_label(

src/librustc_mir/interpret/operand.rs

+2
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
475475
PlaceBase::Local(mir::RETURN_PLACE) => return err!(ReadFromReturnPointer),
476476
PlaceBase::Local(local) => {
477477
// FIXME use place_projection.is_empty() when is available
478+
// Do not use the layout passed in as argument if the base we are looking at
479+
// here is not the entire place.
478480
let layout = if let Place::Base(_) = mir_place {
479481
layout
480482
} else {

src/librustc_mir/transform/const_prop.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
295295
}
296296

297297
fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
298+
trace!("eval_place(place={:?})", place);
298299
match *place {
299300
Place::Base(PlaceBase::Local(loc)) => self.places[loc].clone(),
300301
Place::Projection(ref proj) => match proj.elem {
@@ -516,6 +517,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
516517
}
517518

518519
fn replace_with_const(&self, rval: &mut Rvalue<'tcx>, value: Const<'tcx>, span: Span) {
520+
trace!("attepting to replace {:?} with {:?}", rval, value);
519521
self.ecx.validate_operand(
520522
value,
521523
vec![],
@@ -579,6 +581,10 @@ impl CanConstProp {
579581
// FIXME(oli-obk): lint variables until they are used in a condition
580582
// FIXME(oli-obk): lint if return value is constant
581583
*val = mir.local_kind(local) == LocalKind::Temp;
584+
585+
if !*val {
586+
trace!("local {:?} can't be propagated because it's not a temporary", local);
587+
}
582588
}
583589
cpv.visit_mir(mir);
584590
cpv.can_const_prop
@@ -598,6 +604,7 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
598604
// FIXME(oli-obk): we could be more powerful here, if the multiple writes
599605
// only occur in independent execution paths
600606
MutatingUse(MutatingUseContext::Store) => if self.found_assignment[local] {
607+
trace!("local {:?} can't be propagated because of multiple assignments", local);
601608
self.can_const_prop[local] = false;
602609
} else {
603610
self.found_assignment[local] = true
@@ -609,7 +616,10 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
609616
NonMutatingUse(NonMutatingUseContext::Projection) |
610617
MutatingUse(MutatingUseContext::Projection) |
611618
NonUse(_) => {},
612-
_ => self.can_const_prop[local] = false,
619+
_ => {
620+
trace!("local {:?} can't be propagaged because it's used: {:?}", local, context);
621+
self.can_const_prop[local] = false;
622+
},
613623
}
614624
}
615625
}

0 commit comments

Comments
 (0)