Move const int value code to utils

This commit is contained in:
Michael Wright 2021-10-20 06:13:42 +02:00
parent 5bdd2cebe2
commit 4679eb3a0d
2 changed files with 71 additions and 65 deletions

View file

@ -1,5 +1,3 @@
use std::cmp::Ordering;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::layout::LayoutOf;
@ -7,11 +5,11 @@ use rustc_middle::ty::{self, IntTy, UintTy};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::Span;
use clippy_utils::comparisons;
use clippy_utils::comparisons::Rel;
use clippy_utils::consts::{constant, Constant};
use clippy_utils::consts::{constant_full_int, FullInt};
use clippy_utils::diagnostics::span_lint;
use clippy_utils::source::snippet;
use clippy_utils::{comparisons, sext};
declare_clippy_lint! {
/// ### What it does
@ -39,53 +37,6 @@ declare_clippy_lint! {
declare_lint_pass!(InvalidUpcastComparisons => [INVALID_UPCAST_COMPARISONS]);
#[derive(Copy, Clone, Debug, Eq)]
enum FullInt {
S(i128),
U(u128),
}
impl FullInt {
#[allow(clippy::cast_sign_loss)]
#[must_use]
fn cmp_s_u(s: i128, u: u128) -> Ordering {
if s < 0 {
Ordering::Less
} else if u > (i128::MAX as u128) {
Ordering::Greater
} else {
(s as u128).cmp(&u)
}
}
}
impl PartialEq for FullInt {
#[must_use]
fn eq(&self, other: &Self) -> bool {
self.partial_cmp(other).expect("`partial_cmp` only returns `Some(_)`") == Ordering::Equal
}
}
impl PartialOrd for FullInt {
#[must_use]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(match (self, other) {
(&Self::S(s), &Self::S(o)) => s.cmp(&o),
(&Self::U(s), &Self::U(o)) => s.cmp(&o),
(&Self::S(s), &Self::U(o)) => Self::cmp_s_u(s, o),
(&Self::U(s), &Self::S(o)) => Self::cmp_s_u(o, s).reverse(),
})
}
}
impl Ord for FullInt {
#[must_use]
fn cmp(&self, other: &Self) -> Ordering {
self.partial_cmp(other)
.expect("`partial_cmp` for FullInt can never return `None`")
}
}
fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_>, expr: &'a Expr<'_>) -> Option<(FullInt, FullInt)> {
if let ExprKind::Cast(cast_exp, _) = expr.kind {
let pre_cast_ty = cx.typeck_results().expr_ty(cast_exp);
@ -118,19 +69,6 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_>, expr: &'a Expr<'_>) ->
}
}
fn node_as_const_fullint<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<FullInt> {
let val = constant(cx, cx.typeck_results(), expr)?.0;
if let Constant::Int(const_int) = val {
match *cx.typeck_results().expr_ty(expr).kind() {
ty::Int(ity) => Some(FullInt::S(sext(cx.tcx, const_int, ity))),
ty::Uint(_) => Some(FullInt::U(const_int)),
_ => None,
}
} else {
None
}
}
fn err_upcast_comparison(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, always: bool) {
if let ExprKind::Cast(cast_val, _) = expr.kind {
span_lint(
@ -156,7 +94,7 @@ fn upcast_comparison_bounds_err<'tcx>(
invert: bool,
) {
if let Some((lb, ub)) = lhs_bounds {
if let Some(norm_rhs_val) = node_as_const_fullint(cx, rhs) {
if let Some(norm_rhs_val) = constant_full_int(cx, cx.typeck_results(), rhs) {
if rel == Rel::Eq || rel == Rel::Ne {
if norm_rhs_val < lb || norm_rhs_val > ub {
err_upcast_comparison(cx, span, lhs, rel == Rel::Ne);

View file

@ -155,6 +155,19 @@ impl Constant {
_ => None,
}
}
/// Returns the integer value or `None` if `self` or `val_type` is not integer type.
pub fn int_value(&self, cx: &LateContext<'_>, val_type: Ty<'_>) -> Option<FullInt> {
if let Constant::Int(const_int) = *self {
match *val_type.kind() {
ty::Int(ity) => Some(FullInt::S(sext(cx.tcx, const_int, ity))),
ty::Uint(_) => Some(FullInt::U(const_int)),
_ => None,
}
} else {
None
}
}
}
/// Parses a `LitKind` to a `Constant`.
@ -202,6 +215,61 @@ pub fn constant_simple<'tcx>(
constant(lcx, typeck_results, e).and_then(|(cst, res)| if res { None } else { Some(cst) })
}
pub fn constant_full_int(
lcx: &LateContext<'tcx>,
typeck_results: &ty::TypeckResults<'tcx>,
e: &Expr<'_>,
) -> Option<FullInt> {
constant_simple(lcx, typeck_results, e)?.int_value(lcx, typeck_results.expr_ty(e))
}
#[derive(Copy, Clone, Debug, Eq)]
pub enum FullInt {
S(i128),
U(u128),
}
impl FullInt {
#[allow(clippy::cast_sign_loss)]
#[must_use]
fn cmp_s_u(s: i128, u: u128) -> Ordering {
if s < 0 {
Ordering::Less
} else if u > (i128::MAX as u128) {
Ordering::Greater
} else {
(s as u128).cmp(&u)
}
}
}
impl PartialEq for FullInt {
#[must_use]
fn eq(&self, other: &Self) -> bool {
self.partial_cmp(other).expect("`partial_cmp` only returns `Some(_)`") == Ordering::Equal
}
}
impl PartialOrd for FullInt {
#[must_use]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(match (self, other) {
(&Self::S(s), &Self::S(o)) => s.cmp(&o),
(&Self::U(s), &Self::U(o)) => s.cmp(&o),
(&Self::S(s), &Self::U(o)) => Self::cmp_s_u(s, o),
(&Self::U(s), &Self::S(o)) => Self::cmp_s_u(o, s).reverse(),
})
}
}
impl Ord for FullInt {
#[must_use]
fn cmp(&self, other: &Self) -> Ordering {
self.partial_cmp(other)
.expect("`partial_cmp` for FullInt can never return `None`")
}
}
/// Creates a `ConstEvalLateContext` from the given `LateContext` and `TypeckResults`.
pub fn constant_context<'a, 'tcx>(
lcx: &'a LateContext<'tcx>,