diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 0a4f84558fee4..9c2a6f205e052 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -9,13 +9,13 @@ use crate::ty::adjustment::PointerCast; use crate::ty::codec::{TyDecoder, TyEncoder}; use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeVisitor}; use crate::ty::print::{FmtPrinter, Printer}; -use crate::ty::subst::{Subst, SubstsRef}; +use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; use crate::ty::{self, List, Ty, TyCtxt}; use crate::ty::{AdtDef, InstanceDef, Region, ScalarInt, UserTypeAnnotationIndex}; use rustc_errors::ErrorGuaranteed; use rustc_hir::def::{CtorKind, Namespace}; -use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; +use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX}; use rustc_hir::{self, GeneratorKind}; use rustc_hir::{self as hir, HirId}; use rustc_session::Session; @@ -2664,6 +2664,16 @@ impl<'tcx> ConstantKind<'tcx> { } } + pub fn try_val(&self) -> Option> { + match self { + ConstantKind::Ty(c) => match c.val() { + ty::ConstKind::Value(v) => Some(v), + _ => None, + }, + ConstantKind::Val(v, _) => Some(*v), + } + } + #[inline] pub fn try_to_value(self) -> Option> { match self { @@ -2692,6 +2702,32 @@ impl<'tcx> ConstantKind<'tcx> { self.try_to_scalar_int()?.try_into().ok() } + #[inline] + pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self { + match self { + Self::Ty(c) => { + // FIXME Need to use a different evaluation function that directly returns a `ConstValue` + // if evaluation succeeds and does not create a ValTree first + if let Some(val) = c.val().try_eval(tcx, param_env) { + match val { + Ok(val) => Self::Val(val, c.ty()), + Err(_) => Self::Ty(tcx.const_error(self.ty())), + } + } else { + self + } + } + Self::Val(_, _) => self, + } + } + + /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type. + #[inline] + pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 { + self.try_eval_bits(tcx, param_env, ty) + .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", ty, self)) + } + #[inline] pub fn try_eval_bits( &self, @@ -2726,25 +2762,142 @@ impl<'tcx> ConstantKind<'tcx> { } } + pub fn from_bits( + tcx: TyCtxt<'tcx>, + bits: u128, + param_env_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, + ) -> Self { + let size = tcx + .layout_of(param_env_ty) + .unwrap_or_else(|e| { + bug!("could not compute layout for {:?}: {:?}", param_env_ty.value, e) + }) + .size; + let cv = ConstValue::Scalar(Scalar::from_uint(bits, size)); + + Self::Val(cv, param_env_ty.value) + } + pub fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> Self { let cv = ConstValue::from_bool(v); Self::Val(cv, tcx.types.bool) } - pub fn from_zero_sized(ty: Ty<'tcx>) -> Self { + pub fn zero_sized(ty: Ty<'tcx>) -> Self { let cv = ConstValue::Scalar(Scalar::ZST); Self::Val(cv, ty) } pub fn from_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self { let ty = tcx.types.usize; - let size = tcx - .layout_of(ty::ParamEnv::empty().and(ty)) - .unwrap_or_else(|e| bug!("could not compute layout for {:?}: {:?}", ty, e)) - .size; - let cv = ConstValue::Scalar(Scalar::from_uint(n as u128, size)); + Self::from_bits(tcx, n as u128, ty::ParamEnv::empty().and(ty)) + } - Self::Val(cv, ty) + /// Literals are converted to `ConstantKindVal`, const generic parameters are eagerly + /// converted to a constant, everything else becomes `Unevaluated`. + pub fn from_anon_const( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + param_env: ty::ParamEnv<'tcx>, + ) -> Self { + Self::from_opt_const_arg_anon_const(tcx, ty::WithOptConstParam::unknown(def_id), param_env) + } + + #[instrument(skip(tcx), level = "debug")] + fn from_opt_const_arg_anon_const( + tcx: TyCtxt<'tcx>, + def: ty::WithOptConstParam, + param_env: ty::ParamEnv<'tcx>, + ) -> Self { + let body_id = match tcx.hir().get_by_def_id(def.did) { + hir::Node::AnonConst(ac) => ac.body, + _ => span_bug!( + tcx.def_span(def.did.to_def_id()), + "from_anon_const can only process anonymous constants" + ), + }; + + let expr = &tcx.hir().body(body_id).value; + debug!(?expr); + + // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments + // currently have to be wrapped in curly brackets, so it's necessary to special-case. + let expr = match &expr.kind { + hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => { + block.expr.as_ref().unwrap() + } + _ => expr, + }; + + let ty = tcx.type_of(def.def_id_for_type_of()); + + // FIXME(const_generics): We currently have to special case parameters because `min_const_generics` + // does not provide the parents generics to anonymous constants. We still allow generic const + // parameters by themselves however, e.g. `N`. These constants would cause an ICE if we were to + // ever try to substitute the generic parameters in their bodies. + // + // While this doesn't happen as these constants are always used as `ty::ConstKind::Param`, it does + // cause issues if we were to remove that special-case and try to evaluate the constant instead. + use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath}; + match expr.kind { + ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => { + // Find the name and index of the const parameter by indexing the generics of + // the parent item and construct a `ParamConst`. + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + let item_id = tcx.hir().get_parent_node(hir_id); + let item_def_id = tcx.hir().local_def_id(item_id); + let generics = tcx.generics_of(item_def_id.to_def_id()); + let index = generics.param_def_id_to_index[&def_id]; + let name = tcx.hir().name(hir_id); + let ty_const = tcx.mk_const(ty::ConstS { + val: ty::ConstKind::Param(ty::ParamConst::new(index, name)), + ty, + }); + + return Self::Ty(ty_const); + } + _ => {} + } + + let hir_id = tcx.hir().local_def_id_to_hir_id(def.did); + let parent_substs = if let Some(parent_hir_id) = tcx.hir().find_parent_node(hir_id) { + if let Some(parent_did) = tcx.hir().opt_local_def_id(parent_hir_id) { + InternalSubsts::identity_for_item(tcx, parent_did.to_def_id()) + } else { + tcx.mk_substs(Vec::>::new().into_iter()) + } + } else { + tcx.mk_substs(Vec::>::new().into_iter()) + }; + debug!(?parent_substs); + + let did = def.did.to_def_id(); + let child_substs = InternalSubsts::identity_for_item(tcx, did); + let substs = tcx.mk_substs(parent_substs.into_iter().chain(child_substs.into_iter())); + debug!(?substs); + + let hir_id = tcx.hir().local_def_id_to_hir_id(def.did); + let span = tcx.hir().span(hir_id); + let uneval = ty::Unevaluated::new(def.to_global(), substs); + debug!(?span, ?param_env); + + match tcx.const_eval_resolve(param_env, uneval, Some(span)) { + Ok(val) => Self::Val(val, ty), + Err(_) => { + // Error was handled in `const_eval_resolve`. Here we just create a + // new unevaluated const and error hard later in codegen + let ty_const = tcx.mk_const(ty::ConstS { + val: ty::ConstKind::Unevaluated(ty::Unevaluated { + def: def.to_global(), + substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()), + promoted: None, + }), + ty, + }); + + Self::Ty(ty_const) + } + } } } diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index b31cc17a9594d..b17343d7692f6 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -19,11 +19,11 @@ use rustc_middle::infer::canonical::Canonical; use rustc_middle::middle::region; use rustc_middle::mir::interpret::AllocId; use rustc_middle::mir::{ - BinOp, BorrowKind, FakeReadCause, Field, Mutability, UnOp, UserTypeProjection, + self, BinOp, BorrowKind, FakeReadCause, Field, Mutability, UnOp, UserTypeProjection, }; use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::{self, AdtDef, Const, Ty, UpvarSubsts, UserType}; +use rustc_middle::ty::{self, AdtDef, Ty, UpvarSubsts, UserType}; use rustc_middle::ty::{ CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, }; @@ -375,7 +375,7 @@ pub enum ExprKind<'tcx> { /// An array literal constructed from one repeated element, e.g. `[1; 5]`. Repeat { value: ExprId, - count: Const<'tcx>, + count: ty::Const<'tcx>, }, /// An array, e.g. `[a, b, c, d]`. Array { @@ -522,7 +522,7 @@ pub enum InlineAsmOperand<'tcx> { out_expr: Option, }, Const { - value: Const<'tcx>, + value: mir::ConstantKind<'tcx>, span: Span, }, SymFn { diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 451fa46638771..ef7becde69a66 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -24,6 +24,15 @@ pub trait Visitor<'a, 'tcx: 'a>: Sized { fn visit_pat(&mut self, pat: &Pat<'tcx>) { walk_pat(self, pat); } + + // Note: We don't have visitors for `ty::Const` and `mir::ConstantKind` + // (even though these types occur in THIR) for consistency and to reduce confusion, + // since the lazy creation of constants during thir construction causes most + // 'constants' to not be of type `ty::Const` or `mir::ConstantKind` at that + // stage (they are mostly still identified by `DefId` or `hir::Lit`, see + // the variants `Literal`, `NonHirLiteral` and `NamedConst` in `thir::ExprKind`). + // You have to manually visit `ty::Const` and `mir::ConstantKind` through the + // other `visit*` functions. } pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Expr<'tcx>) { diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index b8da35abd4703..35d286d2c5781 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -126,7 +126,8 @@ impl<'tcx> ConstKind<'tcx> { #[inline] /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary /// return `None`. - pub(super) fn try_eval( + // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged. + pub fn try_eval( self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, diff --git a/compiler/rustc_mir_build/src/build/cfg.rs b/compiler/rustc_mir_build/src/build/cfg.rs index dca9a63120c32..ac92b03e5f385 100644 --- a/compiler/rustc_mir_build/src/build/cfg.rs +++ b/compiler/rustc_mir_build/src/build/cfg.rs @@ -73,7 +73,7 @@ impl<'tcx> CFG<'tcx> { Rvalue::Use(Operand::Constant(Box::new(Constant { span: source_info.span, user_ty: None, - literal: ConstantKind::from_zero_sized(tcx.types.unit), + literal: ConstantKind::zero_sized(tcx.types.unit), }))), ); } diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 6856ded3498ee..8b9b1847e7f0e 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -2,11 +2,10 @@ use crate::build::Builder; use crate::thir::constant::parse_float; -use rustc_ast::ast; +use rustc_ast as ast; use rustc_hir::def_id::DefId; -use rustc_middle::mir::interpret::{ - Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar, -}; +use rustc_middle::mir::interpret::Allocation; +use rustc_middle::mir::interpret::{ConstValue, LitToConstError, LitToConstInput, Scalar}; use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty::subst::SubstsRef; @@ -32,11 +31,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } ExprKind::Literal { lit, neg } => { let literal = - match lit_to_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg }) { + match lit_to_mir_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg }) { Ok(c) => c, Err(LitToConstError::Reported) => ConstantKind::Ty(tcx.const_error(ty)), Err(LitToConstError::TypeError) => { - bug!("encountered type error in `lit_to_constant") + bug!("encountered type error in `lit_to_mir_constant") } }; @@ -90,7 +89,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } -crate fn lit_to_constant<'tcx>( +#[instrument(skip(tcx, lit_input))] +fn lit_to_mir_constant<'tcx>( tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx>, ) -> Result, LitToConstError> { diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 3f8a1a3f79504..be777418433a5 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -322,7 +322,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block.and(Rvalue::Use(Operand::Constant(Box::new(Constant { span: expr_span, user_ty: None, - literal: ty::Const::zero_sized(this.tcx, this.tcx.types.unit).into(), + literal: ConstantKind::zero_sized(this.tcx.types.unit), })))) } ExprKind::Yield { .. } @@ -552,7 +552,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> { let param_ty = ty::ParamEnv::empty().and(ty); let size = self.tcx.layout_of(param_ty).unwrap().size; - let literal = ty::Const::from_bits(self.tcx, size.unsigned_int_max(), param_ty); + let literal = ConstantKind::from_bits(self.tcx, size.unsigned_int_max(), param_ty); self.literal_operand(span, literal) } @@ -563,7 +563,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let param_ty = ty::ParamEnv::empty().and(ty); let bits = self.tcx.layout_of(param_ty).unwrap().size.bits(); let n = 1 << (bits - 1); - let literal = ty::Const::from_bits(self.tcx, n, param_ty); + let literal = ConstantKind::from_bits(self.tcx, n, param_ty); self.literal_operand(span, literal) } diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 96069f05b40f3..806c260d110ea 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -264,7 +264,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ); } else if let [success, fail] = *make_target_blocks(self) { assert_eq!(value.ty(), ty); - let expect = self.literal_operand(test.span, value); + let expect = self.literal_operand(test.span, value.into()); let val = Operand::Copy(place); self.compare(block, success, fail, source_info, BinOp::Eq, expect, val); } else { @@ -277,8 +277,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let target_blocks = make_target_blocks(self); // Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons. - let lo = self.literal_operand(test.span, lo); - let hi = self.literal_operand(test.span, hi); + let lo = self.literal_operand(test.span, lo.into()); + let hi = self.literal_operand(test.span, hi.into()); let val = Operand::Copy(place); let [success, fail] = *target_blocks else { @@ -370,7 +370,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { place: Place<'tcx>, mut ty: Ty<'tcx>, ) { - let mut expect = self.literal_operand(source_info.span, value); + let mut expect = self.literal_operand(source_info.span, value.into()); let mut val = Operand::Copy(place); // If we're using `b"..."` as a pattern, we need to insert an @@ -823,7 +823,7 @@ fn trait_method<'tcx>( method_name: Symbol, self_ty: Ty<'tcx>, params: &[GenericArg<'tcx>], -) -> ty::Const<'tcx> { +) -> ConstantKind<'tcx> { let substs = tcx.mk_substs_trait(self_ty, params); // The unhygienic comparison here is acceptable because this is only @@ -836,5 +836,6 @@ fn trait_method<'tcx>( let method_ty = tcx.type_of(item.def_id); let method_ty = method_ty.subst(tcx, substs); - ty::Const::zero_sized(tcx, method_ty) + + ConstantKind::zero_sized(method_ty) } diff --git a/compiler/rustc_mir_build/src/build/misc.rs b/compiler/rustc_mir_build/src/build/misc.rs index 3516eca1c1469..84762d602f8db 100644 --- a/compiler/rustc_mir_build/src/build/misc.rs +++ b/compiler/rustc_mir_build/src/build/misc.rs @@ -3,6 +3,7 @@ use crate::build::Builder; +use rustc_middle::mir; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty}; use rustc_span::{Span, DUMMY_SP}; @@ -25,8 +26,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// Convenience function for creating a literal operand, one /// without any user type annotation. - crate fn literal_operand(&mut self, span: Span, literal: ty::Const<'tcx>) -> Operand<'tcx> { - let literal = literal.into(); + crate fn literal_operand( + &mut self, + span: Span, + literal: mir::ConstantKind<'tcx>, + ) -> Operand<'tcx> { let constant = Box::new(Constant { span, user_ty: None, literal }); Operand::Constant(constant) } @@ -34,7 +38,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Returns a zero literal operand for the appropriate type, works for // bool, char and integers. crate fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> { - let literal = ty::Const::from_bits(self.tcx, 0, ty::ParamEnv::empty().and(ty)); + let literal = ConstantKind::from_bits(self.tcx, 0, ty::ParamEnv::empty().and(ty)); self.literal_operand(span, literal) } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index e6afc89baa03b..7ef33011234fc 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -8,7 +8,7 @@ use rustc_middle::hir::place::Place as HirPlace; use rustc_middle::hir::place::PlaceBase as HirPlaceBase; use rustc_middle::hir::place::ProjectionKind as HirProjectionKind; use rustc_middle::middle::region; -use rustc_middle::mir::{BinOp, BorrowKind, Field, UnOp}; +use rustc_middle::mir::{self, BinOp, BorrowKind, Field, UnOp}; use rustc_middle::thir::*; use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, PointerCast, @@ -491,7 +491,11 @@ impl<'tcx> Cx<'tcx> { hir::InlineAsmOperand::Const { ref anon_const } => { let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id); - let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id); + let value = mir::ConstantKind::from_anon_const( + self.tcx, + anon_const_def_id, + self.param_env, + ); let span = self.tcx.hir().span(anon_const.hir_id); InlineAsmOperand::Const { value, span } diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index 1fadd0c26fc49..20229d0a19fde 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -55,7 +55,7 @@ use rustc_hir::{HirId, RangeEnd}; use rustc_middle::mir::Field; use rustc_middle::thir::{FieldPat, Pat, PatKind, PatRange}; use rustc_middle::ty::layout::IntegerExt; -use rustc_middle::ty::{self, Const, Ty, TyCtxt, VariantDef}; +use rustc_middle::ty::{self, Ty, TyCtxt, VariantDef}; use rustc_middle::{middle::stability::EvalResult, mir::interpret::ConstValue}; use rustc_session::lint; use rustc_span::{Span, DUMMY_SP}; @@ -136,7 +136,7 @@ impl IntRange { fn from_const<'tcx>( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - value: Const<'tcx>, + value: ty::Const<'tcx>, ) -> Option { let ty = value.ty(); if let Some((target_size, bias)) = Self::integral_size_and_signed_bias(tcx, ty) { @@ -829,7 +829,8 @@ impl<'tcx> Constructor<'tcx> { } } (Str(self_val), Str(other_val)) => { - // FIXME: there's probably a more direct way of comparing for equality + // FIXME Once valtrees are available we can directly use the bytes + // in the `Str` variant of the valtree for the comparison here. match compare_const_vals( pcx.cx.tcx, *self_val, diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 72b597bb13d29..dbcd701c1addd 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -488,9 +488,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { match self.tcx.const_eval_instance(param_env_reveal_all, instance, Some(span)) { Ok(value) => { - let const_ = - ty::Const::from_value(self.tcx, value, self.typeck_results.node_type(id)); - + let const_ = ty::Const::from_value(self.tcx, value, ty); let pattern = self.const_to_pat(const_, id, span, mir_structural_match_violation); if !is_associated_const { @@ -585,7 +583,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let lit_input = LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg }; match self.tcx.at(expr.span).lit_to_const(lit_input) { - Ok(val) => *self.const_to_pat(val, expr.hir_id, lit.span, false).kind, + Ok(constant) => *self.const_to_pat(constant, expr.hir_id, lit.span, false).kind, Err(LitToConstError::Reported) => PatKind::Wild, Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"), } @@ -739,6 +737,7 @@ impl<'tcx> PatternFoldable<'tcx> for PatKind<'tcx> { } } +#[instrument(skip(tcx), level = "debug")] crate fn compare_const_vals<'tcx>( tcx: TyCtxt<'tcx>, a: ty::Const<'tcx>, @@ -746,8 +745,6 @@ crate fn compare_const_vals<'tcx>( param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>, ) -> Option { - trace!("compare_const_vals: {:?}, {:?}", a, b); - let from_bool = |v: bool| v.then_some(Ordering::Equal); let fallback = || from_bool(a == b); diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index 15bb5adf8ba19..687b2e23c9fcb 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -765,10 +765,7 @@ fn lint_non_exhaustive_omitted_patterns<'p, 'tcx>( /// `is_under_guard` is used to inform if the pattern has a guard. If it /// has one it must not be inserted into the matrix. This shouldn't be /// relied on for soundness. -#[instrument( - level = "debug", - skip(cx, matrix, witness_preference, hir_id, is_under_guard, is_top_level) -)] +#[instrument(level = "debug", skip(cx, matrix, hir_id))] fn is_useful<'p, 'tcx>( cx: &MatchCheckCtxt<'p, 'tcx>, matrix: &Matrix<'p, 'tcx>, @@ -800,6 +797,7 @@ fn is_useful<'p, 'tcx>( let ty = v.head().ty(); let is_non_exhaustive = cx.is_foreign_non_exhaustive_enum(ty); + debug!("v.head: {:?}, v.span: {:?}", v.head(), v.head().span()); let pcx = PatCtxt { cx, ty, span: v.head().span(), is_top_level, is_non_exhaustive }; // If the first pattern is an or-pattern, expand it. @@ -809,9 +807,11 @@ fn is_useful<'p, 'tcx>( // We try each or-pattern branch in turn. let mut matrix = matrix.clone(); for v in v.expand_or_pat() { + debug!(?v); let usefulness = ensure_sufficient_stack(|| { is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false) }); + debug!(?usefulness); ret.extend(usefulness); // If pattern has a guard don't add it to the matrix. if !is_under_guard { @@ -822,6 +822,7 @@ fn is_useful<'p, 'tcx>( } } else { let v_ctor = v.head().ctor(); + debug!(?v_ctor); if let Constructor::IntRange(ctor_range) = &v_ctor { // Lint on likely incorrect range patterns (#63987) ctor_range.lint_overlapping_range_endpoints( @@ -895,7 +896,7 @@ fn is_useful<'p, 'tcx>( } /// The arm of a match expression. -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] crate struct MatchArm<'p, 'tcx> { /// The pattern must have been lowered through `check_match::MatchVisitor::lower_pattern`. crate pat: &'p DeconstructedPat<'p, 'tcx>, @@ -928,6 +929,7 @@ crate struct UsefulnessReport<'p, 'tcx> { /// /// Note: the input patterns must have been lowered through /// `check_match::MatchVisitor::lower_pattern`. +#[instrument(skip(cx, arms), level = "debug")] crate fn compute_match_usefulness<'p, 'tcx>( cx: &MatchCheckCtxt<'p, 'tcx>, arms: &[MatchArm<'p, 'tcx>], @@ -939,6 +941,7 @@ crate fn compute_match_usefulness<'p, 'tcx>( .iter() .copied() .map(|arm| { + debug!(?arm); let v = PatStack::from_pattern(arm.pat); is_useful(cx, &matrix, &v, RealArm, arm.hir_id, arm.has_guard, true); if !arm.has_guard { diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 2b9cc75f1b753..b409bc3d64e3f 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -637,6 +637,7 @@ pub(super) fn thir_abstract_const<'tcx>( } } +#[instrument(skip(tcx), level = "debug")] pub(super) fn try_unify_abstract_consts<'tcx>( tcx: TyCtxt<'tcx>, (a, b): (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>), diff --git a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs index 7e65812669029..c0b3e95b18523 100644 --- a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs @@ -40,10 +40,8 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) Some(rhs) => constant(cx, cx.typeck_results(), rhs)?.0, None => miri_to_const(ty.numeric_max_val(cx.tcx)?)?, }; - let lhs_val = lhs_const.int_value(cx, ty)?; let rhs_val = rhs_const.int_value(cx, ty)?; - let rhs_bound = match range_end { RangeEnd::Included => EndBound::Included(rhs_val), RangeEnd::Excluded => EndBound::Excluded(rhs_val), diff --git a/src/tools/clippy/clippy_lints/src/neg_multiply.rs b/src/tools/clippy/clippy_lints/src/neg_multiply.rs index 0d05c83ffe45e..6ba9ba0753d49 100644 --- a/src/tools/clippy/clippy_lints/src/neg_multiply.rs +++ b/src/tools/clippy/clippy_lints/src/neg_multiply.rs @@ -53,7 +53,7 @@ impl<'tcx> LateLintPass<'tcx> for NegMultiply { fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) { if_chain! { if let ExprKind::Lit(ref l) = lit.kind; - if consts::lit_to_constant(&l.node, cx.typeck_results().expr_ty_opt(lit)) == Constant::Int(1); + if consts::lit_to_mir_constant(&l.node, cx.typeck_results().expr_ty_opt(lit)) == Constant::Int(1); if cx.typeck_results().expr_ty(exp).is_integral(); then { diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 1d6f7acab139b..be46b791aa4b6 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -179,7 +179,7 @@ impl Constant { } /// Parses a `LitKind` to a `Constant`. -pub fn lit_to_constant(lit: &LitKind, ty: Option>) -> Constant { +pub fn lit_to_mir_constant(lit: &LitKind, ty: Option>) -> Constant { match *lit { LitKind::Str(ref is, _) => Constant::Str(is.to_string()), LitKind::Byte(b) => Constant::Int(u128::from(b)), @@ -301,7 +301,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { if is_direct_expn_of(e.span, "cfg").is_some() { None } else { - Some(lit_to_constant(&lit.node, self.typeck_results.expr_ty_opt(e))) + Some(lit_to_mir_constant(&lit.node, self.typeck_results.expr_ty_opt(e))) } }, ExprKind::Array(vec) => self.multi(vec).map(Constant::Vec),