about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs7
-rw-r--r--compiler/rustc_middle/src/ty/consts/valtree.rs12
-rw-r--r--compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs10
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs10
-rw-r--r--tests/crashes/131102.rs4
-rw-r--r--tests/ui/consts/bad-array-size-in-type-err.rs11
-rw-r--r--tests/ui/consts/bad-array-size-in-type-err.stderr43
7 files changed, 75 insertions, 22 deletions
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 6875532e28a..4ad5d8443b2 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -5,7 +5,6 @@ use rustc_error_messages::MultiSpan;
 use rustc_macros::HashStable;
 use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
 
-use crate::mir::interpret::Scalar;
 use crate::ty::{self, Ty, TyCtxt};
 
 mod int;
@@ -231,12 +230,6 @@ impl<'tcx> Const<'tcx> {
     }
 
     #[inline]
-    pub fn try_to_scalar(self) -> Option<(Scalar, Ty<'tcx>)> {
-        let cv = self.try_to_value()?;
-        Some((cv.valtree.try_to_scalar()?, cv.ty))
-    }
-
-    #[inline]
     pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
         self.try_to_value()?.try_to_target_usize(tcx)
     }
diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs
index 425b68a951c..d914b7576dc 100644
--- a/compiler/rustc_middle/src/ty/consts/valtree.rs
+++ b/compiler/rustc_middle/src/ty/consts/valtree.rs
@@ -117,9 +117,13 @@ pub struct Value<'tcx> {
 impl<'tcx> Value<'tcx> {
     /// Attempts to extract the raw bits from the constant.
     ///
-    /// Fails if the value can't be represented as bits (e.g. because it is an aggregate).
+    /// Fails if the value can't be represented as bits (e.g. because it is a reference
+    /// or an aggregate).
     #[inline]
     pub fn try_to_bits(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Option<u128> {
+        let (ty::Bool | ty::Char | ty::Uint(_) | ty::Int(_) | ty::Float(_)) = self.ty.kind() else {
+            return None;
+        };
         let scalar = self.valtree.try_to_scalar_int()?;
         let input = typing_env.with_post_analysis_normalized(tcx).as_query_input(self.ty);
         let size = tcx.layout_of(input).ok()?.size;
@@ -127,10 +131,16 @@ impl<'tcx> Value<'tcx> {
     }
 
     pub fn try_to_bool(self) -> Option<bool> {
+        if !self.ty.is_bool() {
+            return None;
+        }
         self.valtree.try_to_scalar_int()?.try_to_bool().ok()
     }
 
     pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
+        if !self.ty.is_usize() {
+            return None;
+        }
         self.valtree.try_to_scalar_int().map(|s| s.to_target_usize(tcx))
     }
 }
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
index 9c6186d6882..b711c238d59 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
@@ -51,8 +51,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for TransformTy<'tcx> {
     // Transforms a ty:Ty for being encoded and used in the substitution dictionary.
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         match t.kind() {
-            ty::Array(..)
-            | ty::Closure(..)
+            ty::Closure(..)
             | ty::Coroutine(..)
             | ty::CoroutineClosure(..)
             | ty::CoroutineWitness(..)
@@ -67,6 +66,13 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for TransformTy<'tcx> {
             | ty::Tuple(..)
             | ty::UnsafeBinder(_) => t.super_fold_with(self),
 
+            // Don't transform the type of the array length and keep it as `usize`.
+            // This is required for `try_to_target_usize` to work correctly.
+            &ty::Array(inner, len) => {
+                let inner = self.fold_ty(inner);
+                Ty::new_array_with_const_len(self.tcx, inner, len)
+            }
+
             ty::Bool => {
                 if self.options.contains(EncodeTyOptions::NORMALIZE_INTEGERS) {
                     // Note: on all platforms that Rust's currently supports, its size and alignment
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
index 9eacd377361..117b6a76425 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
@@ -2023,14 +2023,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             _ => None,
         };
         if let Some(tykind) = tykind
-            && let hir::TyKind::Array(_, length) = tykind
-            && let Some((scalar, ty)) = sz.found.try_to_scalar()
-            && ty == self.tcx.types.usize
+            && let hir::TyKind::Array(_, length_arg) = tykind
+            && let Some(length_val) = sz.found.try_to_target_usize(self.tcx)
         {
-            let span = length.span();
             Some(TypeErrorAdditionalDiags::ConsiderSpecifyingLength {
-                span,
-                length: scalar.to_target_usize(&self.tcx).unwrap(),
+                span: length_arg.span(),
+                length: length_val,
             })
         } else {
             None
diff --git a/tests/crashes/131102.rs b/tests/crashes/131102.rs
deleted file mode 100644
index 12b35f8d1b2..00000000000
--- a/tests/crashes/131102.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-//@ known-bug: #131102
-pub struct Blorb<const N: u16>([String; N]);
-pub struct Wrap(Blorb<0>);
-pub const fn i(_: Wrap) {}
diff --git a/tests/ui/consts/bad-array-size-in-type-err.rs b/tests/ui/consts/bad-array-size-in-type-err.rs
index cb02ad3205d..0490a9d3620 100644
--- a/tests/ui/consts/bad-array-size-in-type-err.rs
+++ b/tests/ui/consts/bad-array-size-in-type-err.rs
@@ -8,3 +8,14 @@ fn main() {
     //~^ ERROR mismatched types
     //~| ERROR the constant `2` is not of type `usize`
 }
+
+fn iter(val: BadArraySize::<2>) {
+    for _ in val.arr {}
+    //~^ ERROR the constant `2` is not of type `usize`
+    //~| ERROR `[i32; 2]` is not an iterator
+}
+
+// issue #131102
+pub struct Blorb<const N: u16>([String; N]); //~ ERROR the constant `N` is not of type `usize`
+pub struct Wrap(Blorb<0>);
+pub const fn i(_: Wrap) {} //~ ERROR destructor of `Wrap` cannot be evaluated at compile-time
diff --git a/tests/ui/consts/bad-array-size-in-type-err.stderr b/tests/ui/consts/bad-array-size-in-type-err.stderr
index c3ff216432e..84e16f8d931 100644
--- a/tests/ui/consts/bad-array-size-in-type-err.stderr
+++ b/tests/ui/consts/bad-array-size-in-type-err.stderr
@@ -6,6 +6,14 @@ LL |     arr: [i32; N],
    |
    = note: the length of array `[i32; N]` must be type `usize`
 
+error: the constant `N` is not of type `usize`
+  --> $DIR/bad-array-size-in-type-err.rs:19:32
+   |
+LL | pub struct Blorb<const N: u16>([String; N]);
+   |                                ^^^^^^^^^^^ expected `usize`, found `u16`
+   |
+   = note: the length of array `[String; N]` must be type `usize`
+
 error[E0308]: mismatched types
   --> $DIR/bad-array-size-in-type-err.rs:7:38
    |
@@ -20,6 +28,37 @@ LL |     let _ = BadArraySize::<2> { arr: [0, 0, 0] };
    |
    = note: the length of array `[i32; 2]` must be type `usize`
 
-error: aborting due to 3 previous errors
+error: the constant `2` is not of type `usize`
+  --> $DIR/bad-array-size-in-type-err.rs:13:14
+   |
+LL |     for _ in val.arr {}
+   |              ^^^^^^^ expected `usize`, found `u8`
+   |
+   = note: the length of array `[i32; 2]` must be type `usize`
+
+error[E0277]: `[i32; 2]` is not an iterator
+  --> $DIR/bad-array-size-in-type-err.rs:13:14
+   |
+LL |     for _ in val.arr {}
+   |              ^^^^^^^ `[i32; 2]` is not an iterator; try calling `.into_iter()` or `.iter()`
+   |
+   = help: the trait `IntoIterator` is not implemented for `[i32; 2]`
+   = help: the following other types implement trait `IntoIterator`:
+             &[T; N]
+             &[T]
+             &mut [T; N]
+             &mut [T]
+             [T; N]
+
+error[E0493]: destructor of `Wrap` cannot be evaluated at compile-time
+  --> $DIR/bad-array-size-in-type-err.rs:21:16
+   |
+LL | pub const fn i(_: Wrap) {}
+   |                ^         - value is dropped here
+   |                |
+   |                the destructor for this type cannot be evaluated in constant functions
+
+error: aborting due to 7 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0277, E0308, E0493.
+For more information about an error, try `rustc --explain E0277`.