| use rustc_ast::{LitFloatType, LitIntType, LitKind}; | |
| use rustc_hir; | |
| use rustc_macros::StableHash; | |
| use crate::ty::{self, Ty, TyCtxt}; | |
| /// Input argument for `tcx.lit_to_const`. | |
| #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, StableHash)] | |
| pub struct LitToConstInput<'tcx> { | |
| /// The absolute value of the resultant constant. | |
| pub lit: LitKind, | |
| /// The type of the constant. | |
| /// | |
| /// `None` is used by const generics when the type of the constant is unknown, e.g. | |
| /// if there are inference variables | |
| pub ty: Option<Ty<'tcx>>, | |
| /// If the constant is negative. | |
| pub neg: bool, | |
| } | |
| /// Checks whether a literal can be interpreted as a const of the given type. | |
| pub fn const_lit_matches_ty<'tcx>( | |
| tcx: TyCtxt<'tcx>, | |
| kind: &LitKind, | |
| ty: Ty<'tcx>, | |
| neg: bool, | |
| ) -> bool { | |
| match (*kind, ty.kind()) { | |
| (LitKind::Str(..), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => true, | |
| (LitKind::Str(..), ty::Str) if tcx.features().deref_patterns() => true, | |
| (LitKind::ByteStr(..), ty::Ref(_, inner_ty, _)) | |
| if let ty::Slice(ty) | ty::Array(ty, _) = inner_ty.kind() | |
| && matches!(ty.kind(), ty::Uint(ty::UintTy::U8)) => | |
| { | |
| true | |
| } | |
| (LitKind::ByteStr(..), ty::Slice(inner_ty) | ty::Array(inner_ty, _)) | |
| if tcx.features().deref_patterns() | |
| && matches!(inner_ty.kind(), ty::Uint(ty::UintTy::U8)) => | |
| { | |
| true | |
| } | |
| (LitKind::Byte(..), ty::Uint(ty::UintTy::U8)) => true, | |
| (LitKind::CStr(..), ty::Ref(_, inner_ty, _)) | |
| if matches!(inner_ty.kind(), ty::Adt(def, _) | |
| if tcx.is_lang_item(def.did(), rustc_hir::LangItem::CStr)) => | |
| { | |
| true | |
| } | |
| (LitKind::Int(_, LitIntType::Unsigned(lit_ty)), ty::Uint(expect_ty)) if !neg => { | |
| lit_ty == *expect_ty | |
| } | |
| (LitKind::Int(_, LitIntType::Signed(lit_ty)), ty::Int(expect_ty)) => lit_ty == *expect_ty, | |
| (LitKind::Int(_, LitIntType::Unsuffixed), ty::Uint(_)) if !neg => true, | |
| (LitKind::Int(_, LitIntType::Unsuffixed), ty::Int(_)) => true, | |
| (LitKind::Bool(..), ty::Bool) => true, | |
| (LitKind::Float(_, LitFloatType::Suffixed(lit_ty)), ty::Float(expect_ty)) => { | |
| lit_ty == *expect_ty | |
| } | |
| (LitKind::Float(_, LitFloatType::Unsuffixed), ty::Float(_)) => true, | |
| (LitKind::Char(..), ty::Char) => true, | |
| (LitKind::Err(..), _) => true, | |
| _ => false, | |
| } | |
| } |