Skip to content

Commit 413a129

Browse files
committed
Auto merge of #71467 - Dylan-DPC:rollup-d1os8ug, r=Dylan-DPC
Rollup of 6 pull requests Successful merges: - #71005 (Reading from the return place is fine) - #71198 (Const check/promotion cleanup and sanity assertion) - #71396 (Improve E0308 error message wording again) - #71452 (Remove outdated reference to interpreter snapshotting) - #71454 (Inline some function docs in `core::ptr`) - #71461 (Improve E0567 explanation) Failed merges: r? @ghost
2 parents 66f7a5d + 47e2687 commit 413a129

File tree

28 files changed

+307
-363
lines changed

28 files changed

+307
-363
lines changed

src/libcore/ptr/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,15 @@ use crate::intrinsics::{self, is_aligned_and_not_null, is_nonoverlapping};
7676
use crate::mem::{self, MaybeUninit};
7777

7878
#[stable(feature = "rust1", since = "1.0.0")]
79+
#[doc(inline)]
7980
pub use crate::intrinsics::copy_nonoverlapping;
8081

8182
#[stable(feature = "rust1", since = "1.0.0")]
83+
#[doc(inline)]
8284
pub use crate::intrinsics::copy;
8385

8486
#[stable(feature = "rust1", since = "1.0.0")]
87+
#[doc(inline)]
8588
pub use crate::intrinsics::write_bytes;
8689

8790
mod non_null;

src/librustc_error_codes/error_codes/E0308.md

+4-5
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ let x: i32 = "I am not a number!";
1212
// type `i32` assigned to variable `x`
1313
```
1414

15-
This error occurs when the compiler was unable to infer the concrete type of a
16-
variable. It can happen in several cases, the most common being a mismatch
17-
between the type that the compiler inferred for a variable based on its
18-
initializing expression, on the one hand, and the type the author explicitly
19-
assigned to the variable, on the other hand.
15+
This error occurs when the compiler is unable to infer the concrete type of a
16+
variable. It can occur in several cases, the most common being a mismatch
17+
between two types: the type the author explicitly assigned, and the type the
18+
compiler inferred.

src/librustc_error_codes/error_codes/E0567.md

+2-4
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ Erroneous code example:
66
#![feature(optin_builtin_traits)]
77
88
auto trait Generic<T> {} // error!
9-
10-
fn main() {}
9+
# fn main() {}
1110
```
1211

1312
Since an auto trait is implemented on all existing types, the
@@ -20,6 +19,5 @@ To fix this issue, just remove the generics:
2019
#![feature(optin_builtin_traits)]
2120
2221
auto trait Generic {} // ok!
23-
24-
fn main() {}
22+
# fn main() {}
2523
```

src/librustc_middle/mir/interpret/allocation.rs

-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ use super::{
1313
read_target_uint, write_target_uint, AllocId, InterpResult, Pointer, Scalar, ScalarMaybeUndef,
1414
};
1515

16-
// NOTE: When adding new fields, make sure to adjust the `Snapshot` impl in
17-
// `src/librustc_mir/interpret/snapshot.rs`.
1816
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
1917
#[derive(HashStable)]
2018
pub struct Allocation<Tag = (), Extra = ()> {

src/librustc_middle/mir/interpret/error.rs

-3
Original file line numberDiff line numberDiff line change
@@ -361,8 +361,6 @@ pub enum UndefinedBehaviorInfo {
361361
InvalidUndefBytes(Option<Pointer>),
362362
/// Working with a local that is not currently live.
363363
DeadLocal,
364-
/// Trying to read from the return place of a function.
365-
ReadFromReturnPlace,
366364
}
367365

368366
impl fmt::Debug for UndefinedBehaviorInfo {
@@ -424,7 +422,6 @@ impl fmt::Debug for UndefinedBehaviorInfo {
424422
"using uninitialized data, but this operation requires initialized memory"
425423
),
426424
DeadLocal => write!(f, "accessing a dead local variable"),
427-
ReadFromReturnPlace => write!(f, "reading from return place"),
428425
}
429426
}
430427
}

src/librustc_middle/mir/interpret/value.rs

-5
Original file line numberDiff line numberDiff line change
@@ -188,11 +188,6 @@ impl<'tcx, Tag> Scalar<Tag> {
188188
}
189189
}
190190

191-
#[inline]
192-
pub fn null_ptr(cx: &impl HasDataLayout) -> Self {
193-
Scalar::Raw { data: 0, size: cx.data_layout().pointer_size.bytes() as u8 }
194-
}
195-
196191
#[inline]
197192
pub fn zst() -> Self {
198193
Scalar::Raw { data: 0, size: 0 }

src/librustc_mir/borrow_check/type_check/mod.rs

+11-5
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,10 @@ use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligations}
4242
use crate::dataflow::move_paths::MoveData;
4343
use crate::dataflow::MaybeInitializedPlaces;
4444
use crate::dataflow::ResultsCursor;
45-
use crate::transform::promote_consts::should_suggest_const_in_array_repeat_expressions_attribute;
45+
use crate::transform::{
46+
check_consts::ConstCx,
47+
promote_consts::should_suggest_const_in_array_repeat_expressions_attribute,
48+
};
4649

4750
use crate::borrow_check::{
4851
borrow_set::BorrowSet,
@@ -1984,14 +1987,17 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
19841987
let span = body.source_info(location).span;
19851988
let ty = operand.ty(body, tcx);
19861989
if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty, span) {
1990+
let ccx = ConstCx::new_with_param_env(
1991+
tcx,
1992+
self.mir_def_id,
1993+
body,
1994+
self.param_env,
1995+
);
19871996
// To determine if `const_in_array_repeat_expressions` feature gate should
19881997
// be mentioned, need to check if the rvalue is promotable.
19891998
let should_suggest =
19901999
should_suggest_const_in_array_repeat_expressions_attribute(
1991-
tcx,
1992-
self.mir_def_id,
1993-
body,
1994-
operand,
2000+
&ccx, operand,
19952001
);
19962002
debug!("check_rvalue: should_suggest={:?}", should_suggest);
19972003

src/librustc_mir/interpret/eval_context.rs

+31-45
Original file line numberDiff line numberDiff line change
@@ -628,35 +628,30 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
628628
let frame = M::init_frame_extra(self, pre_frame)?;
629629
self.stack_mut().push(frame);
630630

631-
// don't allocate at all for trivial constants
632-
if body.local_decls.len() > 1 {
633-
// Locals are initially uninitialized.
634-
let dummy = LocalState { value: LocalValue::Uninitialized, layout: Cell::new(None) };
635-
let mut locals = IndexVec::from_elem(dummy, &body.local_decls);
636-
// Return place is handled specially by the `eval_place` functions, and the
637-
// entry in `locals` should never be used. Make it dead, to be sure.
638-
locals[mir::RETURN_PLACE].value = LocalValue::Dead;
639-
// Now mark those locals as dead that we do not want to initialize
640-
match self.tcx.def_kind(instance.def_id()) {
641-
// statics and constants don't have `Storage*` statements, no need to look for them
642-
//
643-
// FIXME: The above is likely untrue. See
644-
// <https://github.com/rust-lang/rust/pull/70004#issuecomment-602022110>. Is it
645-
// okay to ignore `StorageDead`/`StorageLive` annotations during CTFE?
646-
Some(DefKind::Static | DefKind::Const | DefKind::AssocConst) => {}
647-
_ => {
648-
// Mark locals that use `Storage*` annotations as dead on function entry.
649-
let always_live = AlwaysLiveLocals::new(self.body());
650-
for local in locals.indices() {
651-
if !always_live.contains(local) {
652-
locals[local].value = LocalValue::Dead;
653-
}
631+
// Locals are initially uninitialized.
632+
let dummy = LocalState { value: LocalValue::Uninitialized, layout: Cell::new(None) };
633+
let mut locals = IndexVec::from_elem(dummy, &body.local_decls);
634+
635+
// Now mark those locals as dead that we do not want to initialize
636+
match self.tcx.def_kind(instance.def_id()) {
637+
// statics and constants don't have `Storage*` statements, no need to look for them
638+
//
639+
// FIXME: The above is likely untrue. See
640+
// <https://github.com/rust-lang/rust/pull/70004#issuecomment-602022110>. Is it
641+
// okay to ignore `StorageDead`/`StorageLive` annotations during CTFE?
642+
Some(DefKind::Static | DefKind::Const | DefKind::AssocConst) => {}
643+
_ => {
644+
// Mark locals that use `Storage*` annotations as dead on function entry.
645+
let always_live = AlwaysLiveLocals::new(self.body());
646+
for local in locals.indices() {
647+
if !always_live.contains(local) {
648+
locals[local].value = LocalValue::Dead;
654649
}
655650
}
656651
}
657-
// done
658-
self.frame_mut().locals = locals;
659652
}
653+
// done
654+
self.frame_mut().locals = locals;
660655

661656
M::after_stack_push(self)?;
662657
info!("ENTERING({}) {}", self.frame_idx(), self.frame().instance);
@@ -734,6 +729,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
734729
let frame =
735730
self.stack_mut().pop().expect("tried to pop a stack frame, but there were none");
736731

732+
if !unwinding {
733+
// Copy the return value to the caller's stack frame.
734+
if let Some(return_place) = frame.return_place {
735+
let op = self.access_local(&frame, mir::RETURN_PLACE, None)?;
736+
self.copy_op_transmute(op, return_place)?;
737+
self.dump_place(*return_place);
738+
} else {
739+
throw_ub!(Unreachable);
740+
}
741+
}
742+
737743
// Now where do we jump next?
738744

739745
// Usually we want to clean up (deallocate locals), but in a few rare cases we don't.
@@ -759,7 +765,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
759765
self.deallocate_local(local.value)?;
760766
}
761767

762-
let return_place = frame.return_place;
763768
if M::after_stack_pop(self, frame, unwinding)? == StackPopJump::NoJump {
764769
// The hook already did everything.
765770
// We want to skip the `info!` below, hence early return.
@@ -772,25 +777,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
772777
self.unwind_to_block(unwind);
773778
} else {
774779
// Follow the normal return edge.
775-
// Validate the return value. Do this after deallocating so that we catch dangling
776-
// references.
777-
if let Some(return_place) = return_place {
778-
if M::enforce_validity(self) {
779-
// Data got changed, better make sure it matches the type!
780-
// It is still possible that the return place held invalid data while
781-
// the function is running, but that's okay because nobody could have
782-
// accessed that same data from the "outside" to observe any broken
783-
// invariant -- that is, unless a function somehow has a ptr to
784-
// its return place... but the way MIR is currently generated, the
785-
// return place is always a local and then this cannot happen.
786-
self.validate_operand(self.place_to_op(return_place)?)?;
787-
}
788-
} else {
789-
// Uh, that shouldn't happen... the function did not intend to return
790-
throw_ub!(Unreachable);
791-
}
792-
793-
// Jump to new block -- *after* validation so that the spans make more sense.
794780
if let Some(ret) = next_block {
795781
self.return_to_block(ret)?;
796782
}

src/librustc_mir/interpret/operand.rs

+5-11
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
419419
local: mir::Local,
420420
layout: Option<TyAndLayout<'tcx>>,
421421
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
422-
assert_ne!(local, mir::RETURN_PLACE);
423422
let layout = self.layout_of_local(frame, local, layout)?;
424423
let op = if layout.is_zst() {
425424
// Do not read from ZST, they might not be initialized
@@ -454,16 +453,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
454453
place: mir::Place<'tcx>,
455454
layout: Option<TyAndLayout<'tcx>>,
456455
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
457-
let base_op = match place.local {
458-
mir::RETURN_PLACE => throw_ub!(ReadFromReturnPlace),
459-
local => {
460-
// Do not use the layout passed in as argument if the base we are looking at
461-
// here is not the entire place.
462-
let layout = if place.projection.is_empty() { layout } else { None };
463-
464-
self.access_local(self.frame(), local, layout)?
465-
}
466-
};
456+
// Do not use the layout passed in as argument if the base we are looking at
457+
// here is not the entire place.
458+
let layout = if place.projection.is_empty() { layout } else { None };
459+
460+
let base_op = self.access_local(self.frame(), place.local, layout)?;
467461

468462
let op = place
469463
.projection

src/librustc_mir/interpret/place.rs

+4-41
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,6 @@ impl<Tag> MemPlace<Tag> {
135135
MemPlace { ptr, align, meta: MemPlaceMeta::None }
136136
}
137137

138-
/// Produces a Place that will error if attempted to be read from or written to
139-
#[inline(always)]
140-
fn null(cx: &impl HasDataLayout) -> Self {
141-
Self::from_scalar_ptr(Scalar::null_ptr(cx), Align::from_bytes(1).unwrap())
142-
}
143-
144138
#[inline(always)]
145139
pub fn from_ptr(ptr: Pointer<Tag>, align: Align) -> Self {
146140
Self::from_scalar_ptr(ptr.into(), align)
@@ -260,12 +254,6 @@ impl<'tcx, Tag: ::std::fmt::Debug + Copy> OpTy<'tcx, Tag> {
260254
}
261255

262256
impl<Tag: ::std::fmt::Debug> Place<Tag> {
263-
/// Produces a Place that will error if attempted to be read from or written to
264-
#[inline(always)]
265-
fn null(cx: &impl HasDataLayout) -> Self {
266-
Place::Ptr(MemPlace::null(cx))
267-
}
268-
269257
#[inline]
270258
pub fn assert_mem_place(self) -> MemPlace<Tag> {
271259
match self {
@@ -641,35 +629,10 @@ where
641629
&mut self,
642630
place: mir::Place<'tcx>,
643631
) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
644-
let mut place_ty = match place.local {
645-
mir::RETURN_PLACE => {
646-
// `return_place` has the *caller* layout, but we want to use our
647-
// `layout to verify our assumption. The caller will validate
648-
// their layout on return.
649-
PlaceTy {
650-
place: match self.frame().return_place {
651-
Some(p) => *p,
652-
// Even if we don't have a return place, we sometimes need to
653-
// create this place, but any attempt to read from / write to it
654-
// (even a ZST read/write) needs to error, so let us make this
655-
// a NULL place.
656-
//
657-
// FIXME: Ideally we'd make sure that the place projections also
658-
// bail out.
659-
None => Place::null(&*self),
660-
},
661-
layout: self.layout_of(
662-
self.subst_from_current_frame_and_normalize_erasing_regions(
663-
self.frame().body.return_ty(),
664-
),
665-
)?,
666-
}
667-
}
668-
local => PlaceTy {
669-
// This works even for dead/uninitialized locals; we check further when writing
670-
place: Place::Local { frame: self.frame_idx(), local },
671-
layout: self.layout_of_local(self.frame(), local, None)?,
672-
},
632+
let mut place_ty = PlaceTy {
633+
// This works even for dead/uninitialized locals; we check further when writing
634+
place: Place::Local { frame: self.frame_idx(), local: place.local },
635+
layout: self.layout_of_local(self.frame(), place.local, None)?,
673636
};
674637

675638
for elem in place.projection.iter() {

src/librustc_mir/interpret/terminator.rs

-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
1919
use rustc_middle::mir::TerminatorKind::*;
2020
match terminator.kind {
2121
Return => {
22-
self.frame().return_place.map(|r| self.dump_place(*r));
2322
self.pop_stack_frame(/* unwinding */ false)?
2423
}
2524

src/librustc_mir/transform/check_consts/mod.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,29 @@ pub mod validation;
2020

2121
/// Information about the item currently being const-checked, as well as a reference to the global
2222
/// context.
23-
pub struct Item<'mir, 'tcx> {
23+
pub struct ConstCx<'mir, 'tcx> {
2424
pub body: &'mir mir::Body<'tcx>,
2525
pub tcx: TyCtxt<'tcx>,
2626
pub def_id: DefId,
2727
pub param_env: ty::ParamEnv<'tcx>,
2828
pub const_kind: Option<ConstKind>,
2929
}
3030

31-
impl Item<'mir, 'tcx> {
31+
impl ConstCx<'mir, 'tcx> {
3232
pub fn new(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'mir mir::Body<'tcx>) -> Self {
3333
let param_env = tcx.param_env(def_id);
34+
Self::new_with_param_env(tcx, def_id, body, param_env)
35+
}
36+
37+
pub fn new_with_param_env(
38+
tcx: TyCtxt<'tcx>,
39+
def_id: DefId,
40+
body: &'mir mir::Body<'tcx>,
41+
param_env: ty::ParamEnv<'tcx>,
42+
) -> Self {
3443
let const_kind = ConstKind::for_item(tcx, def_id);
3544

36-
Item { body, tcx, def_id, param_env, const_kind }
45+
ConstCx { body, tcx, def_id, param_env, const_kind }
3746
}
3847

3948
/// Returns the kind of const context this `Item` represents (`const`, `static`, etc.).

0 commit comments

Comments
 (0)