Auto merge of #13200 - Jarcho:constant_no_typeck, r=Alexendoo
Don't use `LateContext` in the constant evaluator This also changes the interface to require explicitly creating the context. `constant` could be added back in, but the others are probably not worth it. A couple of bugs have been fixed. The wrong `TypeckResults` was used once when evaluating a constant, and the wrong `ParamEnv` was used by some callers (there wasn't a way to use the correct one). changelog: none
This commit is contained in:
commit
b1e87922c1
54 changed files with 395 additions and 386 deletions
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_help;
|
||||
use clippy_utils::is_inside_always_const_context;
|
||||
use clippy_utils::macros::{find_assert_args, root_macro_call_first_node, PanicExpn};
|
||||
|
|
@ -43,7 +43,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnConstants {
|
|||
let Some((condition, panic_expn)) = find_assert_args(cx, e, macro_call.expn) else {
|
||||
return;
|
||||
};
|
||||
let Some(Constant::Bool(val)) = constant(cx, cx.typeck_results(), condition) else {
|
||||
let Some(Constant::Bool(val)) = ConstEvalCtxt::new(cx).eval(condition) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use super::CAST_NAN_TO_INT;
|
||||
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_note;
|
||||
use rustc_hir::Expr;
|
||||
use rustc_lint::LateContext;
|
||||
|
|
@ -20,7 +20,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
|
|||
}
|
||||
|
||||
fn is_known_nan(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
|
||||
match constant(cx, cx.typeck_results(), e) {
|
||||
match ConstEvalCtxt::new(cx).eval(e) {
|
||||
// FIXME(f16_f128): add these types when nan checks are available on all platforms
|
||||
Some(Constant::F64(n)) => n.is_nan(),
|
||||
Some(Constant::F32(n)) => n.is_nan(),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
||||
use clippy_utils::expr_or_init;
|
||||
use clippy_utils::source::snippet;
|
||||
|
|
@ -15,7 +15,7 @@ use rustc_target::abi::IntegerType;
|
|||
use super::{utils, CAST_ENUM_TRUNCATION, CAST_POSSIBLE_TRUNCATION};
|
||||
|
||||
fn constant_int(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<u128> {
|
||||
if let Some(Constant::Int(c)) = constant(cx, cx.typeck_results(), expr) {
|
||||
if let Some(Constant::Int(c)) = ConstEvalCtxt::new(cx).eval(expr) {
|
||||
Some(c)
|
||||
} else {
|
||||
None
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::convert::Infallible;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::visitors::{for_each_expr_without_closures, Descend};
|
||||
use clippy_utils::{method_chain_args, sext};
|
||||
|
|
@ -88,7 +88,7 @@ fn get_const_signed_int_eval<'cx>(
|
|||
) -> Option<i128> {
|
||||
let ty = ty.into().unwrap_or_else(|| cx.typeck_results().expr_ty(expr));
|
||||
|
||||
if let Constant::Int(n) = constant(cx, cx.typeck_results(), expr)?
|
||||
if let Constant::Int(n) = ConstEvalCtxt::new(cx).eval(expr)?
|
||||
&& let ty::Int(ity) = *ty.kind()
|
||||
{
|
||||
return Some(sext(cx.tcx, n, ity));
|
||||
|
|
@ -103,7 +103,7 @@ fn get_const_unsigned_int_eval<'cx>(
|
|||
) -> Option<u128> {
|
||||
let ty = ty.into().unwrap_or_else(|| cx.typeck_results().expr_ty(expr));
|
||||
|
||||
if let Constant::Int(n) = constant(cx, cx.typeck_results(), expr)?
|
||||
if let Constant::Int(n) = ConstEvalCtxt::new(cx).eval(expr)?
|
||||
&& let ty::Uint(_ity) = *ty.kind()
|
||||
{
|
||||
return Some(n);
|
||||
|
|
|
|||
|
|
@ -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| mir_to_const(cx, c)) {
|
||||
if let Some(Constant::Int(val)) = constant.and_then(|c| mir_to_const(cx.tcx, c)) {
|
||||
if let ty::Adt(adt, _) = ty.kind() {
|
||||
if adt.is_enum() {
|
||||
ty = adt.repr().discr_type().to_ty(cx.tcx);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use clippy_utils::consts::Constant::{Int, F32, F64};
|
||||
use clippy_utils::consts::{constant, constant_simple, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::{
|
||||
eq_expr_value, get_parent_expr, higher, is_in_const_context, is_inherent_method_call, is_no_std_crate,
|
||||
|
|
@ -112,7 +112,7 @@ declare_lint_pass!(FloatingPointArithmetic => [
|
|||
// Returns the specialized log method for a given base if base is constant
|
||||
// and is one of 2, 10 and e
|
||||
fn get_specialized_log_method(cx: &LateContext<'_>, base: &Expr<'_>) -> Option<&'static str> {
|
||||
if let Some(value) = constant(cx, cx.typeck_results(), base) {
|
||||
if let Some(value) = ConstEvalCtxt::new(cx).eval(base) {
|
||||
if F32(2.0) == value || F64(2.0) == value {
|
||||
return Some("log2");
|
||||
} else if F32(10.0) == value || F64(10.0) == value {
|
||||
|
|
@ -182,10 +182,8 @@ fn check_ln1p(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) {
|
|||
rhs,
|
||||
) = receiver.kind
|
||||
{
|
||||
let recv = match (
|
||||
constant(cx, cx.typeck_results(), lhs),
|
||||
constant(cx, cx.typeck_results(), rhs),
|
||||
) {
|
||||
let ecx = ConstEvalCtxt::new(cx);
|
||||
let recv = match (ecx.eval(lhs), ecx.eval(rhs)) {
|
||||
(Some(value), _) if F32(1.0) == value || F64(1.0) == value => rhs,
|
||||
(_, Some(value)) if F32(1.0) == value || F64(1.0) == value => lhs,
|
||||
_ => return,
|
||||
|
|
@ -230,7 +228,7 @@ fn get_integer_from_float_constant(value: &Constant<'_>) -> Option<i32> {
|
|||
|
||||
fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) {
|
||||
// Check receiver
|
||||
if let Some(value) = constant(cx, cx.typeck_results(), receiver) {
|
||||
if let Some(value) = ConstEvalCtxt::new(cx).eval(receiver) {
|
||||
if let Some(method) = if F32(f32_consts::E) == value || F64(f64_consts::E) == value {
|
||||
Some("exp")
|
||||
} else if F32(2.0) == value || F64(2.0) == value {
|
||||
|
|
@ -251,7 +249,7 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args:
|
|||
}
|
||||
|
||||
// Check argument
|
||||
if let Some(value) = constant(cx, cx.typeck_results(), &args[0]) {
|
||||
if let Some(value) = ConstEvalCtxt::new(cx).eval(&args[0]) {
|
||||
let (lint, help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value {
|
||||
(
|
||||
SUBOPTIMAL_FLOPS,
|
||||
|
|
@ -291,7 +289,7 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args:
|
|||
}
|
||||
|
||||
fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) {
|
||||
if let Some(value) = constant(cx, cx.typeck_results(), &args[0]) {
|
||||
if let Some(value) = ConstEvalCtxt::new(cx).eval(&args[0]) {
|
||||
if value == Int(2) {
|
||||
if let Some(parent) = get_parent_expr(cx, expr) {
|
||||
if let Some(grandparent) = get_parent_expr(cx, parent) {
|
||||
|
|
@ -397,8 +395,9 @@ fn detect_hypot(cx: &LateContext<'_>, receiver: &Expr<'_>) -> Option<String> {
|
|||
) = &add_rhs.kind
|
||||
&& lmethod_name.as_str() == "powi"
|
||||
&& rmethod_name.as_str() == "powi"
|
||||
&& let Some(lvalue) = constant(cx, cx.typeck_results(), largs_1)
|
||||
&& let Some(rvalue) = constant(cx, cx.typeck_results(), rargs_1)
|
||||
&& let ecx = ConstEvalCtxt::new(cx)
|
||||
&& let Some(lvalue) = ecx.eval(largs_1)
|
||||
&& let Some(rvalue) = ecx.eval(rargs_1)
|
||||
&& Int(2) == lvalue
|
||||
&& Int(2) == rvalue
|
||||
{
|
||||
|
|
@ -438,7 +437,7 @@ fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
|||
rhs,
|
||||
) = expr.kind
|
||||
&& cx.typeck_results().expr_ty(lhs).is_floating_point()
|
||||
&& let Some(value) = constant(cx, cx.typeck_results(), rhs)
|
||||
&& let Some(value) = ConstEvalCtxt::new(cx).eval(rhs)
|
||||
&& (F32(1.0) == value || F64(1.0) == value)
|
||||
&& let ExprKind::MethodCall(path, self_arg, ..) = &lhs.kind
|
||||
&& cx.typeck_results().expr_ty(self_arg).is_floating_point()
|
||||
|
|
@ -552,7 +551,7 @@ fn is_testing_negative(cx: &LateContext<'_>, expr: &Expr<'_>, test: &Expr<'_>) -
|
|||
|
||||
/// Returns true iff expr is some zero literal
|
||||
fn is_zero(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||
match constant_simple(cx, cx.typeck_results(), expr) {
|
||||
match ConstEvalCtxt::new(cx).eval_simple(expr) {
|
||||
Some(Int(i)) => i == 0,
|
||||
Some(F32(f)) => f == 0.0,
|
||||
Some(F64(f)) => f == 0.0,
|
||||
|
|
@ -696,8 +695,9 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
|||
mul_lhs,
|
||||
mul_rhs,
|
||||
) = &div_lhs.kind
|
||||
&& let Some(rvalue) = constant(cx, cx.typeck_results(), div_rhs)
|
||||
&& let Some(lvalue) = constant(cx, cx.typeck_results(), mul_rhs)
|
||||
&& let ecx = ConstEvalCtxt::new(cx)
|
||||
&& let Some(rvalue) = ecx.eval(div_rhs)
|
||||
&& let Some(lvalue) = ecx.eval(mul_rhs)
|
||||
{
|
||||
// TODO: also check for constant values near PI/180 or 180/PI
|
||||
if (F32(f32_consts::PI) == rvalue || F64(f64_consts::PI) == rvalue)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
//! lint on if branches that could be swapped so no `!` operation is necessary
|
||||
//! on the condition
|
||||
|
||||
use clippy_utils::consts::{constant_simple, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_help;
|
||||
use clippy_utils::is_else_clause;
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
|
||||
|
|
@ -49,7 +49,7 @@ declare_clippy_lint! {
|
|||
declare_lint_pass!(IfNotElse => [IF_NOT_ELSE]);
|
||||
|
||||
fn is_zero_const(expr: &Expr<'_>, cx: &LateContext<'_>) -> bool {
|
||||
if let Some(value) = constant_simple(cx, cx.typeck_results(), expr) {
|
||||
if let Some(value) = ConstEvalCtxt::new(cx).eval_simple(expr) {
|
||||
return Constant::Int(0) == value;
|
||||
}
|
||||
false
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::get_parent_expr;
|
||||
use clippy_utils::source::snippet_with_context;
|
||||
|
|
@ -117,11 +117,11 @@ fn get_int_max(ty: Ty<'_>) -> Option<u128> {
|
|||
|
||||
fn get_const<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<(u128, BinOpKind, &'tcx Expr<'tcx>)> {
|
||||
if let ExprKind::Binary(op, l, r) = expr.kind {
|
||||
let tr = cx.typeck_results();
|
||||
if let Some(Constant::Int(c)) = constant(cx, tr, r) {
|
||||
let ecx = ConstEvalCtxt::new(cx);
|
||||
if let Some(Constant::Int(c)) = ecx.eval(r) {
|
||||
return Some((c, op.node, l));
|
||||
};
|
||||
if let Some(Constant::Int(c)) = constant(cx, tr, l) {
|
||||
if let Some(Constant::Int(c)) = ecx.eval(l) {
|
||||
return Some((c, invert_op(op.node)?, r));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_config::msrvs::{self, Msrv};
|
||||
use clippy_config::Conf;
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::higher::IfLet;
|
||||
use clippy_utils::ty::is_copy;
|
||||
|
|
@ -246,7 +246,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'a, 'tcx> {
|
|||
&& let parent_id = cx.tcx.parent_hir_id(expr.hir_id)
|
||||
&& let hir::Node::Expr(parent_expr) = cx.tcx.hir_node(parent_id)
|
||||
&& let hir::ExprKind::Index(_, index_expr, _) = parent_expr.kind
|
||||
&& let Some(Constant::Int(index_value)) = constant(cx, cx.typeck_results(), index_expr)
|
||||
&& let Some(Constant::Int(index_value)) = ConstEvalCtxt::new(cx).eval(index_expr)
|
||||
&& let Ok(index_value) = index_value.try_into()
|
||||
&& index_value < max_suggested_slice
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
//! lint on indexing and slicing operations
|
||||
|
||||
use clippy_config::Conf;
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
||||
use clippy_utils::ty::{deref_chain, get_adt_inherent_method};
|
||||
use clippy_utils::{higher, is_from_proc_macro};
|
||||
|
|
@ -177,7 +177,7 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing {
|
|||
return;
|
||||
}
|
||||
// Index is a constant uint.
|
||||
if let Some(constant) = constant(cx, cx.typeck_results(), index) {
|
||||
if let Some(constant) = ConstEvalCtxt::new(cx).eval(index) {
|
||||
// only `usize` index is legal in rust array index
|
||||
// leave other type to rustc
|
||||
if let Constant::Int(off) = constant
|
||||
|
|
@ -215,14 +215,15 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing {
|
|||
/// Returns a tuple of options with the start and end (exclusive) values of
|
||||
/// the range. If the start or end is not constant, None is returned.
|
||||
fn to_const_range(cx: &LateContext<'_>, range: higher::Range<'_>, array_size: u128) -> (Option<u128>, Option<u128>) {
|
||||
let s = range.start.map(|expr| constant(cx, cx.typeck_results(), expr));
|
||||
let ecx = ConstEvalCtxt::new(cx);
|
||||
let s = range.start.map(|expr| ecx.eval(expr));
|
||||
let start = match s {
|
||||
Some(Some(Constant::Int(x))) => Some(x),
|
||||
Some(_) => None,
|
||||
None => Some(0),
|
||||
};
|
||||
|
||||
let e = range.end.map(|expr| constant(cx, cx.typeck_results(), expr));
|
||||
let e = range.end.map(|expr| ecx.eval(expr));
|
||||
let end = match e {
|
||||
Some(Some(Constant::Int(x))) => {
|
||||
if range.limits == RangeLimits::Closed {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use rustc_span::Span;
|
|||
|
||||
use clippy_utils::comparisons;
|
||||
use clippy_utils::comparisons::Rel;
|
||||
use clippy_utils::consts::{constant_full_int, FullInt};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, FullInt};
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::source::snippet;
|
||||
|
||||
|
|
@ -95,7 +95,7 @@ fn upcast_comparison_bounds_err<'tcx>(
|
|||
invert: bool,
|
||||
) {
|
||||
if let Some((lb, ub)) = lhs_bounds {
|
||||
if let Some(norm_rhs_val) = constant_full_int(cx, cx.typeck_results(), rhs) {
|
||||
if let Some(norm_rhs_val) = ConstEvalCtxt::new(cx).eval_full_int(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);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use super::WHILE_IMMUTABLE_CONDITION;
|
||||
use clippy_utils::consts::constant;
|
||||
use clippy_utils::consts::ConstEvalCtxt;
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::usage::mutated_variables;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
|
|
@ -10,7 +10,7 @@ use rustc_lint::LateContext;
|
|||
use std::ops::ControlFlow;
|
||||
|
||||
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, expr: &'tcx Expr<'_>) {
|
||||
if constant(cx, cx.typeck_results(), cond).is_some() {
|
||||
if ConstEvalCtxt::new(cx).eval(cond).is_some() {
|
||||
// A pure constant condition (e.g., `while false`) is not linted.
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_config::msrvs::{self, Msrv};
|
||||
use clippy_config::Conf;
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
|
||||
use clippy_utils::higher::If;
|
||||
use clippy_utils::sugg::Sugg;
|
||||
|
|
@ -122,8 +122,9 @@ impl<'tcx> ClampSuggestion<'tcx> {
|
|||
if max_type != min_type {
|
||||
return false;
|
||||
}
|
||||
if let Some(max) = constant(cx, cx.typeck_results(), self.params.max)
|
||||
&& let Some(min) = constant(cx, cx.typeck_results(), self.params.min)
|
||||
let ecx = ConstEvalCtxt::new(cx);
|
||||
if let Some(max) = ecx.eval(self.params.max)
|
||||
&& let Some(min) = ecx.eval(self.params.min)
|
||||
&& let Some(ord) = Constant::partial_cmp(cx.tcx, max_type, &min, &max)
|
||||
{
|
||||
ord != Ordering::Greater
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::{is_from_proc_macro, path_to_local};
|
||||
|
|
@ -95,8 +95,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods {
|
|||
|| cx.tcx.features().declared(sym!(const_float_classify))
|
||||
)
|
||||
&& let [first, second, const_1, const_2] = exprs
|
||||
&& let Some(const_1) = constant(cx, cx.typeck_results(), const_1)
|
||||
&& let Some(const_2) = constant(cx, cx.typeck_results(), const_2)
|
||||
&& let ecx = ConstEvalCtxt::new(cx)
|
||||
&& let Some(const_1) = ecx.eval(const_1)
|
||||
&& let Some(const_2) = ecx.eval(const_2)
|
||||
&& path_to_local(first).is_some_and(|f| path_to_local(second).is_some_and(|s| f == s))
|
||||
// The actual infinity check, we also allow `NEG_INFINITY` before` INFINITY` just in
|
||||
// case somebody does that for some reason
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_config::msrvs::{self, Msrv};
|
||||
use clippy_config::Conf;
|
||||
use clippy_utils::consts::{constant_full_int, FullInt};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, FullInt};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet_with_context;
|
||||
use clippy_utils::{is_in_const_context, path_to_local};
|
||||
|
|
@ -117,7 +117,7 @@ fn check_for_either_unsigned_int_constant<'a>(
|
|||
}
|
||||
|
||||
fn check_for_unsigned_int_constant<'a>(cx: &'a LateContext<'_>, expr: &'a Expr<'_>) -> Option<u128> {
|
||||
let int_const = constant_full_int(cx, cx.typeck_results(), expr)?;
|
||||
let int_const = ConstEvalCtxt::new(cx).eval_full_int(expr)?;
|
||||
match int_const {
|
||||
FullInt::S(s) => s.try_into().ok(),
|
||||
FullInt::U(u) => Some(u),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::sugg;
|
||||
use rustc_errors::Applicability;
|
||||
|
|
@ -66,7 +66,7 @@ fn parse_shift<'tcx>(
|
|||
BinOpKind::Shr => ShiftDirection::Right,
|
||||
_ => return None,
|
||||
};
|
||||
let const_expr = constant(cx, cx.typeck_results(), r)?;
|
||||
let const_expr = ConstEvalCtxt::new(cx).eval(r)?;
|
||||
if let Constant::Int(shift) = const_expr {
|
||||
return Some((dir, shift, l));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_config::msrvs::{self, Msrv};
|
||||
use clippy_config::Conf;
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::usage::mutated_variables;
|
||||
|
|
@ -147,7 +147,7 @@ fn len_arg<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx E
|
|||
|
||||
// Returns the length of the `expr` if it's a constant string or char.
|
||||
fn constant_length(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<u128> {
|
||||
let value = constant(cx, cx.typeck_results(), expr)?;
|
||||
let value = ConstEvalCtxt::new(cx).eval(expr)?;
|
||||
match value {
|
||||
Constant::Str(value) => Some(value.len() as u128),
|
||||
Constant::Char(value) => Some(value.len_utf8() as u128),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::consts::constant_simple;
|
||||
use clippy_utils::consts::ConstEvalCtxt;
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
|
|
@ -69,7 +69,7 @@ fn check_and_lint<'tcx>(
|
|||
&& let Some(ty_name) = find_type_name(cx, ty)
|
||||
&& let Some(or_body_snippet) = snippet_opt(cx, else_expr.span)
|
||||
&& let Some(indent) = indent_of(cx, expr.span)
|
||||
&& constant_simple(cx, cx.typeck_results(), else_expr).is_some()
|
||||
&& ConstEvalCtxt::new(cx).eval_simple(else_expr).is_some()
|
||||
{
|
||||
lint(cx, expr, let_expr, ty_name, or_body_snippet, indent);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::consts::{constant, constant_full_int, mir_to_const, FullInt};
|
||||
use clippy_utils::consts::{mir_to_const, ConstEvalCtxt, FullInt};
|
||||
use clippy_utils::diagnostics::span_lint_and_note;
|
||||
use core::cmp::Ordering;
|
||||
use rustc_hir::{Arm, Expr, PatKind, RangeEnd};
|
||||
|
|
@ -34,19 +34,19 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
|
|||
if let Arm { pat, guard: None, .. } = *arm {
|
||||
if let PatKind::Range(ref lhs, ref rhs, range_end) = pat.kind {
|
||||
let lhs_const = if let Some(lhs) = lhs {
|
||||
constant(cx, cx.typeck_results(), lhs)?
|
||||
ConstEvalCtxt::new(cx).eval(lhs)?
|
||||
} else {
|
||||
let min_val_const = ty.numeric_min_val(cx.tcx)?;
|
||||
mir_to_const(cx, mir::Const::from_ty_const(min_val_const, ty, cx.tcx))?
|
||||
mir_to_const(cx.tcx, mir::Const::from_ty_const(min_val_const, ty, cx.tcx))?
|
||||
};
|
||||
let rhs_const = if let Some(rhs) = rhs {
|
||||
constant(cx, cx.typeck_results(), rhs)?
|
||||
ConstEvalCtxt::new(cx).eval(rhs)?
|
||||
} else {
|
||||
let max_val_const = ty.numeric_max_val(cx.tcx)?;
|
||||
mir_to_const(cx, mir::Const::from_ty_const(max_val_const, ty, cx.tcx))?
|
||||
mir_to_const(cx.tcx, mir::Const::from_ty_const(max_val_const, ty, cx.tcx))?
|
||||
};
|
||||
let lhs_val = lhs_const.int_value(cx, ty)?;
|
||||
let rhs_val = rhs_const.int_value(cx, ty)?;
|
||||
let lhs_val = lhs_const.int_value(cx.tcx, ty)?;
|
||||
let rhs_val = rhs_const.int_value(cx.tcx, ty)?;
|
||||
let rhs_bound = match range_end {
|
||||
RangeEnd::Included => EndBound::Included(rhs_val),
|
||||
RangeEnd::Excluded => EndBound::Excluded(rhs_val),
|
||||
|
|
@ -58,7 +58,7 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
|
|||
}
|
||||
|
||||
if let PatKind::Lit(value) = pat.kind {
|
||||
let value = constant_full_int(cx, cx.typeck_results(), value)?;
|
||||
let value = ConstEvalCtxt::new(cx).eval_full_int(value)?;
|
||||
return Some(SpannedRange {
|
||||
span: pat.span,
|
||||
node: (value, EndBound::Included(value)),
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use super::IS_DIGIT_ASCII_RADIX;
|
||||
use clippy_config::msrvs::{self, Msrv};
|
||||
use clippy_utils::consts::{constant_full_int, FullInt};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, FullInt};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use rustc_errors::Applicability;
|
||||
|
|
@ -24,7 +24,7 @@ pub(super) fn check<'tcx>(
|
|||
return;
|
||||
}
|
||||
|
||||
if let Some(radix_val) = constant_full_int(cx, cx.typeck_results(), radix) {
|
||||
if let Some(radix_val) = ConstEvalCtxt::new(cx).eval_full_int(radix) {
|
||||
let (num, replacement) = match radix_val {
|
||||
FullInt::S(10) | FullInt::U(10) => (10, "is_ascii_digit"),
|
||||
FullInt::S(16) | FullInt::U(16) => (16, "is_ascii_hexdigit"),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::consts::constant_is_empty;
|
||||
use clippy_utils::consts::ConstEvalCtxt;
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::{find_binding_init, path_to_local};
|
||||
use rustc_hir::{Expr, HirId};
|
||||
|
|
@ -18,7 +18,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_
|
|||
if !receiver.span.eq_ctxt(init_expr.span) {
|
||||
return;
|
||||
}
|
||||
if let Some(init_is_empty) = constant_is_empty(cx, init_expr) {
|
||||
if let Some(init_is_empty) = ConstEvalCtxt::new(cx).eval_is_empty(init_expr) {
|
||||
span_lint(
|
||||
cx,
|
||||
CONST_IS_EMPTY,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use clippy_utils::{is_lang_item_or_ctor, is_trait_method};
|
||||
|
|
@ -14,7 +14,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr
|
|||
if let OwnerNode::Item(item) = cx.tcx.hir_owner_node(cx.tcx.hir().get_parent_item(expr.hir_id))
|
||||
&& let def_id = item.owner_id.to_def_id()
|
||||
&& is_trait_method(cx, expr, sym::Iterator)
|
||||
&& let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), arg)
|
||||
&& let Some(Constant::Int(0)) = ConstEvalCtxt::new(cx).eval(arg)
|
||||
&& !is_lang_item_or_ctor(cx, def_id, LangItem::IteratorNext)
|
||||
{
|
||||
let mut app = Applicability::MachineApplicable;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::{is_from_proc_macro, is_trait_method};
|
||||
use rustc_errors::Applicability;
|
||||
|
|
@ -11,7 +11,7 @@ use super::ITER_SKIP_ZERO;
|
|||
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg_expr: &Expr<'_>) {
|
||||
if !expr.span.from_expansion()
|
||||
&& is_trait_method(cx, expr, sym::Iterator)
|
||||
&& let Some(arg) = constant(cx, cx.typeck_results(), arg_expr).and_then(|constant| {
|
||||
&& let Some(arg) = ConstEvalCtxt::new(cx).eval(arg_expr).and_then(|constant| {
|
||||
if let Constant::Int(arg) = constant {
|
||||
Some(arg)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::is_trait_method;
|
||||
use rustc_hir as hir;
|
||||
|
|
@ -9,7 +9,7 @@ use super::ITERATOR_STEP_BY_ZERO;
|
|||
|
||||
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, arg: &'tcx hir::Expr<'_>) {
|
||||
if is_trait_method(cx, expr, sym::Iterator) {
|
||||
if let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), arg) {
|
||||
if let Some(Constant::Int(0)) = ConstEvalCtxt::new(cx).eval(arg) {
|
||||
span_lint(
|
||||
cx,
|
||||
ITERATOR_STEP_BY_ZERO,
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ mod zst_offset;
|
|||
|
||||
use clippy_config::msrvs::{self, Msrv};
|
||||
use clippy_config::Conf;
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
|
||||
use clippy_utils::macros::FormatArgsStorage;
|
||||
use clippy_utils::ty::{contains_ty_adt_constructor_opaque, implements_trait, is_copy, is_type_diagnostic_item};
|
||||
|
|
@ -4915,13 +4915,13 @@ impl Methods {
|
|||
str_split::check(cx, expr, recv, arg);
|
||||
},
|
||||
("splitn" | "rsplitn", [count_arg, pat_arg]) => {
|
||||
if let Some(Constant::Int(count)) = constant(cx, cx.typeck_results(), count_arg) {
|
||||
if let Some(Constant::Int(count)) = ConstEvalCtxt::new(cx).eval(count_arg) {
|
||||
suspicious_splitn::check(cx, name, expr, recv, count);
|
||||
str_splitn::check(cx, name, expr, recv, pat_arg, count, &self.msrv);
|
||||
}
|
||||
},
|
||||
("splitn_mut" | "rsplitn_mut", [count_arg, _]) => {
|
||||
if let Some(Constant::Int(count)) = constant(cx, cx.typeck_results(), count_arg) {
|
||||
if let Some(Constant::Int(count)) = ConstEvalCtxt::new(cx).eval(count_arg) {
|
||||
suspicious_splitn::check(cx, name, expr, recv, count);
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::ty::is_type_lang_item;
|
||||
|
|
@ -14,7 +14,7 @@ pub(super) fn check<'tcx>(
|
|||
recv: &'tcx Expr<'_>,
|
||||
repeat_arg: &'tcx Expr<'_>,
|
||||
) {
|
||||
if constant(cx, cx.typeck_results(), repeat_arg) == Some(Constant::Int(1)) {
|
||||
if ConstEvalCtxt::new(cx).eval(repeat_arg) == Some(Constant::Int(1)) {
|
||||
let ty = cx.typeck_results().expr_ty(recv).peel_refs();
|
||||
if ty.is_str() {
|
||||
span_lint_and_sugg(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use clippy_config::msrvs::{self, Msrv};
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
|
||||
use clippy_utils::source::snippet_with_context;
|
||||
use clippy_utils::usage::local_used_after_expr;
|
||||
|
|
@ -301,7 +301,7 @@ fn parse_iter_usage<'tcx>(
|
|||
};
|
||||
},
|
||||
("nth" | "skip", [idx_expr]) if cx.tcx.trait_of_item(did) == Some(iter_id) => {
|
||||
if let Some(Constant::Int(idx)) = constant(cx, cx.typeck_results(), idx_expr) {
|
||||
if let Some(Constant::Int(idx)) = ConstEvalCtxt::new(cx).eval(idx_expr) {
|
||||
let span = if name.ident.as_str() == "nth" {
|
||||
e.span
|
||||
} else if let Some((_, Node::Expr(next_expr))) = iter.next()
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::cmp::Ordering;
|
|||
use super::UNNECESSARY_MIN_OR_MAX;
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
|
||||
use clippy_utils::consts::{constant, constant_with_source, Constant, ConstantSource, FullInt};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant, ConstantSource, FullInt};
|
||||
use clippy_utils::source::snippet;
|
||||
|
||||
use rustc_errors::Applicability;
|
||||
|
|
@ -20,10 +20,9 @@ pub(super) fn check<'tcx>(
|
|||
arg: &'tcx Expr<'_>,
|
||||
) {
|
||||
let typeck_results = cx.typeck_results();
|
||||
if let Some((left, ConstantSource::Local | ConstantSource::CoreConstant)) =
|
||||
constant_with_source(cx, typeck_results, recv)
|
||||
&& let Some((right, ConstantSource::Local | ConstantSource::CoreConstant)) =
|
||||
constant_with_source(cx, typeck_results, arg)
|
||||
let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck_results);
|
||||
if let Some((left, ConstantSource::Local | ConstantSource::CoreConstant)) = ecx.eval_with_source(recv)
|
||||
&& let Some((right, ConstantSource::Local | ConstantSource::CoreConstant)) = ecx.eval_with_source(arg)
|
||||
{
|
||||
let Some(ord) = Constant::partial_cmp(cx.tcx, typeck_results.expr_ty(recv), &left, &right) else {
|
||||
return;
|
||||
|
|
@ -78,9 +77,9 @@ enum Extrema {
|
|||
fn detect_extrema<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<Extrema> {
|
||||
let ty = cx.typeck_results().expr_ty(expr);
|
||||
|
||||
let cv = constant(cx, cx.typeck_results(), expr)?;
|
||||
let cv = ConstEvalCtxt::new(cx).eval(expr)?;
|
||||
|
||||
match (cv.int_value(cx, ty)?, ty.kind()) {
|
||||
match (cv.int_value(cx.tcx, ty)?, ty.kind()) {
|
||||
(FullInt::S(i), &ty::Int(ity)) if i == i128::MIN >> (128 - ity.bit_width()?) => Some(Extrema::Minimum),
|
||||
(FullInt::S(i), &ty::Int(ity)) if i == i128::MAX >> (128 - ity.bit_width()?) => Some(Extrema::Maximum),
|
||||
(FullInt::U(i), &ty::Uint(uty)) if i == u128::MAX >> (128 - uty.bit_width()?) => Some(Extrema::Maximum),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::consts::{constant_simple, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::is_trait_method;
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
|
|
@ -106,15 +106,11 @@ fn fetch_const<'a, 'tcx>(
|
|||
if args.next().is_some() {
|
||||
return None;
|
||||
}
|
||||
constant_simple(cx, cx.typeck_results(), first_arg).map_or_else(
|
||||
|| constant_simple(cx, cx.typeck_results(), second_arg).map(|c| (m, c, first_arg)),
|
||||
|c| {
|
||||
if constant_simple(cx, cx.typeck_results(), second_arg).is_none() {
|
||||
// otherwise ignore
|
||||
Some((m, c, second_arg))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
)
|
||||
let ecx = ConstEvalCtxt::new(cx);
|
||||
match (ecx.eval_simple(first_arg), ecx.eval_simple(second_arg)) {
|
||||
(Some(c), None) => Some((m, c, second_arg)),
|
||||
(None, Some(c)) => Some((m, c, first_arg)),
|
||||
// otherwise ignore
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use rustc_lint::LateContext;
|
|||
use rustc_middle::ty;
|
||||
|
||||
use clippy_utils::comparisons::{normalize_comparison, Rel};
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_help;
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::ty::is_isize_or_usize;
|
||||
|
|
@ -121,7 +121,7 @@ fn detect_absurd_comparison<'tcx>(
|
|||
fn detect_extreme_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<ExtremeExpr<'tcx>> {
|
||||
let ty = cx.typeck_results().expr_ty(expr);
|
||||
|
||||
let cv = constant(cx, cx.typeck_results(), expr)?;
|
||||
let cv = ConstEvalCtxt::new(cx).eval(expr)?;
|
||||
|
||||
let which = match (ty.kind(), cv) {
|
||||
(&ty::Bool, Constant::Bool(false)) | (&ty::Uint(_), Constant::Int(0)) => ExtremeType::Minimum,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use super::ARITHMETIC_SIDE_EFFECTS;
|
||||
use clippy_config::Conf;
|
||||
use clippy_utils::consts::{constant, constant_simple, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use clippy_utils::{expr_or_init, is_from_proc_macro, is_lint_allowed, peel_hir_expr_refs, peel_hir_expr_unary};
|
||||
|
|
@ -162,7 +162,7 @@ impl ArithmeticSideEffects {
|
|||
{
|
||||
return Some(n.get());
|
||||
}
|
||||
if let Some(Constant::Int(n)) = constant(cx, cx.typeck_results(), expr) {
|
||||
if let Some(Constant::Int(n)) = ConstEvalCtxt::new(cx).eval(expr) {
|
||||
return Some(n);
|
||||
}
|
||||
None
|
||||
|
|
@ -200,7 +200,7 @@ impl ArithmeticSideEffects {
|
|||
lhs: &'tcx hir::Expr<'_>,
|
||||
rhs: &'tcx hir::Expr<'_>,
|
||||
) {
|
||||
if constant_simple(cx, cx.typeck_results(), expr).is_some() {
|
||||
if ConstEvalCtxt::new(cx).eval_simple(expr).is_some() {
|
||||
return;
|
||||
}
|
||||
if !matches!(
|
||||
|
|
@ -280,7 +280,7 @@ impl ArithmeticSideEffects {
|
|||
let Some(arg) = args.first() else {
|
||||
return;
|
||||
};
|
||||
if constant_simple(cx, cx.typeck_results(), receiver).is_some() {
|
||||
if ConstEvalCtxt::new(cx).eval_simple(receiver).is_some() {
|
||||
return;
|
||||
}
|
||||
let instance_ty = cx.typeck_results().expr_ty(receiver);
|
||||
|
|
@ -308,7 +308,7 @@ impl ArithmeticSideEffects {
|
|||
let hir::UnOp::Neg = un_op else {
|
||||
return;
|
||||
};
|
||||
if constant(cx, cx.typeck_results(), un_expr).is_some() {
|
||||
if ConstEvalCtxt::new(cx).eval(un_expr).is_some() {
|
||||
return;
|
||||
}
|
||||
let ty = cx.typeck_results().expr_ty(expr).peel_refs();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind};
|
||||
use rustc_lint::LateContext;
|
||||
|
|
@ -166,7 +166,7 @@ fn check_ineffective_gt(cx: &LateContext<'_>, span: Span, m: u128, c: u128, op:
|
|||
}
|
||||
|
||||
fn fetch_int_literal(cx: &LateContext<'_>, lit: &Expr<'_>) -> Option<u128> {
|
||||
match constant(cx, cx.typeck_results(), lit)? {
|
||||
match ConstEvalCtxt::new(cx).eval(lit)? {
|
||||
Constant::Int(n) => Some(n),
|
||||
_ => None,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::layout::HasTyCtxt;
|
||||
|
|
@ -20,13 +20,14 @@ use super::{IMPOSSIBLE_COMPARISONS, REDUNDANT_COMPARISONS};
|
|||
// Flip yoda conditionals, turnings expressions like `42 < x` into `x > 42`
|
||||
fn comparison_to_const<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
typeck: &TypeckResults<'tcx>,
|
||||
typeck: &'tcx TypeckResults<'tcx>,
|
||||
expr: &'tcx Expr<'tcx>,
|
||||
) -> Option<(CmpOp, &'tcx Expr<'tcx>, &'tcx Expr<'tcx>, Constant<'tcx>, Ty<'tcx>)> {
|
||||
if let ExprKind::Binary(operator, left, right) = expr.kind
|
||||
&& let Ok(cmp_op) = CmpOp::try_from(operator.node)
|
||||
{
|
||||
match (constant(cx, typeck, left), constant(cx, typeck, right)) {
|
||||
let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck);
|
||||
match (ecx.eval(left), ecx.eval(right)) {
|
||||
(Some(_), Some(_)) => None,
|
||||
(_, Some(con)) => Some((cmp_op, left, right, con, typeck.expr_ty(right))),
|
||||
(Some(con), _) => Some((cmp_op.reverse(), right, left, con, typeck.expr_ty(left))),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
|
|
@ -19,7 +19,7 @@ pub(crate) fn check<'tcx>(
|
|||
if op == BinOpKind::Div
|
||||
&& let ExprKind::MethodCall(method_path, self_arg, [], _) = left.kind
|
||||
&& is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_arg).peel_refs(), sym::Duration)
|
||||
&& let Some(Constant::Int(divisor)) = constant(cx, cx.typeck_results(), right)
|
||||
&& let Some(Constant::Int(divisor)) = ConstEvalCtxt::new(cx).eval(right)
|
||||
{
|
||||
let suggested_fn = match (method_path.ident.as_str(), divisor) {
|
||||
("subsec_micros", 1_000) | ("subsec_nanos", 1_000_000) => "subsec_millis",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::consts::{constant_simple, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::ty::same_type_and_consts;
|
||||
|
||||
|
|
@ -34,12 +34,12 @@ fn different_types(tck: &TypeckResults<'_>, input: &Expr<'_>, output: &Expr<'_>)
|
|||
|
||||
fn check_op<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
tck: &TypeckResults<'tcx>,
|
||||
tck: &'tcx TypeckResults<'tcx>,
|
||||
op: &Expr<'tcx>,
|
||||
other: &Expr<'tcx>,
|
||||
parent: &Expr<'tcx>,
|
||||
) {
|
||||
if constant_simple(cx, tck, op) == Some(Constant::Int(0)) {
|
||||
if ConstEvalCtxt::with_env(cx.tcx, cx.param_env, tck).eval_simple(op) == Some(Constant::Int(0)) {
|
||||
if different_types(tck, other, parent) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::consts::{constant_with_source, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::get_item_name;
|
||||
use clippy_utils::sugg::Sugg;
|
||||
|
|
@ -17,12 +17,14 @@ pub(crate) fn check<'tcx>(
|
|||
right: &'tcx Expr<'_>,
|
||||
) {
|
||||
if (op == BinOpKind::Eq || op == BinOpKind::Ne) && is_float(cx, left) {
|
||||
let left_is_local = match constant_with_source(cx, cx.typeck_results(), left) {
|
||||
let typeck = cx.typeck_results();
|
||||
let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck);
|
||||
let left_is_local = match ecx.eval_with_source(left) {
|
||||
Some((c, s)) if !is_allowed(&c) => s.is_local(),
|
||||
Some(_) => return,
|
||||
None => true,
|
||||
};
|
||||
let right_is_local = match constant_with_source(cx, cx.typeck_results(), right) {
|
||||
let right_is_local = match ecx.eval_with_source(right) {
|
||||
Some((c, s)) if !is_allowed(&c) => s.is_local(),
|
||||
Some(_) => return,
|
||||
None => true,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::consts::{constant_full_int, constant_simple, Constant, FullInt};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant, FullInt};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use clippy_utils::{clip, peel_hir_expr_refs, unsext};
|
||||
|
|
@ -184,14 +184,13 @@ fn is_allowed(cx: &LateContext<'_>, cmp: BinOpKind, left: &Expr<'_>, right: &Exp
|
|||
&& cx.typeck_results().expr_ty(right).peel_refs().is_integral()
|
||||
// `1 << 0` is a common pattern in bit manipulation code
|
||||
&& !(cmp == BinOpKind::Shl
|
||||
&& constant_simple(cx, cx.typeck_results(), right) == Some(Constant::Int(0))
|
||||
&& constant_simple(cx, cx.typeck_results(), left) == Some(Constant::Int(1)))
|
||||
&& ConstEvalCtxt::new(cx).eval_simple(right) == Some(Constant::Int(0))
|
||||
&& ConstEvalCtxt::new(cx).eval_simple(left) == Some(Constant::Int(1)))
|
||||
}
|
||||
|
||||
fn check_remainder(cx: &LateContext<'_>, left: &Expr<'_>, right: &Expr<'_>, span: Span, arg: Span) {
|
||||
let lhs_const = constant_full_int(cx, cx.typeck_results(), left);
|
||||
let rhs_const = constant_full_int(cx, cx.typeck_results(), right);
|
||||
if match (lhs_const, rhs_const) {
|
||||
let ecx = ConstEvalCtxt::new(cx);
|
||||
if match (ecx.eval_full_int(left), ecx.eval_full_int(right)) {
|
||||
(Some(FullInt::S(lv)), Some(FullInt::S(rv))) => lv.abs() < rv.abs(),
|
||||
(Some(FullInt::U(lv)), Some(FullInt::U(rv))) => lv < rv,
|
||||
_ => return,
|
||||
|
|
@ -201,7 +200,7 @@ fn check_remainder(cx: &LateContext<'_>, left: &Expr<'_>, right: &Expr<'_>, span
|
|||
}
|
||||
|
||||
fn check_op(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span, parens: Parens, is_erased: bool) -> bool {
|
||||
if let Some(Constant::Int(v)) = constant_simple(cx, cx.typeck_results(), e).map(Constant::peel_refs) {
|
||||
if let Some(Constant::Int(v)) = ConstEvalCtxt::new(cx).eval_simple(e).map(Constant::peel_refs) {
|
||||
let check = match *cx.typeck_results().expr_ty(e).peel_refs().kind() {
|
||||
ty::Int(ity) => unsext(cx.tcx, -1_i128, ity),
|
||||
ty::Uint(uty) => clip(cx.tcx, !0, uty),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::sext;
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind, Node};
|
||||
|
|
@ -42,15 +42,11 @@ fn used_in_comparison_with_zero(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
|||
};
|
||||
|
||||
if op.node == BinOpKind::Eq || op.node == BinOpKind::Ne {
|
||||
if let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), rhs) {
|
||||
return true;
|
||||
}
|
||||
if let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), lhs) {
|
||||
return true;
|
||||
}
|
||||
let ecx = ConstEvalCtxt::new(cx);
|
||||
matches!(ecx.eval(lhs), Some(Constant::Int(0))) || matches!(ecx.eval(rhs), Some(Constant::Int(0)))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
struct OperandInfo {
|
||||
|
|
@ -60,7 +56,7 @@ struct OperandInfo {
|
|||
}
|
||||
|
||||
fn analyze_operand(operand: &Expr<'_>, cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<OperandInfo> {
|
||||
match constant(cx, cx.typeck_results(), operand) {
|
||||
match ConstEvalCtxt::new(cx).eval(operand) {
|
||||
Some(Constant::Int(v)) => match *cx.typeck_results().expr_ty(expr).kind() {
|
||||
ty::Int(ity) => {
|
||||
let value = sext(cx.tcx, v, ity);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use super::FLOAT_ARITHMETIC;
|
||||
use clippy_utils::consts::constant_simple;
|
||||
use clippy_utils::consts::ConstEvalCtxt;
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint::LateContext;
|
||||
|
|
@ -55,7 +55,7 @@ impl Context {
|
|||
return;
|
||||
}
|
||||
let ty = cx.typeck_results().expr_ty(arg);
|
||||
if constant_simple(cx, cx.typeck_results(), expr).is_none() && ty.is_floating_point() {
|
||||
if ConstEvalCtxt::new(cx).eval_simple(expr).is_none() && ty.is_floating_point() {
|
||||
span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected");
|
||||
self.expr_id = Some(expr.hir_id);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_config::msrvs::{self, Msrv};
|
||||
use clippy_config::Conf;
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
|
||||
use clippy_utils::source::{snippet, snippet_with_applicability, SpanRangeExt};
|
||||
use clippy_utils::sugg::Sugg;
|
||||
|
|
@ -319,7 +319,7 @@ fn check_range_bounds<'a, 'tcx>(cx: &'a LateContext<'tcx>, ex: &'a Expr<'_>) ->
|
|||
_ => return None,
|
||||
};
|
||||
if let Some(id) = path_to_local(l) {
|
||||
if let Some(c) = constant(cx, cx.typeck_results(), r) {
|
||||
if let Some(c) = ConstEvalCtxt::new(cx).eval(r) {
|
||||
return Some(RangeBounds {
|
||||
val: c,
|
||||
expr: r,
|
||||
|
|
@ -331,7 +331,7 @@ fn check_range_bounds<'a, 'tcx>(cx: &'a LateContext<'tcx>, ex: &'a Expr<'_>) ->
|
|||
});
|
||||
}
|
||||
} else if let Some(id) = path_to_local(r) {
|
||||
if let Some(c) = constant(cx, cx.typeck_results(), l) {
|
||||
if let Some(c) = ConstEvalCtxt::new(cx).eval(l) {
|
||||
return Some(RangeBounds {
|
||||
val: c,
|
||||
expr: l,
|
||||
|
|
@ -451,8 +451,9 @@ fn check_reversed_empty_range(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
|||
}) = higher::Range::hir(expr)
|
||||
&& let ty = cx.typeck_results().expr_ty(start)
|
||||
&& let ty::Int(_) | ty::Uint(_) = ty.kind()
|
||||
&& let Some(start_idx) = constant(cx, cx.typeck_results(), start)
|
||||
&& let Some(end_idx) = constant(cx, cx.typeck_results(), end)
|
||||
&& let ecx = ConstEvalCtxt::new(cx)
|
||||
&& let Some(start_idx) = ecx.eval(start)
|
||||
&& let Some(end_idx) = ecx.eval(end)
|
||||
&& let Some(ordering) = Constant::partial_cmp(cx.tcx, ty, &start_idx, &end_idx)
|
||||
&& is_empty_range(limits, ordering)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::{def_path_def_ids, path_def_id, paths};
|
||||
|
|
@ -148,7 +148,7 @@ fn lint_syntax_error(cx: &LateContext<'_>, error: ®ex_syntax::Error, unescape
|
|||
}
|
||||
|
||||
fn const_str<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> Option<String> {
|
||||
constant(cx, cx.typeck_results(), e).and_then(|c| match c {
|
||||
ConstEvalCtxt::new(cx).eval(e).and_then(|c| match c {
|
||||
Constant::Str(s) => Some(s),
|
||||
_ => None,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::higher::VecArgs;
|
||||
use clippy_utils::macros::matching_root_macro_call;
|
||||
|
|
@ -69,7 +69,7 @@ fn check_vec_macro(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
|||
&& let Some(VecArgs::Repeat(repeat_expr, len_expr)) = VecArgs::hir(cx, expr)
|
||||
&& fn_def_id(cx, repeat_expr).is_some_and(|did| match_def_path(cx, did, &paths::VEC_WITH_CAPACITY))
|
||||
&& !len_expr.span.from_expansion()
|
||||
&& let Some(Constant::Int(2..)) = constant(cx, cx.typeck_results(), expr_or_init(cx, len_expr))
|
||||
&& let Some(Constant::Int(2..)) = ConstEvalCtxt::new(cx).eval(expr_or_init(cx, len_expr))
|
||||
{
|
||||
emit_lint(
|
||||
cx,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::{is_integer_literal, is_path_diagnostic_item};
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
|
|
@ -33,10 +33,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t
|
|||
// Catching:
|
||||
// transmute over constants that resolve to `null`.
|
||||
ExprKind::Path(ref _qpath)
|
||||
if matches!(
|
||||
constant(cx, cx.typeck_results(), casts_peeled),
|
||||
Some(Constant::RawPtr(0))
|
||||
) =>
|
||||
if matches!(ConstEvalCtxt::new(cx).eval(casts_peeled), Some(Constant::RawPtr(0))) =>
|
||||
{
|
||||
lint_expr(cx, expr);
|
||||
true
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::{is_integer_literal, is_path_diagnostic_item};
|
||||
use rustc_hir::{Expr, ExprKind};
|
||||
|
|
@ -17,7 +17,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t
|
|||
|
||||
// Catching transmute over constants that resolve to `null`.
|
||||
if let ExprKind::Path(ref _qpath) = arg.kind
|
||||
&& let Some(Constant::RawPtr(0)) = constant(cx, cx.typeck_results(), arg)
|
||||
&& let Some(Constant::RawPtr(0)) = ConstEvalCtxt::new(cx).eval(arg)
|
||||
{
|
||||
span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG);
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::consts::{constant_simple, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet;
|
||||
use clippy_utils::ty::match_type;
|
||||
|
|
@ -93,7 +93,7 @@ impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol {
|
|||
if let ExprKind::Call(func, [arg]) = &expr.kind
|
||||
&& let ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(func).kind()
|
||||
&& match_def_path(cx, *def_id, &paths::SYMBOL_INTERN)
|
||||
&& let Some(Constant::Str(arg)) = constant_simple(cx, cx.typeck_results(), arg)
|
||||
&& let Some(Constant::Str(arg)) = ConstEvalCtxt::new(cx).eval_simple(arg)
|
||||
&& let value = Symbol::intern(&arg).as_u32()
|
||||
&& let Some(&def_id) = self.symbol_map.get(&value)
|
||||
{
|
||||
|
|
@ -199,7 +199,7 @@ impl InterningDefinedSymbol {
|
|||
});
|
||||
}
|
||||
// is a string constant
|
||||
if let Some(Constant::Str(s)) = constant_simple(cx, cx.typeck_results(), expr) {
|
||||
if let Some(Constant::Str(s)) = ConstEvalCtxt::new(cx).eval_simple(expr) {
|
||||
let value = Symbol::intern(&s).as_u32();
|
||||
// ...which matches a symbol constant
|
||||
if let Some(&def_id) = self.symbol_map.get(&value) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::consts::{constant_simple, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::def_path_res;
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use rustc_hir as hir;
|
||||
|
|
@ -32,9 +32,9 @@ impl<'tcx> LateLintPass<'tcx> for InvalidPaths {
|
|||
let mod_name = &cx.tcx.item_name(local_def_id.to_def_id());
|
||||
if mod_name.as_str() == "paths"
|
||||
&& let hir::ItemKind::Const(.., body_id) = item.kind
|
||||
&& let body = cx.tcx.hir().body(body_id)
|
||||
&& let typeck_results = cx.tcx.typeck_body(body_id)
|
||||
&& let Some(Constant::Vec(path)) = constant_simple(cx, typeck_results, body.value)
|
||||
&& let Some(Constant::Vec(path)) =
|
||||
ConstEvalCtxt::with_env(cx.tcx, cx.tcx.param_env(item.owner_id), cx.tcx.typeck(item.owner_id))
|
||||
.eval_simple(cx.tcx.hir().body(body_id).value)
|
||||
&& let Some(path) = path
|
||||
.iter()
|
||||
.map(|x| {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::ops::ControlFlow;
|
|||
|
||||
use clippy_config::msrvs::{self, Msrv};
|
||||
use clippy_config::Conf;
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_hir_and_then;
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::ty::is_copy;
|
||||
|
|
@ -159,7 +159,7 @@ impl UselessVec {
|
|||
|
||||
let snippet = match *vec_args {
|
||||
higher::VecArgs::Repeat(elem, len) => {
|
||||
if let Some(Constant::Int(len_constant)) = constant(cx, cx.typeck_results(), len) {
|
||||
if let Some(Constant::Int(len_constant)) = ConstEvalCtxt::new(cx).eval(len) {
|
||||
// vec![ty; N] works when ty is Clone, [ty; N] requires it to be Copy also
|
||||
if !is_copy(cx, cx.typeck_results().expr_ty(elem)) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use clippy_utils::consts::{constant_simple, Constant};
|
||||
use clippy_utils::consts::{ConstEvalCtxt, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_help;
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
|
|
@ -36,8 +36,9 @@ impl<'tcx> LateLintPass<'tcx> for ZeroDiv {
|
|||
// TODO - constant_simple does not fold many operations involving floats.
|
||||
// That's probably fine for this lint - it's pretty unlikely that someone would
|
||||
// do something like 0.0/(2.0 - 2.0), but it would be nice to warn on that case too.
|
||||
&& let Some(lhs_value) = constant_simple(cx, cx.typeck_results(), left)
|
||||
&& let Some(rhs_value) = constant_simple(cx, cx.typeck_results(), right)
|
||||
&& let ecx = ConstEvalCtxt::new(cx)
|
||||
&& let Some(lhs_value) = ecx.eval_simple(left)
|
||||
&& let Some(rhs_value) = ecx.eval_simple(right)
|
||||
// FIXME(f16_f128): add these types when eq is available on all platforms
|
||||
&& (Constant::F32(0.0) == lhs_value || Constant::F64(0.0) == lhs_value)
|
||||
&& (Constant::F32(0.0) == rhs_value || Constant::F64(0.0) == rhs_value)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue