Skip to content

Commit 90a4105

Browse files
committed
implement valtrees as the type-system representation for constant values
1 parent 7969056 commit 90a4105

File tree

6 files changed

+67
-81
lines changed

6 files changed

+67
-81
lines changed

clippy_lints/src/enum_clike.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant {
4848
let mut ty = cx.tcx.type_of(def_id.to_def_id());
4949
let constant = cx
5050
.tcx
51-
.const_eval_poly(def_id.to_def_id())
51+
.const_eval_poly_for_typeck(def_id.to_def_id())
5252
.ok()
53-
.map(|val| rustc_middle::ty::Const::from_value(cx.tcx, val, ty));
54-
if let Some(Constant::Int(val)) = constant.and_then(miri_to_const) {
53+
.and_then(|val| val.map(|valtree| rustc_middle::ty::Const::from_value(cx.tcx, valtree, ty)));
54+
if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx.tcx, c)) {
5555
if let ty::Adt(adt, _) = ty.kind() {
5656
if adt.is_enum() {
5757
ty = adt.repr().discr_type().to_ty(cx.tcx);

clippy_lints/src/large_const_arrays.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use if_chain::if_chain;
33
use rustc_errors::Applicability;
44
use rustc_hir::{Item, ItemKind};
55
use rustc_lint::{LateContext, LateLintPass};
6-
use rustc_middle::mir::interpret::ConstValue;
76
use rustc_middle::ty::layout::LayoutOf;
87
use rustc_middle::ty::{self, ConstKind};
98
use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -53,8 +52,8 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
5352
if let ItemKind::Const(hir_ty, _) = &item.kind;
5453
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
5554
if let ty::Array(element_type, cst) = ty.kind();
56-
if let ConstKind::Value(ConstValue::Scalar(element_count)) = cst.kind();
57-
if let Ok(element_count) = element_count.to_machine_usize(&cx.tcx);
55+
if let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind();
56+
if let Ok(element_count) = element_count.try_to_machine_usize(cx.tcx);
5857
if let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes());
5958
if self.maximum_allowed_size < element_count * element_size;
6059

clippy_lints/src/large_stack_arrays.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use clippy_utils::source::snippet;
33
use if_chain::if_chain;
44
use rustc_hir::{Expr, ExprKind};
55
use rustc_lint::{LateContext, LateLintPass};
6-
use rustc_middle::mir::interpret::ConstValue;
76
use rustc_middle::ty::layout::LayoutOf;
87
use rustc_middle::ty::{self, ConstKind};
98
use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -43,8 +42,8 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackArrays {
4342
if_chain! {
4443
if let ExprKind::Repeat(_, _) = expr.kind;
4544
if let ty::Array(element_type, cst) = cx.typeck_results().expr_ty(expr).kind();
46-
if let ConstKind::Value(ConstValue::Scalar(element_count)) = cst.kind();
47-
if let Ok(element_count) = element_count.to_machine_usize(&cx.tcx);
45+
if let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind();
46+
if let Ok(element_count) = element_count.try_to_machine_usize(cx.tcx);
4847
if let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes());
4948
if self.maximum_allowed_size < element_count * element_size;
5049
then {

clippy_lints/src/matches/overlapping_arms.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
3434
if let PatKind::Range(ref lhs, ref rhs, range_end) = pat.kind {
3535
let lhs_const = match lhs {
3636
Some(lhs) => constant(cx, cx.typeck_results(), lhs)?.0,
37-
None => miri_to_const(ty.numeric_min_val(cx.tcx)?)?,
37+
None => miri_to_const(cx.tcx, ty.numeric_min_val(cx.tcx)?)?,
3838
};
3939
let rhs_const = match rhs {
4040
Some(rhs) => constant(cx, cx.typeck_results(), rhs)?.0,
41-
None => miri_to_const(ty.numeric_max_val(cx.tcx)?)?,
41+
None => miri_to_const(cx.tcx, ty.numeric_max_val(cx.tcx)?)?,
4242
};
4343
let lhs_val = lhs_const.int_value(cx, ty)?;
4444
let rhs_val = rhs_const.int_value(cx, ty)?;

clippy_lints/src/non_copy_const.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_hir::{
1313
BodyId, Expr, ExprKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind, UnOp,
1414
};
1515
use rustc_lint::{LateContext, LateLintPass, Lint};
16-
use rustc_middle::mir::interpret::{ConstValue, ErrorHandled};
16+
use rustc_middle::mir::interpret::ErrorHandled;
1717
use rustc_middle::ty::adjustment::Adjust;
1818
use rustc_middle::ty::{self, Const, Ty};
1919
use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -133,7 +133,7 @@ fn is_unfrozen<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
133133

134134
fn is_value_unfrozen_raw<'tcx>(
135135
cx: &LateContext<'tcx>,
136-
result: Result<ConstValue<'tcx>, ErrorHandled>,
136+
result: Result<Option<ty::ValTree<'tcx>>, ErrorHandled>,
137137
ty: Ty<'tcx>,
138138
) -> bool {
139139
fn inner<'tcx>(cx: &LateContext<'tcx>, val: Const<'tcx>) -> bool {
@@ -142,7 +142,7 @@ fn is_value_unfrozen_raw<'tcx>(
142142
// leads us to the point checking `UnsafeCell` directly is the only option.
143143
ty::Adt(ty_def, ..) if Some(ty_def.did()) == cx.tcx.lang_items().unsafe_cell_type() => true,
144144
ty::Array(..) | ty::Adt(..) | ty::Tuple(..) => {
145-
let val = cx.tcx.destructure_const(cx.param_env.and(val));
145+
let val = cx.tcx.destructure_const(val);
146146
val.fields.iter().any(|field| inner(cx, *field))
147147
},
148148
_ => false,
@@ -174,19 +174,19 @@ fn is_value_unfrozen_raw<'tcx>(
174174
// I chose this way because unfrozen enums as assoc consts are rare (or, hopefully, none).
175175
err == ErrorHandled::TooGeneric
176176
},
177-
|val| inner(cx, Const::from_value(cx.tcx, val, ty)),
177+
|val| val.map_or(false, |val| inner(cx, Const::from_value(cx.tcx, val, ty))),
178178
)
179179
}
180180

181181
fn is_value_unfrozen_poly<'tcx>(cx: &LateContext<'tcx>, body_id: BodyId, ty: Ty<'tcx>) -> bool {
182-
let result = cx.tcx.const_eval_poly(body_id.hir_id.owner.to_def_id());
182+
let result = cx.tcx.const_eval_poly_for_typeck(body_id.hir_id.owner.to_def_id());
183183
is_value_unfrozen_raw(cx, result, ty)
184184
}
185185

186186
fn is_value_unfrozen_expr<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool {
187187
let substs = cx.typeck_results().node_substs(hir_id);
188188

189-
let result = cx.tcx.const_eval_resolve(
189+
let result = cx.tcx.const_eval_resolve_for_typeck(
190190
cx.param_env,
191191
ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs),
192192
None,

clippy_utils/src/consts.rs

Lines changed: 52 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use rustc_data_structures::sync::Lrc;
77
use rustc_hir::def::{DefKind, Res};
88
use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp};
99
use rustc_lint::LateContext;
10-
use rustc_middle::mir::interpret::Scalar;
1110
use rustc_middle::ty::subst::{Subst, SubstsRef};
1211
use rustc_middle::ty::{self, EarlyBinder, FloatTy, ScalarInt, Ty, TyCtxt};
1312
use rustc_middle::{bug, span_bug};
@@ -423,14 +422,14 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
423422
let result = self
424423
.lcx
425424
.tcx
426-
.const_eval_resolve(
425+
.const_eval_resolve_for_typeck(
427426
self.param_env,
428427
ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs),
429428
None,
430429
)
431430
.ok()
432-
.map(|val| rustc_middle::ty::Const::from_value(self.lcx.tcx, val, ty))?;
433-
let result = miri_to_const(result);
431+
.and_then(|val| val.map(|val| rustc_middle::ty::Const::from_value(self.lcx.tcx, val, ty)))?;
432+
let result = miri_to_const(self.lcx.tcx, result);
434433
if result.is_some() {
435434
self.needed_resolution = true;
436435
}
@@ -580,80 +579,69 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
580579
}
581580
}
582581

583-
pub fn miri_to_const(result: ty::Const<'_>) -> Option<Constant> {
584-
use rustc_middle::mir::interpret::ConstValue;
582+
pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: ty::Const<'tcx>) -> Option<Constant> {
585583
match result.kind() {
586-
ty::ConstKind::Value(ConstValue::Scalar(Scalar::Int(int))) => {
587-
match result.ty().kind() {
588-
ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)),
589-
ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.assert_bits(int.size()))),
590-
ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits(
584+
ty::ConstKind::Value(valtree) => {
585+
match (valtree, result.ty().kind()) {
586+
(ty::ValTree::Leaf(int), ty::Bool) => Some(Constant::Bool(int == ScalarInt::TRUE)),
587+
(ty::ValTree::Leaf(int), ty::Uint(_) | ty::Int(_)) => Some(Constant::Int(int.assert_bits(int.size()))),
588+
(ty::ValTree::Leaf(int), ty::Float(FloatTy::F32)) => Some(Constant::F32(f32::from_bits(
591589
int.try_into().expect("invalid f32 bit representation"),
592590
))),
593-
ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits(
591+
(ty::ValTree::Leaf(int), ty::Float(FloatTy::F64)) => Some(Constant::F64(f64::from_bits(
594592
int.try_into().expect("invalid f64 bit representation"),
595593
))),
596-
ty::RawPtr(type_and_mut) => {
594+
(ty::ValTree::Leaf(int), ty::RawPtr(type_and_mut)) => {
597595
if let ty::Uint(_) = type_and_mut.ty.kind() {
598596
return Some(Constant::RawPtr(int.assert_bits(int.size())));
599597
}
600598
None
601599
},
602-
// FIXME: implement other conversions.
603-
_ => None,
604-
}
605-
},
606-
ty::ConstKind::Value(ConstValue::Slice { data, start, end }) => match result.ty().kind() {
607-
ty::Ref(_, tam, _) => match tam.kind() {
608-
ty::Str => String::from_utf8(
609-
data.inner()
610-
.inspect_with_uninit_and_ptr_outside_interpreter(start..end)
611-
.to_owned(),
612-
)
613-
.ok()
614-
.map(Constant::Str),
615-
_ => None,
616-
},
617-
_ => None,
618-
},
619-
ty::ConstKind::Value(ConstValue::ByRef { alloc, offset: _ }) => match result.ty().kind() {
620-
ty::Array(sub_type, len) => match sub_type.kind() {
621-
ty::Float(FloatTy::F32) => match miri_to_const(*len) {
622-
Some(Constant::Int(len)) => alloc
623-
.inner()
624-
.inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * len as usize))
625-
.to_owned()
626-
.chunks(4)
627-
.map(|chunk| {
628-
Some(Constant::F32(f32::from_le_bytes(
629-
chunk.try_into().expect("this shouldn't happen"),
630-
)))
631-
})
632-
.collect::<Option<Vec<Constant>>>()
633-
.map(Constant::Vec),
634-
_ => None,
635-
},
636-
ty::Float(FloatTy::F64) => match miri_to_const(*len) {
637-
Some(Constant::Int(len)) => alloc
638-
.inner()
639-
.inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * len as usize))
640-
.to_owned()
641-
.chunks(8)
642-
.map(|chunk| {
643-
Some(Constant::F64(f64::from_le_bytes(
644-
chunk.try_into().expect("this shouldn't happen"),
645-
)))
646-
})
647-
.collect::<Option<Vec<Constant>>>()
648-
.map(Constant::Vec),
600+
(ty::ValTree::Branch(_), ty::Ref(_, inner_ty, _)) if *inner_ty == tcx.types.str_ => valtree
601+
.try_to_raw_bytes(tcx, result.ty())
602+
.and_then(|bytes| String::from_utf8(bytes.to_owned()).ok().map(Constant::Str)),
603+
(ty::ValTree::Branch(_), ty::Array(arr_ty, len)) => match arr_ty.kind() {
604+
ty::Float(float_ty) => {
605+
let chunk_size = match float_ty {
606+
FloatTy::F32 => 4,
607+
FloatTy::F64 => 8,
608+
};
609+
610+
match miri_to_const(tcx, *len) {
611+
Some(Constant::Int(_)) => valtree.try_to_raw_bytes(tcx, result.ty()).and_then(|bytes| {
612+
bytes
613+
.to_owned()
614+
.chunks(chunk_size)
615+
.map(|chunk| match float_ty {
616+
FloatTy::F32 => {
617+
let float = f32::from_le_bytes(
618+
chunk
619+
.try_into()
620+
.expect(&format!("expected to construct f32 from {:?}", chunk)),
621+
);
622+
Some(Constant::F32(float))
623+
},
624+
FloatTy::F64 => {
625+
let float = f64::from_le_bytes(
626+
chunk
627+
.try_into()
628+
.expect(&format!("expected to construct f64 from {:?}", chunk)),
629+
);
630+
Some(Constant::F64(float))
631+
},
632+
})
633+
.collect::<Option<Vec<Constant>>>()
634+
.map(Constant::Vec)
635+
}),
636+
_ => None,
637+
}
638+
},
649639
_ => None,
650640
},
651-
// FIXME: implement other array type conversions.
641+
// FIXME: implement other conversions.
652642
_ => None,
653-
},
654-
_ => None,
643+
}
655644
},
656-
// FIXME: implement other conversions.
657645
_ => None,
658646
}
659647
}

0 commit comments

Comments
 (0)