Skip to content

Commit 0f19857

Browse files
committed
mir_to_const: fix handling of float arrays
1 parent ce45221 commit 0f19857

File tree

1 file changed

+27
-36
lines changed

1 file changed

+27
-36
lines changed

clippy_utils/src/consts.rs

Lines changed: 27 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ use rustc_hir::def::{DefKind, Res};
99
use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp};
1010
use rustc_lexer::tokenize;
1111
use rustc_lint::LateContext;
12-
use rustc_middle::mir::interpret::Scalar;
12+
use rustc_middle::mir::interpret::{alloc_range, Scalar};
1313
use rustc_middle::ty::{self, EarlyBinder, FloatTy, GenericArgsRef, List, ScalarInt, Ty, TyCtxt};
1414
use rustc_middle::{bug, mir, span_bug};
1515
use rustc_span::symbol::{Ident, Symbol};
1616
use rustc_span::SyntaxContext;
17+
use rustc_target::abi::Size;
1718
use std::cmp::Ordering::{self, Equal};
1819
use std::hash::{Hash, Hasher};
1920
use std::iter;
@@ -657,8 +658,12 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
657658

658659
pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> Option<Constant<'tcx>> {
659660
use rustc_middle::mir::ConstValue;
660-
match result {
661-
mir::Const::Val(ConstValue::Scalar(Scalar::Int(int)), _) => match result.ty().kind() {
661+
let mir::Const::Val(val, _) = result else {
662+
// We only work on evaluated consts.
663+
return None;
664+
};
665+
match (val, result.ty().kind()) {
666+
(ConstValue::Scalar(Scalar::Int(int)), _) => match result.ty().kind() {
662667
ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
663668
ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)),
664669
ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.assert_bits(int.size()))),
@@ -671,42 +676,28 @@ pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) ->
671676
ty::RawPtr(_) => Some(Constant::RawPtr(int.assert_bits(int.size()))),
672677
_ => None,
673678
},
674-
mir::Const::Val(cv, _) if matches!(result.ty().kind(), ty::Ref(_, inner_ty, _) if matches!(inner_ty.kind(), ty::Str)) =>
675-
{
676-
let data = cv.try_get_slice_bytes_for_diagnostics(lcx.tcx)?;
679+
(_, ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Str) => {
680+
let data = val.try_get_slice_bytes_for_diagnostics(lcx.tcx)?;
677681
String::from_utf8(data.to_owned()).ok().map(Constant::Str)
678682
},
679-
mir::Const::Val(ConstValue::Indirect { alloc_id, offset: _ }, _) => {
680-
let alloc = lcx.tcx.global_alloc(alloc_id).unwrap_memory();
681-
match result.ty().kind() {
682-
ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
683-
ty::Array(sub_type, len) => match sub_type.kind() {
684-
ty::Float(FloatTy::F32) => match len.try_to_target_usize(lcx.tcx) {
685-
Some(len) => alloc
686-
.inner()
687-
.inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * usize::try_from(len).unwrap()))
688-
.to_owned()
689-
.array_chunks::<4>()
690-
.map(|&chunk| Some(Constant::F32(f32::from_le_bytes(chunk))))
691-
.collect::<Option<Vec<Constant<'tcx>>>>()
692-
.map(Constant::Vec),
693-
_ => None,
694-
},
695-
ty::Float(FloatTy::F64) => match len.try_to_target_usize(lcx.tcx) {
696-
Some(len) => alloc
697-
.inner()
698-
.inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * usize::try_from(len).unwrap()))
699-
.to_owned()
700-
.array_chunks::<8>()
701-
.map(|&chunk| Some(Constant::F64(f64::from_le_bytes(chunk))))
702-
.collect::<Option<Vec<Constant<'tcx>>>>()
703-
.map(Constant::Vec),
704-
_ => None,
705-
},
706-
_ => None,
707-
},
708-
_ => None,
683+
(_, ty::Adt(adt_def, _)) if adt_def.is_struct() => Some(Constant::Adt(result)),
684+
(ConstValue::Indirect { alloc_id, offset }, ty::Array(sub_type, len)) => {
685+
let alloc = lcx.tcx.global_alloc(alloc_id).unwrap_memory().inner();
686+
let len = len.try_to_target_usize(lcx.tcx)?;
687+
let ty::Float(flt) = sub_type.kind() else {
688+
return None;
689+
};
690+
let size = Size::from_bits(flt.bit_width());
691+
let mut res = Vec::new();
692+
for idx in 0..len {
693+
let range = alloc_range(offset + size * idx, size);
694+
let val = alloc.read_scalar(&lcx.tcx, range, /* read_provenance */ false).ok()?;
695+
res.push(match flt {
696+
FloatTy::F32 => Constant::F32(f32::from_bits(val.to_u32().ok()?)),
697+
FloatTy::F64 => Constant::F64(f64::from_bits(val.to_u64().ok()?)),
698+
});
709699
}
700+
Some(Constant::Vec(res))
710701
},
711702
_ => None,
712703
}

0 commit comments

Comments
 (0)