fix clippy test failures
This commit is contained in:
parent
705d818bd5
commit
5c95a3db2a
@ -199,6 +199,14 @@ pub fn from_value(tcx: TyCtxt<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Se
|
||||
tcx.mk_const(ConstS { kind: ConstKind::Value(val), ty })
|
||||
}
|
||||
|
||||
/// Panics if self.kind != ty::ConstKind::Value
|
||||
pub fn to_valtree(self) -> ty::ValTree<'tcx> {
|
||||
match self.val() {
|
||||
ty::ConstKind::Value(valtree) => valtree,
|
||||
_ => bug!("expected ConstKind::Value"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_scalar_int(tcx: TyCtxt<'tcx>, i: ScalarInt, ty: Ty<'tcx>) -> Self {
|
||||
let valtree = ty::ValTree::from_scalar_int(i);
|
||||
Self::from_value(tcx, valtree, ty)
|
||||
|
@ -798,7 +798,7 @@ pub(crate) fn compare_const_vals<'tcx>(
|
||||
if let ty::Str = ty.kind() && let (
|
||||
Some(a_val @ ConstValue::Slice { .. }),
|
||||
Some(b_val @ ConstValue::Slice { .. }),
|
||||
) = (a.try_val(tcx), b.try_val(tcx))
|
||||
) = (a.try_to_value(tcx), b.try_to_value(tcx))
|
||||
{
|
||||
let a_bytes = get_slice_bytes(&tcx, a_val);
|
||||
let b_bytes = get_slice_bytes(&tcx, b_val);
|
||||
|
@ -48,9 +48,9 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
let mut ty = cx.tcx.type_of(def_id.to_def_id());
|
||||
let constant = cx
|
||||
.tcx
|
||||
.const_eval_poly_for_typeck(def_id.to_def_id())
|
||||
.const_eval_poly(def_id.to_def_id())
|
||||
.ok()
|
||||
.and_then(|val| val.map(|valtree| rustc_middle::ty::Const::from_value(cx.tcx, valtree, ty)));
|
||||
.and_then(|val| Some(rustc_middle::mir::ConstantKind::from_value(val, ty)));
|
||||
if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx.tcx, c)) {
|
||||
if let ty::Adt(adt, _) = ty.kind() {
|
||||
if adt.is_enum() {
|
||||
|
@ -3,6 +3,7 @@
|
||||
use core::cmp::Ordering;
|
||||
use rustc_hir::{Arm, Expr, PatKind, RangeEnd};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_span::Span;
|
||||
|
||||
@ -34,11 +35,25 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
|
||||
if let PatKind::Range(ref lhs, ref rhs, range_end) = pat.kind {
|
||||
let lhs_const = match lhs {
|
||||
Some(lhs) => constant(cx, cx.typeck_results(), lhs)?.0,
|
||||
None => miri_to_const(cx.tcx, ty.numeric_min_val(cx.tcx)?)?,
|
||||
None => {
|
||||
let min_val_const = ty.numeric_min_val(cx.tcx)?;
|
||||
let min_constant = mir::ConstantKind::from_value(
|
||||
cx.tcx.valtree_to_const_val((ty, min_val_const.to_valtree())),
|
||||
ty,
|
||||
);
|
||||
miri_to_const(cx.tcx, min_constant)?
|
||||
},
|
||||
};
|
||||
let rhs_const = match rhs {
|
||||
Some(rhs) => constant(cx, cx.typeck_results(), rhs)?.0,
|
||||
None => miri_to_const(cx.tcx, ty.numeric_max_val(cx.tcx)?)?,
|
||||
None => {
|
||||
let max_val_const = ty.numeric_max_val(cx.tcx)?;
|
||||
let max_constant = mir::ConstantKind::from_value(
|
||||
cx.tcx.valtree_to_const_val((ty, max_val_const.to_valtree())),
|
||||
ty,
|
||||
);
|
||||
miri_to_const(cx.tcx, max_constant)?
|
||||
},
|
||||
};
|
||||
let lhs_val = lhs_const.int_value(cx, ty)?;
|
||||
let rhs_val = rhs_const.int_value(cx, ty)?;
|
||||
|
@ -13,9 +13,10 @@
|
||||
BodyId, Expr, ExprKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind, UnOp,
|
||||
};
|
||||
use rustc_lint::{LateContext, LateLintPass, Lint};
|
||||
use rustc_middle::mir::interpret::ErrorHandled;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::mir::interpret::{ConstValue, ErrorHandled};
|
||||
use rustc_middle::ty::adjustment::Adjust;
|
||||
use rustc_middle::ty::{self, Const, Ty};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::{InnerSpan, Span, DUMMY_SP};
|
||||
use rustc_typeck::hir_ty_to_ty;
|
||||
@ -133,22 +134,21 @@ fn is_unfrozen<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
|
||||
fn is_value_unfrozen_raw<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
result: Result<Option<ty::ValTree<'tcx>>, ErrorHandled>,
|
||||
result: Result<ConstValue<'tcx>, ErrorHandled>,
|
||||
ty: Ty<'tcx>,
|
||||
) -> bool {
|
||||
fn inner<'tcx>(cx: &LateContext<'tcx>, val: Const<'tcx>) -> bool {
|
||||
fn inner<'tcx>(cx: &LateContext<'tcx>, val: mir::ConstantKind<'tcx>) -> bool {
|
||||
match val.ty().kind() {
|
||||
// the fact that we have to dig into every structs to search enums
|
||||
// leads us to the point checking `UnsafeCell` directly is the only option.
|
||||
ty::Adt(ty_def, ..) if Some(ty_def.did()) == cx.tcx.lang_items().unsafe_cell_type() => true,
|
||||
ty::Array(..) | ty::Adt(..) | ty::Tuple(..) => {
|
||||
let val = cx.tcx.destructure_const(val);
|
||||
let val = cx.tcx.destructure_mir_constant(cx.param_env, val);
|
||||
val.fields.iter().any(|field| inner(cx, *field))
|
||||
},
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
result.map_or_else(
|
||||
|err| {
|
||||
// Consider `TooGeneric` cases as being unfrozen.
|
||||
@ -174,19 +174,19 @@ fn inner<'tcx>(cx: &LateContext<'tcx>, val: Const<'tcx>) -> bool {
|
||||
// I chose this way because unfrozen enums as assoc consts are rare (or, hopefully, none).
|
||||
err == ErrorHandled::TooGeneric
|
||||
},
|
||||
|val| val.map_or(false, |val| inner(cx, Const::from_value(cx.tcx, val, ty))),
|
||||
|val| inner(cx, mir::ConstantKind::from_value(val, ty)),
|
||||
)
|
||||
}
|
||||
|
||||
fn is_value_unfrozen_poly<'tcx>(cx: &LateContext<'tcx>, body_id: BodyId, ty: Ty<'tcx>) -> bool {
|
||||
let result = cx.tcx.const_eval_poly_for_typeck(body_id.hir_id.owner.to_def_id());
|
||||
let result = cx.tcx.const_eval_poly(body_id.hir_id.owner.to_def_id());
|
||||
is_value_unfrozen_raw(cx, result, ty)
|
||||
}
|
||||
|
||||
fn is_value_unfrozen_expr<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool {
|
||||
let substs = cx.typeck_results().node_substs(hir_id);
|
||||
|
||||
let result = cx.tcx.const_eval_resolve_for_typeck(
|
||||
let result = cx.tcx.const_eval_resolve(
|
||||
cx.param_env,
|
||||
ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs),
|
||||
None,
|
||||
|
@ -7,6 +7,8 @@
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::mir::interpret::Scalar;
|
||||
use rustc_middle::ty::subst::{Subst, SubstsRef};
|
||||
use rustc_middle::ty::{self, EarlyBinder, FloatTy, ScalarInt, Ty, TyCtxt};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
@ -422,13 +424,13 @@ fn fetch_path(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'tcx>) -> Option<C
|
||||
let result = self
|
||||
.lcx
|
||||
.tcx
|
||||
.const_eval_resolve_for_typeck(
|
||||
.const_eval_resolve(
|
||||
self.param_env,
|
||||
ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs),
|
||||
None,
|
||||
)
|
||||
.ok()
|
||||
.and_then(|val| val.map(|val| rustc_middle::ty::Const::from_value(self.lcx.tcx, val, ty)))?;
|
||||
.and_then(|val| Some(rustc_middle::mir::ConstantKind::from_value(val, ty)))?;
|
||||
let result = miri_to_const(self.lcx.tcx, result);
|
||||
if result.is_some() {
|
||||
self.needed_resolution = true;
|
||||
@ -579,69 +581,90 @@ fn binop(&mut self, op: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> Option<Cons
|
||||
}
|
||||
}
|
||||
|
||||
pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: ty::Const<'tcx>) -> Option<Constant> {
|
||||
match result.kind() {
|
||||
fn try_const_to_constant<'tcx>(tcx: TyCtxt<'tcx>, c: ty::Const<'tcx>) -> Option<Constant> {
|
||||
match c.kind() {
|
||||
ty::ConstKind::Value(valtree) => {
|
||||
match (valtree, result.ty().kind()) {
|
||||
(ty::ValTree::Leaf(int), ty::Bool) => Some(Constant::Bool(int == ScalarInt::TRUE)),
|
||||
(ty::ValTree::Leaf(int), ty::Uint(_) | ty::Int(_)) => Some(Constant::Int(int.assert_bits(int.size()))),
|
||||
(ty::ValTree::Leaf(int), ty::Float(FloatTy::F32)) => Some(Constant::F32(f32::from_bits(
|
||||
let const_val = tcx.valtree_to_const_val((c.ty(), valtree));
|
||||
miri_to_const(tcx, mir::ConstantKind::from_value(const_val, c.ty()))
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) -> Option<Constant> {
|
||||
use rustc_middle::mir::interpret::ConstValue;
|
||||
match result {
|
||||
mir::ConstantKind::Val(ConstValue::Scalar(Scalar::Int(int)), _) => {
|
||||
match result.ty().kind() {
|
||||
ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)),
|
||||
ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.assert_bits(int.size()))),
|
||||
ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits(
|
||||
int.try_into().expect("invalid f32 bit representation"),
|
||||
))),
|
||||
(ty::ValTree::Leaf(int), ty::Float(FloatTy::F64)) => Some(Constant::F64(f64::from_bits(
|
||||
ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits(
|
||||
int.try_into().expect("invalid f64 bit representation"),
|
||||
))),
|
||||
(ty::ValTree::Leaf(int), ty::RawPtr(type_and_mut)) => {
|
||||
ty::RawPtr(type_and_mut) => {
|
||||
if let ty::Uint(_) = type_and_mut.ty.kind() {
|
||||
return Some(Constant::RawPtr(int.assert_bits(int.size())));
|
||||
}
|
||||
None
|
||||
},
|
||||
(ty::ValTree::Branch(_), ty::Ref(_, inner_ty, _)) if *inner_ty == tcx.types.str_ => valtree
|
||||
.try_to_raw_bytes(tcx, result.ty())
|
||||
.and_then(|bytes| String::from_utf8(bytes.to_owned()).ok().map(Constant::Str)),
|
||||
(ty::ValTree::Branch(_), ty::Array(arr_ty, len)) => match arr_ty.kind() {
|
||||
ty::Float(float_ty) => {
|
||||
let chunk_size = match float_ty {
|
||||
FloatTy::F32 => 4,
|
||||
FloatTy::F64 => 8,
|
||||
};
|
||||
|
||||
match miri_to_const(tcx, *len) {
|
||||
Some(Constant::Int(_)) => valtree.try_to_raw_bytes(tcx, result.ty()).and_then(|bytes| {
|
||||
bytes
|
||||
.to_owned()
|
||||
.chunks(chunk_size)
|
||||
.map(|chunk| match float_ty {
|
||||
FloatTy::F32 => {
|
||||
let float = f32::from_le_bytes(
|
||||
chunk
|
||||
.try_into()
|
||||
.expect(&format!("expected to construct f32 from {:?}", chunk)),
|
||||
);
|
||||
Some(Constant::F32(float))
|
||||
},
|
||||
FloatTy::F64 => {
|
||||
let float = f64::from_le_bytes(
|
||||
chunk
|
||||
.try_into()
|
||||
.expect(&format!("expected to construct f64 from {:?}", chunk)),
|
||||
);
|
||||
Some(Constant::F64(float))
|
||||
},
|
||||
})
|
||||
.collect::<Option<Vec<Constant>>>()
|
||||
.map(Constant::Vec)
|
||||
}),
|
||||
_ => None,
|
||||
}
|
||||
},
|
||||
_ => None,
|
||||
},
|
||||
// FIXME: implement other conversions.
|
||||
_ => None,
|
||||
}
|
||||
},
|
||||
mir::ConstantKind::Val(ConstValue::Slice { data, start, end }, _) => match result.ty().kind() {
|
||||
ty::Ref(_, tam, _) => match tam.kind() {
|
||||
ty::Str => String::from_utf8(
|
||||
data.inner()
|
||||
.inspect_with_uninit_and_ptr_outside_interpreter(start..end)
|
||||
.to_owned(),
|
||||
)
|
||||
.ok()
|
||||
.map(Constant::Str),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
},
|
||||
mir::ConstantKind::Val(ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() {
|
||||
ty::Array(sub_type, len) => match sub_type.kind() {
|
||||
ty::Float(FloatTy::F32) => match try_const_to_constant(tcx, *len) {
|
||||
Some(Constant::Int(len)) => alloc
|
||||
.inner()
|
||||
.inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * len as usize))
|
||||
.to_owned()
|
||||
.chunks(4)
|
||||
.map(|chunk| {
|
||||
Some(Constant::F32(f32::from_le_bytes(
|
||||
chunk.try_into().expect("this shouldn't happen"),
|
||||
)))
|
||||
})
|
||||
.collect::<Option<Vec<Constant>>>()
|
||||
.map(Constant::Vec),
|
||||
_ => None,
|
||||
},
|
||||
ty::Float(FloatTy::F64) => match try_const_to_constant(tcx, *len) {
|
||||
Some(Constant::Int(len)) => alloc
|
||||
.inner()
|
||||
.inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * len as usize))
|
||||
.to_owned()
|
||||
.chunks(8)
|
||||
.map(|chunk| {
|
||||
Some(Constant::F64(f64::from_le_bytes(
|
||||
chunk.try_into().expect("this shouldn't happen"),
|
||||
)))
|
||||
})
|
||||
.collect::<Option<Vec<Constant>>>()
|
||||
.map(Constant::Vec),
|
||||
_ => None,
|
||||
},
|
||||
// FIXME: implement other array type conversions.
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
},
|
||||
// FIXME: implement other conversions.
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user