Skip to content

Commit 5caada9

Browse files
committedAug 17, 2024
stabilize const_mut_refs
1 parent a2a238f commit 5caada9

File tree

150 files changed

+259
-1336
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

150 files changed

+259
-1336
lines changed
 

‎compiler/rustc_const_eval/messages.ftl

-7
Original file line numberDiff line numberDiff line change
@@ -230,9 +230,6 @@ const_eval_memory_exhausted =
230230
const_eval_modified_global =
231231
modifying a static's initial value from another static's initializer
232232
233-
const_eval_mut_deref =
234-
mutation through a reference is not allowed in {const_eval_const_context}s
235-
236233
const_eval_mutable_ptr_in_final = encountered mutable pointer in final value of {const_eval_intern_kind}
237234
238235
const_eval_nested_static_in_thread_local = #[thread_local] does not support implicit nested statics, please create explicit static items and refer to them instead
@@ -363,10 +360,6 @@ const_eval_too_generic =
363360
const_eval_too_many_caller_args =
364361
calling a function with more arguments than it expected
365362
366-
const_eval_transient_mut_borrow = mutable references are not allowed in {const_eval_const_context}s
367-
368-
const_eval_transient_mut_raw = raw mutable pointers are not allowed in {const_eval_const_context}s
369-
370363
const_eval_try_block_from_output_non_const =
371364
`try` block cannot convert `{$ty}` to the result in {const_eval_const_context}s
372365
const_eval_unallowed_fn_pointer_call = function pointer calls are not allowed in {const_eval_const_context}s

‎compiler/rustc_const_eval/src/check_consts/check.rs

+6-105
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ use rustc_mir_dataflow::Analysis;
1919
use rustc_span::{sym, Span, Symbol, DUMMY_SP};
2020
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
2121
use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt};
22-
use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitor};
2322
use tracing::{debug, instrument, trace};
2423

2524
use super::ops::{self, NonConstOp, Status};
@@ -163,24 +162,6 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> {
163162
}
164163
}
165164

166-
struct LocalReturnTyVisitor<'ck, 'mir, 'tcx> {
167-
kind: LocalKind,
168-
checker: &'ck mut Checker<'mir, 'tcx>,
169-
}
170-
171-
impl<'ck, 'mir, 'tcx> TypeVisitor<TyCtxt<'tcx>> for LocalReturnTyVisitor<'ck, 'mir, 'tcx> {
172-
fn visit_ty(&mut self, t: Ty<'tcx>) {
173-
match t.kind() {
174-
ty::FnPtr(..) => {}
175-
ty::Ref(_, _, hir::Mutability::Mut) => {
176-
self.checker.check_op(ops::mut_ref::MutRef(self.kind));
177-
t.super_visit_with(self)
178-
}
179-
_ => t.super_visit_with(self),
180-
}
181-
}
182-
}
183-
184165
pub struct Checker<'mir, 'tcx> {
185166
ccx: &'mir ConstCx<'mir, 'tcx>,
186167
qualifs: Qualifs<'mir, 'tcx>,
@@ -226,25 +207,6 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
226207
return;
227208
}
228209

229-
// The local type and predicate checks are not free and only relevant for `const fn`s.
230-
if self.const_kind() == hir::ConstContext::ConstFn {
231-
for (idx, local) in body.local_decls.iter_enumerated() {
232-
// Handle the return place below.
233-
if idx == RETURN_PLACE {
234-
continue;
235-
}
236-
237-
self.span = local.source_info.span;
238-
self.check_local_or_return_ty(local.ty, idx);
239-
}
240-
241-
// impl trait is gone in MIR, so check the return type of a const fn by its signature
242-
// instead of the type of the return place.
243-
self.span = body.local_decls[RETURN_PLACE].source_info.span;
244-
let return_ty = self.ccx.fn_sig().output();
245-
self.check_local_or_return_ty(return_ty.skip_binder(), RETURN_PLACE);
246-
}
247-
248210
if !tcx.has_attr(def_id, sym::rustc_do_not_const_check) {
249211
self.visit_body(body);
250212
}
@@ -344,24 +306,16 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
344306
self.check_op_spanned(ops::StaticAccess, span)
345307
}
346308

347-
fn check_local_or_return_ty(&mut self, ty: Ty<'tcx>, local: Local) {
348-
let kind = self.body.local_kind(local);
349-
350-
let mut visitor = LocalReturnTyVisitor { kind, checker: self };
351-
352-
visitor.visit_ty(ty);
353-
}
354-
355309
fn check_mut_borrow(&mut self, place: &Place<'_>, kind: hir::BorrowKind) {
356-
match self.const_kind() {
310+
let is_transient = match self.const_kind() {
357311
// In a const fn all borrows are transient or point to the places given via
358312
// references in the arguments (so we already checked them with
359313
// TransientMutBorrow/MutBorrow as appropriate).
360314
// The borrow checker guarantees that no new non-transient borrows are created.
361315
// NOTE: Once we have heap allocations during CTFE we need to figure out
362316
// how to prevent `const fn` to create long-lived allocations that point
363317
// to mutable memory.
364-
hir::ConstContext::ConstFn => self.check_op(ops::TransientMutBorrow(kind)),
318+
hir::ConstContext::ConstFn => true,
365319
_ => {
366320
// For indirect places, we are not creating a new permanent borrow, it's just as
367321
// transient as the already existing one. For reborrowing references this is handled
@@ -375,12 +329,11 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
375329
// `StorageDead` in every control flow path leading to a `return` terminator.
376330
// The good news is that interning will detect if any unexpected mutable
377331
// pointer slips through.
378-
if place.is_indirect() || self.local_has_storage_dead(place.local) {
379-
self.check_op(ops::TransientMutBorrow(kind));
380-
} else {
381-
self.check_op(ops::MutBorrow(kind));
382-
}
332+
place.is_indirect() || self.local_has_storage_dead(place.local)
383333
}
334+
};
335+
if !is_transient {
336+
self.check_op(ops::EscapingMutBorrow(kind));
384337
}
385338
}
386339
}
@@ -626,58 +579,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
626579
}
627580
}
628581
}
629-
fn visit_projection_elem(
630-
&mut self,
631-
place_ref: PlaceRef<'tcx>,
632-
elem: PlaceElem<'tcx>,
633-
context: PlaceContext,
634-
location: Location,
635-
) {
636-
trace!(
637-
"visit_projection_elem: place_ref={:?} elem={:?} \
638-
context={:?} location={:?}",
639-
place_ref, elem, context, location,
640-
);
641-
642-
self.super_projection_elem(place_ref, elem, context, location);
643-
644-
match elem {
645-
ProjectionElem::Deref => {
646-
let base_ty = place_ref.ty(self.body, self.tcx).ty;
647-
if base_ty.is_unsafe_ptr() {
648-
if place_ref.projection.is_empty() {
649-
let decl = &self.body.local_decls[place_ref.local];
650-
// If this is a static, then this is not really dereferencing a pointer,
651-
// just directly accessing a static. That is not subject to any feature
652-
// gates (except for the one about whether statics can even be used, but
653-
// that is checked already by `visit_operand`).
654-
if let LocalInfo::StaticRef { .. } = *decl.local_info() {
655-
return;
656-
}
657-
}
658-
659-
// `*const T` is stable, `*mut T` is not
660-
if !base_ty.is_mutable_ptr() {
661-
return;
662-
}
663-
664-
self.check_op(ops::RawMutPtrDeref);
665-
}
666-
667-
if context.is_mutating_use() {
668-
self.check_op(ops::MutDeref);
669-
}
670-
}
671-
672-
ProjectionElem::ConstantIndex { .. }
673-
| ProjectionElem::Downcast(..)
674-
| ProjectionElem::OpaqueCast(..)
675-
| ProjectionElem::Subslice { .. }
676-
| ProjectionElem::Subtype(..)
677-
| ProjectionElem::Field(..)
678-
| ProjectionElem::Index(_) => {}
679-
}
680-
}
681582

682583
fn visit_source_info(&mut self, source_info: &SourceInfo) {
683584
trace!("visit_source_info: source_info={:?}", source_info);

0 commit comments

Comments
 (0)