Don't store LateContext in ConstEvalLateContext

This commit is contained in:
Jason Newcomb 2024-07-31 17:51:09 -04:00
parent 3779062955
commit d2cb227eb4
6 changed files with 75 additions and 78 deletions

View File

@ -51,7 +51,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
.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);

View File

@ -37,13 +37,13 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
constant(cx, cx.typeck_results(), 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)?
} 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)?;

View File

@ -20,7 +20,7 @@
// 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

View File

@ -34,7 +34,7 @@ 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>,

View File

@ -14,10 +14,12 @@
use rustc_lint::LateContext;
use rustc_middle::mir::interpret::{alloc_range, Scalar};
use rustc_middle::mir::ConstValue;
use rustc_middle::ty::{self, EarlyBinder, FloatTy, GenericArgsRef, IntTy, List, ScalarInt, Ty, TyCtxt, UintTy};
use rustc_middle::ty::{
self, EarlyBinder, FloatTy, GenericArgsRef, IntTy, List, ParamEnv, ScalarInt, Ty, TyCtxt, TypeckResults, UintTy,
};
use rustc_middle::{bug, mir, span_bug};
use rustc_span::def_id::DefId;
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::symbol::Ident;
use rustc_span::{sym, SyntaxContext};
use rustc_target::abi::Size;
use std::cmp::Ordering;
@ -339,25 +341,25 @@ pub fn is_local(&self) -> bool {
/// Attempts to check whether the expression is a constant representing an empty slice, str, array,
/// etc…
pub fn constant_is_empty(lcx: &LateContext<'_>, e: &Expr<'_>) -> Option<bool> {
ConstEvalLateContext::new(lcx, lcx.typeck_results()).expr_is_empty(e)
ConstEvalLateContext::new(lcx.tcx, lcx.param_env, lcx.typeck_results()).expr_is_empty(e)
}
/// Attempts to evaluate the expression as a constant.
pub fn constant<'tcx>(
lcx: &LateContext<'tcx>,
typeck_results: &ty::TypeckResults<'tcx>,
typeck_results: &'tcx TypeckResults<'tcx>,
e: &Expr<'_>,
) -> Option<Constant<'tcx>> {
ConstEvalLateContext::new(lcx, typeck_results).expr(e)
ConstEvalLateContext::new(lcx.tcx, lcx.param_env, typeck_results).expr(e)
}
/// Attempts to evaluate the expression as a constant.
pub fn constant_with_source<'tcx>(
lcx: &LateContext<'tcx>,
typeck_results: &ty::TypeckResults<'tcx>,
typeck_results: &'tcx TypeckResults<'tcx>,
e: &Expr<'_>,
) -> Option<(Constant<'tcx>, ConstantSource)> {
let mut ctxt = ConstEvalLateContext::new(lcx, typeck_results);
let mut ctxt = ConstEvalLateContext::new(lcx.tcx, lcx.param_env, typeck_results);
let res = ctxt.expr(e);
res.map(|x| (x, ctxt.source))
}
@ -365,7 +367,7 @@ pub fn constant_with_source<'tcx>(
/// Attempts to evaluate an expression only if its value is not dependent on other items.
pub fn constant_simple<'tcx>(
lcx: &LateContext<'tcx>,
typeck_results: &ty::TypeckResults<'tcx>,
typeck_results: &'tcx TypeckResults<'tcx>,
e: &Expr<'_>,
) -> Option<Constant<'tcx>> {
constant_with_source(lcx, typeck_results, e).and_then(|(c, s)| s.is_local().then_some(c))
@ -373,7 +375,7 @@ pub fn constant_simple<'tcx>(
pub fn constant_full_int<'tcx>(
lcx: &LateContext<'tcx>,
typeck_results: &ty::TypeckResults<'tcx>,
typeck_results: &'tcx TypeckResults<'tcx>,
e: &Expr<'_>,
) -> Option<FullInt> {
constant_simple(lcx, typeck_results, e)?.int_value(lcx, typeck_results.expr_ty(e))
@ -417,20 +419,20 @@ fn cmp_s_u(s: i128, u: u128) -> Ordering {
}
}
pub struct ConstEvalLateContext<'a, 'tcx> {
lcx: &'a LateContext<'tcx>,
typeck_results: &'a ty::TypeckResults<'tcx>,
param_env: ty::ParamEnv<'tcx>,
pub struct ConstEvalLateContext<'tcx> {
tcx: TyCtxt<'tcx>,
typeck_results: &'tcx TypeckResults<'tcx>,
param_env: ParamEnv<'tcx>,
source: ConstantSource,
args: GenericArgsRef<'tcx>,
}
impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
pub fn new(lcx: &'a LateContext<'tcx>, typeck_results: &'a ty::TypeckResults<'tcx>) -> Self {
impl<'tcx> ConstEvalLateContext<'tcx> {
pub fn new(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, typeck_results: &'tcx TypeckResults<'tcx>) -> Self {
Self {
lcx,
tcx,
typeck_results,
param_env: lcx.param_env,
param_env,
source: ConstantSource::Local,
args: List::empty(),
}
@ -439,18 +441,19 @@ pub fn new(lcx: &'a LateContext<'tcx>, typeck_results: &'a ty::TypeckResults<'tc
/// Simple constant folding: Insert an expression, get a constant or none.
pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant<'tcx>> {
match e.kind {
ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.lcx.tcx.hir().body(body).value),
ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.tcx.hir().body(body).value),
ExprKind::DropTemps(e) => self.expr(e),
ExprKind::Path(ref qpath) => {
let is_core_crate = if let Some(def_id) = self.lcx.qpath_res(qpath, e.hir_id()).opt_def_id() {
self.lcx.tcx.crate_name(def_id.krate) == sym::core
let is_core_crate = if let Some(def_id) = self.typeck_results.qpath_res(qpath, e.hir_id()).opt_def_id()
{
self.tcx.crate_name(def_id.krate) == sym::core
} else {
false
};
self.fetch_path_and_apply(qpath, e.hir_id, self.typeck_results.expr_ty(e), |this, result| {
let result = mir_to_const(this.lcx, result)?;
self.fetch_path_and_apply(qpath, e.hir_id, self.typeck_results.expr_ty(e), |self_, result| {
let result = mir_to_const(self_.tcx, result)?;
// If source is already Constant we wouldn't want to override it with CoreConstant
this.source = if is_core_crate && !matches!(this.source, ConstantSource::Constant) {
self_.source = if is_core_crate && !matches!(self_.source, ConstantSource::Constant) {
ConstantSource::CoreConstant
} else {
ConstantSource::Constant
@ -470,7 +473,7 @@ pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant<'tcx>> {
ExprKind::Tup(tup) => self.multi(tup).map(Constant::Tuple),
ExprKind::Repeat(value, _) => {
let n = match self.typeck_results.expr_ty(e).kind() {
ty::Array(_, n) => n.try_eval_target_usize(self.lcx.tcx, self.lcx.param_env)?,
ty::Array(_, n) => n.try_eval_target_usize(self.tcx, self.param_env)?,
_ => span_bug!(e.span, "typeck error"),
};
self.expr(value).map(|v| Constant::Repeat(Box::new(v), n))
@ -486,21 +489,16 @@ pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant<'tcx>> {
// We only handle a few const functions for now.
if args.is_empty()
&& let ExprKind::Path(qpath) = &callee.kind
&& let res = self.typeck_results.qpath_res(qpath, callee.hir_id)
&& let Some(def_id) = res.opt_def_id()
&& let def_path = self.lcx.get_def_path(def_id)
&& let def_path = def_path.iter().take(4).map(Symbol::as_str).collect::<Vec<_>>()
&& let ["core", "num", int_impl, "max_value"] = *def_path
&& let Some(did) = self.typeck_results.qpath_res(qpath, callee.hir_id).opt_def_id()
{
let value = match int_impl {
"<impl i8>" => i8::MAX as u128,
"<impl i16>" => i16::MAX as u128,
"<impl i32>" => i32::MAX as u128,
"<impl i64>" => i64::MAX as u128,
"<impl i128>" => i128::MAX as u128,
_ => return None,
};
Some(Constant::Int(value))
match self.tcx.get_diagnostic_name(did) {
Some(sym::i8_legacy_fn_max_value) => Some(Constant::Int(i8::MAX as u128)),
Some(sym::i16_legacy_fn_max_value) => Some(Constant::Int(i16::MAX as u128)),
Some(sym::i32_legacy_fn_max_value) => Some(Constant::Int(i32::MAX as u128)),
Some(sym::i64_legacy_fn_max_value) => Some(Constant::Int(i64::MAX as u128)),
Some(sym::i128_legacy_fn_max_value) => Some(Constant::Int(i128::MAX as u128)),
_ => None,
}
} else {
None
}
@ -512,9 +510,9 @@ pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant<'tcx>> {
if let Some(Constant::Adt(constant)) = &self.expr(local_expr)
&& let ty::Adt(adt_def, _) = constant.ty().kind()
&& adt_def.is_struct()
&& let Some(desired_field) = field_of_struct(*adt_def, self.lcx, *constant, field)
&& let Some(desired_field) = field_of_struct(*adt_def, self.tcx, *constant, field)
{
mir_to_const(self.lcx, desired_field)
mir_to_const(self.tcx, desired_field)
} else {
result
}
@ -528,7 +526,7 @@ pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant<'tcx>> {
/// leaves the local crate.
pub fn expr_is_empty(&mut self, e: &Expr<'_>) -> Option<bool> {
match e.kind {
ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr_is_empty(self.lcx.tcx.hir().body(body).value),
ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr_is_empty(self.tcx.hir().body(body).value),
ExprKind::DropTemps(e) => self.expr_is_empty(e),
ExprKind::Path(ref qpath) => {
if !self
@ -539,8 +537,8 @@ pub fn expr_is_empty(&mut self, e: &Expr<'_>) -> Option<bool> {
{
return None;
}
self.fetch_path_and_apply(qpath, e.hir_id, self.typeck_results.expr_ty(e), |this, result| {
mir_is_empty(this.lcx, result)
self.fetch_path_and_apply(qpath, e.hir_id, self.typeck_results.expr_ty(e), |self_, result| {
mir_is_empty(self_.tcx, result)
})
},
ExprKind::Lit(lit) => {
@ -557,7 +555,7 @@ pub fn expr_is_empty(&mut self, e: &Expr<'_>) -> Option<bool> {
ExprKind::Array(vec) => self.multi(vec).map(|v| v.is_empty()),
ExprKind::Repeat(..) => {
if let ty::Array(_, n) = self.typeck_results.expr_ty(e).kind() {
Some(n.try_eval_target_usize(self.lcx.tcx, self.lcx.param_env)? == 0)
Some(n.try_eval_target_usize(self.tcx, self.param_env)? == 0)
} else {
span_bug!(e.span, "typeck error");
}
@ -574,8 +572,8 @@ fn constant_not(&self, o: &Constant<'tcx>, ty: Ty<'_>) -> Option<Constant<'tcx>>
Int(value) => {
let value = !value;
match *ty.kind() {
ty::Int(ity) => Some(Int(unsext(self.lcx.tcx, value as i128, ity))),
ty::Uint(ity) => Some(Int(clip(self.lcx.tcx, value, ity))),
ty::Int(ity) => Some(Int(unsext(self.tcx, value as i128, ity))),
ty::Uint(ity) => Some(Int(clip(self.tcx, value, ity))),
_ => None,
}
},
@ -590,7 +588,7 @@ fn constant_negate(&self, o: &Constant<'tcx>, ty: Ty<'_>) -> Option<Constant<'tc
let ty::Int(ity) = *ty.kind() else { return None };
let (min, _) = ity.min_max()?;
// sign extend
let value = sext(self.lcx.tcx, value, ity);
let value = sext(self.tcx, value, ity);
// Applying unary - to the most negative value of any signed integer type panics.
if value == min {
@ -599,7 +597,7 @@ fn constant_negate(&self, o: &Constant<'tcx>, ty: Ty<'_>) -> Option<Constant<'tc
let value = value.checked_neg()?;
// clear unused bits
Some(Int(unsext(self.lcx.tcx, value, ity)))
Some(Int(unsext(self.tcx, value, ity)))
},
F32(f) => Some(F32(-f)),
F64(f) => Some(F64(-f)),
@ -623,7 +621,7 @@ fn fetch_path_and_apply<T, F>(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'t
Res::Def(DefKind::Const | DefKind::AssocConst, def_id) => {
// Check if this constant is based on `cfg!(..)`,
// which is NOT constant for our purposes.
if let Some(node) = self.lcx.tcx.hir().get_if_local(def_id)
if let Some(node) = self.tcx.hir().get_if_local(def_id)
&& let Node::Item(Item {
kind: ItemKind::Const(.., body_id),
..
@ -632,7 +630,7 @@ fn fetch_path_and_apply<T, F>(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'t
kind: ExprKind::Lit(_),
span,
..
}) = self.lcx.tcx.hir_node(body_id.hir_id)
}) = self.tcx.hir_node(body_id.hir_id)
&& is_direct_expn_of(*span, "cfg").is_some()
{
return None;
@ -642,10 +640,9 @@ fn fetch_path_and_apply<T, F>(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'t
let args = if self.args.is_empty() {
args
} else {
EarlyBinder::bind(args).instantiate(self.lcx.tcx, self.args)
EarlyBinder::bind(args).instantiate(self.tcx, self.args)
};
let result = self
.lcx
.tcx
.const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, args), qpath.span())
.ok()
@ -685,7 +682,7 @@ fn index(&mut self, lhs: &'_ Expr<'_>, index: &'_ Expr<'_>) -> Option<Constant<'
}
}
/// A block can only yield a constant if it only has one constant expression.
/// A block can only yield a constant if it has exactly one constant expression.
fn block(&mut self, block: &Block<'_>) -> Option<Constant<'tcx>> {
if block.stmts.is_empty()
&& let Some(expr) = block.expr
@ -696,7 +693,7 @@ fn block(&mut self, block: &Block<'_>) -> Option<Constant<'tcx>> {
if let Some(expr_span) = walk_span_to_context(expr.span, span.ctxt)
&& let expr_lo = expr_span.lo()
&& expr_lo >= span.lo
&& let Some(src) = (span.lo..expr_lo).get_source_text(self.lcx)
&& let Some(src) = (span.lo..expr_lo).get_source_text(&self.tcx)
&& let Some(src) = src.as_str()
{
use rustc_lexer::TokenKind::{BlockComment, LineComment, OpenBrace, Semi, Whitespace};
@ -739,8 +736,8 @@ fn binop(&mut self, op: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> Option<Cons
ty::Int(ity) => {
let (ty_min_value, _) = ity.min_max()?;
let bits = ity.bits();
let l = sext(self.lcx.tcx, l, ity);
let r = sext(self.lcx.tcx, r, ity);
let l = sext(self.tcx, l, ity);
let r = sext(self.tcx, r, ity);
// Using / or %, where the left-hand argument is the smallest integer of a signed integer type and
// the right-hand argument is -1 always panics, even with overflow-checks disabled
@ -751,7 +748,7 @@ fn binop(&mut self, op: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> Option<Cons
return None;
}
let zext = |n: i128| Constant::Int(unsext(self.lcx.tcx, n, ity));
let zext = |n: i128| Constant::Int(unsext(self.tcx, n, ity));
match op.node {
// When +, * or binary - create a value greater than the maximum value, or less than
// the minimum value that can be stored, it panics.
@ -845,7 +842,7 @@ fn binop(&mut self, op: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> Option<Cons
}
}
pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> Option<Constant<'tcx>> {
pub fn mir_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::Const<'tcx>) -> Option<Constant<'tcx>> {
let mir::Const::Val(val, _) = result else {
// We only work on evaluated consts.
return None;
@ -863,13 +860,13 @@ pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) ->
_ => None,
},
(_, ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Str) => {
let data = val.try_get_slice_bytes_for_diagnostics(lcx.tcx)?;
let data = val.try_get_slice_bytes_for_diagnostics(tcx)?;
String::from_utf8(data.to_owned()).ok().map(Constant::Str)
},
(_, ty::Adt(adt_def, _)) if adt_def.is_struct() => Some(Constant::Adt(result)),
(ConstValue::Indirect { alloc_id, offset }, ty::Array(sub_type, len)) => {
let alloc = lcx.tcx.global_alloc(alloc_id).unwrap_memory().inner();
let len = len.try_to_target_usize(lcx.tcx)?;
let alloc = tcx.global_alloc(alloc_id).unwrap_memory().inner();
let len = len.try_to_target_usize(tcx)?;
let ty::Float(flt) = sub_type.kind() else {
return None;
};
@ -877,7 +874,7 @@ pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) ->
let mut res = Vec::new();
for idx in 0..len {
let range = alloc_range(offset + size * idx, size);
let val = alloc.read_scalar(&lcx.tcx, range, /* read_provenance */ false).ok()?;
let val = alloc.read_scalar(&tcx, range, /* read_provenance */ false).ok()?;
res.push(match flt {
FloatTy::F16 => Constant::F16(f16::from_bits(val.to_u16().ok()?)),
FloatTy::F32 => Constant::F32(f32::from_bits(val.to_u32().ok()?)),
@ -891,7 +888,7 @@ pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) ->
}
}
fn mir_is_empty<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> Option<bool> {
fn mir_is_empty<'tcx>(tcx: TyCtxt<'tcx>, result: mir::Const<'tcx>) -> Option<bool> {
let mir::Const::Val(val, _) = result else {
// We only work on evaluated consts.
return None;
@ -902,26 +899,26 @@ fn mir_is_empty<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> Opti
if let ConstValue::Indirect { alloc_id, offset } = val {
// Get the length from the slice, using the same formula as
// [`ConstValue::try_get_slice_bytes_for_diagnostics`].
let a = lcx.tcx.global_alloc(alloc_id).unwrap_memory().inner();
let ptr_size = lcx.tcx.data_layout.pointer_size;
let a = tcx.global_alloc(alloc_id).unwrap_memory().inner();
let ptr_size = tcx.data_layout.pointer_size;
if a.size() < offset + 2 * ptr_size {
// (partially) dangling reference
return None;
}
let len = a
.read_scalar(&lcx.tcx, alloc_range(offset + ptr_size, ptr_size), false)
.read_scalar(&tcx, alloc_range(offset + ptr_size, ptr_size), false)
.ok()?
.to_target_usize(&lcx.tcx)
.to_target_usize(&tcx)
.ok()?;
Some(len == 0)
} else {
None
}
},
ty::Array(_, len) => Some(len.try_to_target_usize(lcx.tcx)? == 0),
ty::Array(_, len) => Some(len.try_to_target_usize(tcx)? == 0),
_ => None,
},
(ConstValue::Indirect { .. }, ty::Array(_, len)) => Some(len.try_to_target_usize(lcx.tcx)? == 0),
(ConstValue::Indirect { .. }, ty::Array(_, len)) => Some(len.try_to_target_usize(tcx)? == 0),
(ConstValue::ZeroSized, _) => Some(true),
_ => None,
}
@ -929,12 +926,12 @@ fn mir_is_empty<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> Opti
fn field_of_struct<'tcx>(
adt_def: ty::AdtDef<'tcx>,
lcx: &LateContext<'tcx>,
tcx: TyCtxt<'tcx>,
result: mir::Const<'tcx>,
field: &Ident,
) -> Option<mir::Const<'tcx>> {
if let mir::Const::Val(result, ty) = result
&& let Some(dc) = lcx.tcx.try_destructure_mir_constant_for_user_output(result, ty)
&& let Some(dc) = tcx.try_destructure_mir_constant_for_user_output(result, ty)
&& let Some(dc_variant) = dc.variant
&& let Some(variant) = adt_def.variants().get(dc_variant)
&& let Some(field_idx) = variant.fields.iter().position(|el| el.name == field.name)

View File

@ -1577,7 +1577,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti
if let rustc_ty::Adt(_, subst) = ty.kind()
&& let bnd_ty = subst.type_at(0)
&& let Some(min_val) = bnd_ty.numeric_min_val(cx.tcx)
&& let Some(min_const) = mir_to_const(cx, Const::from_ty_const(min_val, bnd_ty, cx.tcx))
&& let Some(min_const) = mir_to_const(cx.tcx, Const::from_ty_const(min_val, bnd_ty, cx.tcx))
&& let Some(start_const) = constant(cx, cx.typeck_results(), start)
{
start_const == min_const
@ -1590,7 +1590,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti
if let rustc_ty::Adt(_, subst) = ty.kind()
&& let bnd_ty = subst.type_at(0)
&& let Some(max_val) = bnd_ty.numeric_max_val(cx.tcx)
&& let Some(max_const) = mir_to_const(cx, Const::from_ty_const(max_val, bnd_ty, cx.tcx))
&& let Some(max_const) = mir_to_const(cx.tcx, Const::from_ty_const(max_val, bnd_ty, cx.tcx))
&& let Some(end_const) = constant(cx, cx.typeck_results(), end)
{
end_const == max_const