};
use rustc_middle::mir::*;
use rustc_middle::thir::*;
-use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, TyCtxt};
+use rustc_middle::ty::{
+ self, CanonicalUserType, CanonicalUserTypeAnnotation, TyCtxt, UserTypeAnnotationIndex,
+};
use rustc_span::DUMMY_SP;
use rustc_target::abi::Size;
let this = self;
let tcx = this.tcx;
let Expr { ty, temp_lifetime: _, span, ref kind } = *expr;
- match *kind {
+ match kind {
ExprKind::Scope { region_scope: _, lint_level: _, value } => {
- this.as_constant(&this.thir[value])
- }
- ExprKind::Literal { lit, neg } => {
- let literal =
- match lit_to_mir_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg }) {
- Ok(c) => c,
- Err(LitToConstError::Reported(guar)) => {
- ConstantKind::Ty(tcx.const_error_with_guaranteed(ty, guar))
- }
- Err(LitToConstError::TypeError) => {
- bug!("encountered type error in `lit_to_mir_constant")
- }
- };
-
- Constant { span, user_ty: None, literal }
+ this.as_constant(&this.thir[*value])
}
- ExprKind::NonHirLiteral { lit, ref user_ty } => {
- let user_ty = user_ty.as_ref().map(|user_ty| {
- this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
+ _ => as_constant_inner(
+ expr,
+ |user_ty| {
+ Some(this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span,
user_ty: user_ty.clone(),
inferred_ty: ty,
- })
- });
- let literal = ConstantKind::Val(ConstValue::Scalar(Scalar::Int(lit)), ty);
+ }))
+ },
+ tcx,
+ ),
+ }
+ }
+}
- Constant { span, user_ty: user_ty, literal }
- }
- ExprKind::ZstLiteral { ref user_ty } => {
- let user_ty = user_ty.as_ref().map(|user_ty| {
- this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
- span,
- user_ty: user_ty.clone(),
- inferred_ty: ty,
- })
- });
- let literal = ConstantKind::Val(ConstValue::ZeroSized, ty);
+pub fn as_constant_inner<'tcx>(
+ expr: &Expr<'tcx>,
+ push_cuta: impl FnMut(&Box<CanonicalUserType<'tcx>>) -> Option<UserTypeAnnotationIndex>,
+ tcx: TyCtxt<'tcx>,
+) -> Constant<'tcx> {
+ let Expr { ty, temp_lifetime: _, span, ref kind } = *expr;
+ match *kind {
+ ExprKind::Literal { lit, neg } => {
+ let literal =
+ match lit_to_mir_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg }) {
+ Ok(c) => c,
+ Err(LitToConstError::Reported(guar)) => {
+ ConstantKind::Ty(tcx.const_error_with_guaranteed(ty, guar))
+ }
+ Err(LitToConstError::TypeError) => {
+ bug!("encountered type error in `lit_to_mir_constant")
+ }
+ };
- Constant { span, user_ty: user_ty, literal }
- }
- ExprKind::NamedConst { def_id, substs, ref user_ty } => {
- let user_ty = user_ty.as_ref().map(|user_ty| {
- this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
- span,
- user_ty: user_ty.clone(),
- inferred_ty: ty,
- })
- });
+ Constant { span, user_ty: None, literal }
+ }
+ ExprKind::NonHirLiteral { lit, ref user_ty } => {
+ let user_ty = user_ty.as_ref().map(push_cuta).flatten();
- let uneval =
- mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs);
- let literal = ConstantKind::Unevaluated(uneval, ty);
+ let literal = ConstantKind::Val(ConstValue::Scalar(Scalar::Int(lit)), ty);
- Constant { user_ty, span, literal }
- }
- ExprKind::ConstParam { param, def_id: _ } => {
- let const_param = tcx.mk_const(param, expr.ty);
- let literal = ConstantKind::Ty(const_param);
+ Constant { span, user_ty: user_ty, literal }
+ }
+ ExprKind::ZstLiteral { ref user_ty } => {
+ let user_ty = user_ty.as_ref().map(push_cuta).flatten();
- Constant { user_ty: None, span, literal }
- }
- ExprKind::ConstBlock { did: def_id, substs } => {
- let uneval =
- mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs);
- let literal = ConstantKind::Unevaluated(uneval, ty);
+ let literal = ConstantKind::Val(ConstValue::ZeroSized, ty);
- Constant { user_ty: None, span, literal }
- }
- ExprKind::StaticRef { alloc_id, ty, .. } => {
- let const_val = ConstValue::Scalar(Scalar::from_pointer(alloc_id.into(), &tcx));
- let literal = ConstantKind::Val(const_val, ty);
+ Constant { span, user_ty: user_ty, literal }
+ }
+ ExprKind::NamedConst { def_id, substs, ref user_ty } => {
+ let user_ty = user_ty.as_ref().map(push_cuta).flatten();
- Constant { span, user_ty: None, literal }
- }
- _ => span_bug!(span, "expression is not a valid constant {:?}", kind),
+ let uneval = mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs);
+ let literal = ConstantKind::Unevaluated(uneval, ty);
+
+ Constant { user_ty, span, literal }
+ }
+ ExprKind::ConstParam { param, def_id: _ } => {
+ let const_param = tcx.mk_const(ty::ConstKind::Param(param), expr.ty);
+ let literal = ConstantKind::Ty(const_param);
+
+ Constant { user_ty: None, span, literal }
+ }
+ ExprKind::ConstBlock { did: def_id, substs } => {
+ let uneval = mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs);
+ let literal = ConstantKind::Unevaluated(uneval, ty);
+
+ Constant { user_ty: None, span, literal }
+ }
+ ExprKind::StaticRef { alloc_id, ty, .. } => {
+ let const_val = ConstValue::Scalar(Scalar::from_pointer(alloc_id.into(), &tcx));
+ let literal = ConstantKind::Val(const_val, ty);
+
+ Constant { span, user_ty: None, literal }
}
+ _ => span_bug!(span, "expression is not a valid constant {:?}", kind),
}
}
let allocation = tcx.intern_const_alloc(allocation);
ConstValue::Slice { data: allocation, start: 0, end: s.len() }
}
- (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _))
+ (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _))
if matches!(inner_ty.kind(), ty::Slice(_)) =>
{
let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]);
let allocation = tcx.intern_const_alloc(allocation);
ConstValue::Slice { data: allocation, start: 0, end: data.len() }
}
- (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
+ (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
let id = tcx.allocate_bytes(data);
ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx))
}