about summary refs log tree commit diff
path: root/compiler/rustc_const_eval/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-06-27 23:15:35 +0000
committerbors <bors@rust-lang.org>2025-06-27 23:15:35 +0000
commitd41e12f1f4e4884c356f319b881921aa37040de5 (patch)
tree031a06c68e6bd4691cd0b14ede842ad4561b48dc /compiler/rustc_const_eval/src
parentbdaba05a953eb5abeba0011cdda2560d157aed2e (diff)
parent0e79b8914dd3cc372d34968b24fd05132a4a7f1f (diff)
downloadrust-d41e12f1f4e4884c356f319b881921aa37040de5.tar.gz
rust-d41e12f1f4e4884c356f319b881921aa37040de5.zip
Auto merge of #143116 - matthiaskrgr:rollup-zy9ez06, r=matthiaskrgr
Rollup of 9 pull requests

Successful merges:

 - rust-lang/rust#139858 (New const traits syntax)
 - rust-lang/rust#140809 (Reduce special casing for the panic runtime)
 - rust-lang/rust#142730 (suggest declaring modules when file found but module not defined)
 - rust-lang/rust#142806 (Normalize before computing ConstArgHasType goal in new solver)
 - rust-lang/rust#143046 (const validation: properly ignore zero-sized UnsafeCell)
 - rust-lang/rust#143092 (const checks for lifetime-extended temporaries: avoid 'top-level scope' terminology)
 - rust-lang/rust#143096 (tag_for_variant: properly pass TypingEnv)
 - rust-lang/rust#143104 (hir_analysis: prohibit `dyn PointeeSized`)
 - rust-lang/rust#143106 (gce: don't ICE on non-local const)

Failed merges:

 - rust-lang/rust#143036 (Remove support for `dyn*` from the compiler)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler/rustc_const_eval/src')
-rw-r--r--compiler/rustc_const_eval/src/check_consts/check.rs2
-rw-r--r--compiler/rustc_const_eval/src/check_consts/ops.rs15
-rw-r--r--compiler/rustc_const_eval/src/check_consts/qualifs.rs12
-rw-r--r--compiler/rustc_const_eval/src/const_eval/mod.rs13
-rw-r--r--compiler/rustc_const_eval/src/errors.rs13
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs10
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs10
-rw-r--r--compiler/rustc_const_eval/src/interpret/projection.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs15
10 files changed, 43 insertions, 51 deletions
diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs
index c151e8acf92..c1d91f98957 100644
--- a/compiler/rustc_const_eval/src/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/check_consts/check.rs
@@ -421,7 +421,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
             Some(ConstConditionsHold::Yes)
         } else {
             tcx.dcx()
-                .span_delayed_bug(call_span, "this should have reported a ~const error in HIR");
+                .span_delayed_bug(call_span, "this should have reported a [const] error in HIR");
             Some(ConstConditionsHold::No)
         }
     }
diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs
index 02edff8f632..b2e0577cc82 100644
--- a/compiler/rustc_const_eval/src/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/check_consts/ops.rs
@@ -149,7 +149,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
                         debug!(?param_ty);
                         if let Some(generics) = tcx.hir_node_by_def_id(caller).generics() {
                             let constraint = with_no_trimmed_paths!(format!(
-                                "~const {}",
+                                "[const] {}",
                                 trait_ref.print_trait_sugared(),
                             ));
                             suggest_constraining_type_param(
@@ -567,12 +567,7 @@ impl<'tcx> NonConstOp<'tcx> for EscapingCellBorrow {
         DiagImportance::Secondary
     }
     fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
-        ccx.dcx().create_err(errors::InteriorMutableBorrowEscaping {
-            span,
-            opt_help: matches!(ccx.const_kind(), hir::ConstContext::Static(_)),
-            kind: ccx.const_kind(),
-            teach: ccx.tcx.sess.teach(E0492),
-        })
+        ccx.dcx().create_err(errors::InteriorMutableBorrowEscaping { span, kind: ccx.const_kind() })
     }
 }
 
@@ -594,11 +589,7 @@ impl<'tcx> NonConstOp<'tcx> for EscapingMutBorrow {
     }
 
     fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
-        ccx.dcx().create_err(errors::MutableBorrowEscaping {
-            span,
-            kind: ccx.const_kind(),
-            teach: ccx.tcx.sess.teach(E0764),
-        })
+        ccx.dcx().create_err(errors::MutableBorrowEscaping { span, kind: ccx.const_kind() })
     }
 }
 
diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs
index c1a37ab6a83..166491b47a1 100644
--- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs
@@ -170,14 +170,14 @@ impl Qualif for NeedsNonConstDrop {
 
     #[instrument(level = "trace", skip(cx), ret)]
     fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
-        // If this doesn't need drop at all, then don't select `~const Destruct`.
+        // If this doesn't need drop at all, then don't select `[const] Destruct`.
         if !ty.needs_drop(cx.tcx, cx.typing_env) {
             return false;
         }
 
-        // We check that the type is `~const Destruct` since that will verify that
-        // the type is both `~const Drop` (if a drop impl exists for the adt), *and*
-        // that the components of this type are also `~const Destruct`. This
+        // We check that the type is `[const] Destruct` since that will verify that
+        // the type is both `[const] Drop` (if a drop impl exists for the adt), *and*
+        // that the components of this type are also `[const] Destruct`. This
         // amounts to verifying that there are no values in this ADT that may have
         // a non-const drop.
         let destruct_def_id = cx.tcx.require_lang_item(LangItem::Destruct, cx.body.span);
@@ -203,9 +203,9 @@ impl Qualif for NeedsNonConstDrop {
     fn is_structural_in_adt_value<'tcx>(cx: &ConstCx<'_, 'tcx>, adt: AdtDef<'tcx>) -> bool {
         // As soon as an ADT has a destructor, then the drop becomes non-structural
         // in its value since:
-        // 1. The destructor may have `~const` bounds which are not present on the type.
+        // 1. The destructor may have `[const]` bounds which are not present on the type.
         //   Someone needs to check that those are satisfied.
-        //   While this could be instead satisfied by checking that the `~const Drop`
+        //   While this could be instead satisfied by checking that the `[const] Drop`
         //   impl holds (i.e. replicating part of the `in_any_value_of_ty` logic above),
         //   even in this case, we have another problem, which is,
         // 2. The destructor may *modify* the operand being dropped, so even if we
diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs
index 2aaf718c733..d95d552d7d5 100644
--- a/compiler/rustc_const_eval/src/const_eval/mod.rs
+++ b/compiler/rustc_const_eval/src/const_eval/mod.rs
@@ -66,18 +66,13 @@ pub(crate) fn try_destructure_mir_constant_for_user_output<'tcx>(
 #[instrument(skip(tcx), level = "debug")]
 pub fn tag_for_variant_provider<'tcx>(
     tcx: TyCtxt<'tcx>,
-    (ty, variant_index): (Ty<'tcx>, VariantIdx),
+    key: ty::PseudoCanonicalInput<'tcx, (Ty<'tcx>, VariantIdx)>,
 ) -> Option<ty::ScalarInt> {
+    let (ty, variant_index) = key.value;
     assert!(ty.is_enum());
 
-    // FIXME: This uses an empty `TypingEnv` even though
-    // it may be used by a generic CTFE.
-    let ecx = InterpCx::new(
-        tcx,
-        ty.default_span(tcx),
-        ty::TypingEnv::fully_monomorphized(),
-        crate::const_eval::DummyMachine,
-    );
+    let ecx =
+        InterpCx::new(tcx, ty.default_span(tcx), key.typing_env, crate::const_eval::DummyMachine);
 
     let layout = ecx.layout_of(ty).unwrap();
     ecx.tag_for_variant(layout, variant_index).unwrap().map(|(tag, _tag_field)| tag)
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index b2c3103c34a..14abdd8c98c 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -151,12 +151,14 @@ pub(crate) struct UnmarkedIntrinsicExposed {
 
 #[derive(Diagnostic)]
 #[diag(const_eval_mutable_borrow_escaping, code = E0764)]
+#[note]
+#[note(const_eval_note2)]
+#[help]
 pub(crate) struct MutableBorrowEscaping {
     #[primary_span]
+    #[label]
     pub span: Span,
     pub kind: ConstContext,
-    #[note(const_eval_teach_note)]
-    pub teach: bool,
 }
 
 #[derive(Diagnostic)]
@@ -217,15 +219,14 @@ pub(crate) struct UnallowedInlineAsm {
 
 #[derive(Diagnostic)]
 #[diag(const_eval_interior_mutable_borrow_escaping, code = E0492)]
+#[note]
+#[note(const_eval_note2)]
+#[help]
 pub(crate) struct InteriorMutableBorrowEscaping {
     #[primary_span]
     #[label]
     pub span: Span,
-    #[help]
-    pub opt_help: bool,
     pub kind: ConstContext,
-    #[note(const_eval_teach_note)]
-    pub teach: bool,
 }
 
 #[derive(LintDiagnostic)]
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 99ca733df58..46c784b41c6 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -383,7 +383,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     /// Returns the actual dynamic size and alignment of the place at the given type.
     /// Only the "meta" (metadata) part of the place matters.
     /// This can fail to provide an answer for extern types.
-    pub(super) fn size_and_align_of(
+    pub(super) fn size_and_align_from_meta(
         &self,
         metadata: &MemPlaceMeta<M::Provenance>,
         layout: &TyAndLayout<'tcx>,
@@ -409,7 +409,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 // adjust alignment and size for them?
                 let field = layout.field(self, layout.fields.count() - 1);
                 let Some((unsized_size, mut unsized_align)) =
-                    self.size_and_align_of(metadata, &field)?
+                    self.size_and_align_from_meta(metadata, &field)?
                 else {
                     // A field with an extern type. We don't know the actual dynamic size
                     // or the alignment.
@@ -471,11 +471,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         }
     }
     #[inline]
-    pub fn size_and_align_of_mplace(
+    pub fn size_and_align_of_val(
         &self,
-        mplace: &MPlaceTy<'tcx, M::Provenance>,
+        val: &impl Projectable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, Option<(Size, Align)>> {
-        self.size_and_align_of(&mplace.meta(), &mplace.layout)
+        self.size_and_align_from_meta(&val.meta(), &val.layout())
     }
 
     /// Jump to the given block.
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 6acc89c8b02..b29c5c7c7d7 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -125,7 +125,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 // dereferenceable!
                 let place = self.ref_to_mplace(&self.read_immediate(&args[0])?)?;
                 let (size, align) = self
-                    .size_and_align_of_mplace(&place)?
+                    .size_and_align_of_val(&place)?
                     .ok_or_else(|| err_unsup_format!("`extern type` does not have known layout"))?;
 
                 let result = match intrinsic_name {
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index 88f323e0c56..3028568dd8f 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -470,7 +470,7 @@ where
     ) -> InterpResult<'tcx, Option<AllocRef<'_, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>>
     {
         let (size, _align) = self
-            .size_and_align_of_mplace(mplace)?
+            .size_and_align_of_val(mplace)?
             .unwrap_or((mplace.layout.size, mplace.layout.align.abi));
         // We check alignment separately, and *after* checking everything else.
         // If an access is both OOB and misaligned, we want to see the bounds error.
@@ -486,7 +486,7 @@ where
     ) -> InterpResult<'tcx, Option<AllocRefMut<'_, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>>
     {
         let (size, _align) = self
-            .size_and_align_of_mplace(mplace)?
+            .size_and_align_of_val(mplace)?
             .unwrap_or((mplace.layout.size, mplace.layout.align.abi));
         // We check alignment separately, and raise that error *after* checking everything else.
         // If an access is both OOB and misaligned, we want to see the bounds error.
@@ -888,11 +888,11 @@ where
         trace!("copy_op: {:?} <- {:?}: {}", *dest, src, dest.layout().ty);
 
         let dest = dest.force_mplace(self)?;
-        let Some((dest_size, _)) = self.size_and_align_of_mplace(&dest)? else {
+        let Some((dest_size, _)) = self.size_and_align_of_val(&dest)? else {
             span_bug!(self.cur_span(), "copy_op needs (dynamically) sized values")
         };
         if cfg!(debug_assertions) {
-            let src_size = self.size_and_align_of_mplace(&src)?.unwrap().0;
+            let src_size = self.size_and_align_of_val(&src)?.unwrap().0;
             assert_eq!(src_size, dest_size, "Cannot copy differently-sized data");
         } else {
             // As a cheap approximation, we compare the fixed parts of the size.
@@ -980,7 +980,7 @@ where
         kind: MemoryKind<M::MemoryKind>,
         meta: MemPlaceMeta<M::Provenance>,
     ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
-        let Some((size, align)) = self.size_and_align_of(&meta, &layout)? else {
+        let Some((size, align)) = self.size_and_align_from_meta(&meta, &layout)? else {
             span_bug!(self.cur_span(), "cannot allocate space for `extern` type, size is not known")
         };
         let ptr = self.allocate_ptr(size, align, kind, AllocInit::Uninit)?;
diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs
index a71affb1be1..306697d4ec9 100644
--- a/compiler/rustc_const_eval/src/interpret/projection.rs
+++ b/compiler/rustc_const_eval/src/interpret/projection.rs
@@ -168,7 +168,7 @@ where
             // Re-use parent metadata to determine dynamic field layout.
             // With custom DSTS, this *will* execute user-defined code, but the same
             // happens at run-time so that's okay.
-            match self.size_and_align_of(&base_meta, &field_layout)? {
+            match self.size_and_align_from_meta(&base_meta, &field_layout)? {
                 Some((_, align)) => {
                     // For packed types, we need to cap alignment.
                     let align = if let ty::Adt(def, _) = base.layout().ty.kind()
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 099ee4e16ff..998ef3729ea 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -494,7 +494,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
         }
         // Make sure this is dereferenceable and all.
         let size_and_align = try_validation!(
-            self.ecx.size_and_align_of_mplace(&place),
+            self.ecx.size_and_align_of_val(&place),
             self.path,
             Ub(InvalidMeta(msg)) => match msg {
                 InvalidMetaKind::SliceTooBig => InvalidMetaSliceTooLarge { ptr_kind },
@@ -906,7 +906,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
         let (_prov, start_offset) = mplace.ptr().into_parts();
         let (size, _align) = self
             .ecx
-            .size_and_align_of_mplace(&mplace)?
+            .size_and_align_of_val(&mplace)?
             .unwrap_or((mplace.layout.size, mplace.layout.align.abi));
         // If there is no padding at all, we can skip the rest: check for
         // a single data range covering the entire value.
@@ -1086,8 +1086,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
     ) -> InterpResult<'tcx> {
         // Special check for CTFE validation, preventing `UnsafeCell` inside unions in immutable memory.
         if self.ctfe_mode.is_some_and(|c| !c.allow_immutable_unsafe_cell()) {
-            if !val.layout.is_zst() && !val.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.typing_env)
-            {
+            // Unsized unions are currently not a thing, but let's keep this code consistent with
+            // the check in `visit_value`.
+            let zst = self.ecx.size_and_align_of_val(val)?.is_some_and(|(s, _a)| s.bytes() == 0);
+            if !zst && !val.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.typing_env) {
                 if !self.in_mutable_memory(val) {
                     throw_validation_failure!(self.path, UnsafeCellInImmutable);
                 }
@@ -1131,7 +1133,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
 
         // Special check preventing `UnsafeCell` in the inner part of constants
         if self.ctfe_mode.is_some_and(|c| !c.allow_immutable_unsafe_cell()) {
-            if !val.layout.is_zst()
+            // Exclude ZST values. We need to compute the dynamic size/align to properly
+            // handle slices and trait objects.
+            let zst = self.ecx.size_and_align_of_val(val)?.is_some_and(|(s, _a)| s.bytes() == 0);
+            if !zst
                 && let Some(def) = val.layout.ty.ty_adt_def()
                 && def.is_unsafe_cell()
             {