about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/enum_clike.rs4
-rw-r--r--clippy_lints/src/matches/overlapping_arms.rs6
-rw-r--r--clippy_utils/src/consts.rs69
-rw-r--r--clippy_utils/src/lib.rs10
4 files changed, 38 insertions, 51 deletions
diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs
index 3f60e5a7c4d..646767868e2 100644
--- a/clippy_lints/src/enum_clike.rs
+++ b/clippy_lints/src/enum_clike.rs
@@ -1,7 +1,7 @@
 //! lint on C-like enums that are `repr(isize/usize)` and have values that
 //! don't fit into an `i32`
 
-use clippy_utils::consts::{miri_to_const, Constant};
+use clippy_utils::consts::{mir_to_const, Constant};
 use clippy_utils::diagnostics::span_lint;
 use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -51,7 +51,7 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant {
                         .const_eval_poly(def_id.to_def_id())
                         .ok()
                         .map(|val| rustc_middle::mir::Const::from_value(val, ty));
-                    if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx, c)) {
+                    if let Some(Constant::Int(val)) = constant.and_then(|c| mir_to_const(cx, c)) {
                         if let ty::Adt(adt, _) = ty.kind() {
                             if adt.is_enum() {
                                 ty = adt.repr().discr_type().to_ty(cx.tcx);
diff --git a/clippy_lints/src/matches/overlapping_arms.rs b/clippy_lints/src/matches/overlapping_arms.rs
index 7c0485914b8..8f0083f812c 100644
--- a/clippy_lints/src/matches/overlapping_arms.rs
+++ b/clippy_lints/src/matches/overlapping_arms.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant, constant_full_int, miri_to_const, FullInt};
+use clippy_utils::consts::{constant, constant_full_int, mir_to_const, FullInt};
 use clippy_utils::diagnostics::span_lint_and_note;
 use core::cmp::Ordering;
 use rustc_hir::{Arm, Expr, PatKind, RangeEnd};
@@ -37,14 +37,14 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
                         Some(lhs) => constant(cx, cx.typeck_results(), lhs)?,
                         None => {
                             let min_val_const = ty.numeric_min_val(cx.tcx)?;
-                            miri_to_const(cx, mir::Const::from_ty_const(min_val_const, cx.tcx))?
+                            mir_to_const(cx, mir::Const::from_ty_const(min_val_const, cx.tcx))?
                         },
                     };
                     let rhs_const = match rhs {
                         Some(rhs) => constant(cx, cx.typeck_results(), rhs)?,
                         None => {
                             let max_val_const = ty.numeric_max_val(cx.tcx)?;
-                            miri_to_const(cx, mir::Const::from_ty_const(max_val_const, cx.tcx))?
+                            mir_to_const(cx, mir::Const::from_ty_const(max_val_const, cx.tcx))?
                         },
                     };
                     let lhs_val = lhs_const.int_value(cx, ty)?;
diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs
index d596eed4b7c..0bae7056c4f 100644
--- a/clippy_utils/src/consts.rs
+++ b/clippy_utils/src/consts.rs
@@ -9,11 +9,12 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp};
 use rustc_lexer::tokenize;
 use rustc_lint::LateContext;
-use rustc_middle::mir::interpret::Scalar;
+use rustc_middle::mir::interpret::{alloc_range, Scalar};
 use rustc_middle::ty::{self, EarlyBinder, FloatTy, GenericArgsRef, List, ScalarInt, Ty, TyCtxt};
 use rustc_middle::{bug, mir, span_bug};
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::SyntaxContext;
+use rustc_target::abi::Size;
 use std::cmp::Ordering::{self, Equal};
 use std::hash::{Hash, Hasher};
 use std::iter;
@@ -403,7 +404,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
                     && adt_def.is_struct()
                     && let Some(desired_field) = field_of_struct(*adt_def, self.lcx, *constant, field)
                 {
-                    miri_to_const(self.lcx, desired_field)
+                    mir_to_const(self.lcx, desired_field)
                 }
                 else {
                     result
@@ -483,7 +484,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
                     .const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, args), None)
                     .ok()
                     .map(|val| rustc_middle::mir::Const::from_value(val, ty))?;
-                let result = miri_to_const(self.lcx, result)?;
+                let result = mir_to_const(self.lcx, result)?;
                 self.source = ConstantSource::Constant;
                 Some(result)
             },
@@ -655,10 +656,14 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
     }
 }
 
-pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> Option<Constant<'tcx>> {
+pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> Option<Constant<'tcx>> {
     use rustc_middle::mir::ConstValue;
-    match result {
-        mir::Const::Val(ConstValue::Scalar(Scalar::Int(int)), _) => match result.ty().kind() {
+    let mir::Const::Val(val, _) = result else {
+        // We only work on evaluated consts.
+        return None;
+    };
+    match (val, result.ty().kind()) {
+        (ConstValue::Scalar(Scalar::Int(int)), _) => match result.ty().kind() {
             ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
             ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)),
             ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.assert_bits(int.size()))),
@@ -671,42 +676,28 @@ pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) ->
             ty::RawPtr(_) => Some(Constant::RawPtr(int.assert_bits(int.size()))),
             _ => None,
         },
-        mir::Const::Val(cv, _) if matches!(result.ty().kind(), ty::Ref(_, inner_ty, _) if matches!(inner_ty.kind(), ty::Str)) =>
-        {
-            let data = cv.try_get_slice_bytes_for_diagnostics(lcx.tcx)?;
+        (_, ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Str) => {
+            let data = val.try_get_slice_bytes_for_diagnostics(lcx.tcx)?;
             String::from_utf8(data.to_owned()).ok().map(Constant::Str)
         },
-        mir::Const::Val(ConstValue::Indirect { alloc_id, offset: _ }, _) => {
-            let alloc = lcx.tcx.global_alloc(alloc_id).unwrap_memory();
-            match result.ty().kind() {
-                ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
-                ty::Array(sub_type, len) => match sub_type.kind() {
-                    ty::Float(FloatTy::F32) => match len.try_to_target_usize(lcx.tcx) {
-                        Some(len) => alloc
-                            .inner()
-                            .inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * usize::try_from(len).unwrap()))
-                            .to_owned()
-                            .array_chunks::<4>()
-                            .map(|&chunk| Some(Constant::F32(f32::from_le_bytes(chunk))))
-                            .collect::<Option<Vec<Constant<'tcx>>>>()
-                            .map(Constant::Vec),
-                        _ => None,
-                    },
-                    ty::Float(FloatTy::F64) => match len.try_to_target_usize(lcx.tcx) {
-                        Some(len) => alloc
-                            .inner()
-                            .inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * usize::try_from(len).unwrap()))
-                            .to_owned()
-                            .array_chunks::<8>()
-                            .map(|&chunk| Some(Constant::F64(f64::from_le_bytes(chunk))))
-                            .collect::<Option<Vec<Constant<'tcx>>>>()
-                            .map(Constant::Vec),
-                        _ => None,
-                    },
-                    _ => None,
-                },
-                _ => None,
+        (_, ty::Adt(adt_def, _)) if adt_def.is_struct() => Some(Constant::Adt(result)),
+        (ConstValue::Indirect { alloc_id, offset }, ty::Array(sub_type, len)) => {
+            let alloc = lcx.tcx.global_alloc(alloc_id).unwrap_memory().inner();
+            let len = len.try_to_target_usize(lcx.tcx)?;
+            let ty::Float(flt) = sub_type.kind() else {
+                return None;
+            };
+            let size = Size::from_bits(flt.bit_width());
+            let mut res = Vec::new();
+            for idx in 0..len {
+                let range = alloc_range(offset + size * idx, size);
+                let val = alloc.read_scalar(&lcx.tcx, range, /* read_provenance */ false).ok()?;
+                res.push(match flt {
+                    FloatTy::F32 => Constant::F32(f32::from_bits(val.to_u32().ok()?)),
+                    FloatTy::F64 => Constant::F64(f64::from_bits(val.to_u64().ok()?)),
+                });
             }
+            Some(Constant::Vec(res))
         },
         _ => None,
     }
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 0f7bc04ccba..350b231e903 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -113,7 +113,7 @@ use rustc_span::{sym, Span};
 use rustc_target::abi::Integer;
 use visitors::Visitable;
 
-use crate::consts::{constant, miri_to_const, Constant};
+use crate::consts::{constant, mir_to_const, Constant};
 use crate::higher::Range;
 use crate::ty::{
     adt_and_variant_of_res, can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type,
@@ -1509,9 +1509,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti
             if let rustc_ty::Adt(_, subst) = ty.kind()
                 && let bnd_ty = subst.type_at(0)
                 && let Some(min_val) = bnd_ty.numeric_min_val(cx.tcx)
-                && let const_val = cx.tcx.valtree_to_const_val((bnd_ty, min_val.to_valtree()))
-                && let min_const_kind = Const::from_value(const_val, bnd_ty)
-                && let Some(min_const) = miri_to_const(cx, min_const_kind)
+                && let Some(min_const) = mir_to_const(cx, Const::from_ty_const(min_val, cx.tcx))
                 && let Some(start_const) = constant(cx, cx.typeck_results(), start)
             {
                 start_const == min_const
@@ -1525,9 +1523,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti
                     if let rustc_ty::Adt(_, subst) = ty.kind()
                         && let bnd_ty = subst.type_at(0)
                         && let Some(max_val) = bnd_ty.numeric_max_val(cx.tcx)
-                        && let const_val = cx.tcx.valtree_to_const_val((bnd_ty, max_val.to_valtree()))
-                        && let max_const_kind = Const::from_value(const_val, bnd_ty)
-                        && let Some(max_const) = miri_to_const(cx, max_const_kind)
+                        && let Some(max_const) = mir_to_const(cx, Const::from_ty_const(max_val, cx.tcx))
                         && let Some(end_const) = constant(cx, cx.typeck_results(), end)
                     {
                         end_const == max_const