summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_mir_build/src/build/expr/as_constant.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_build/src/build/expr/as_constant.rs')
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_constant.rs163
1 files changed, 93 insertions, 70 deletions
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 37dc1ad9f..717c62315 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -8,7 +8,10 @@ use rustc_middle::mir::interpret::{
};
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;
impl<'a, 'tcx> Builder<'a, 'tcx> {
@@ -18,83 +21,87 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
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) => ConstantKind::Ty(tcx.const_error(ty)),
- 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(ty::ConstS { kind: ty::ConstKind::Param(param), ty: 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),
}
}
@@ -106,7 +113,15 @@ pub(crate) fn lit_to_mir_constant<'tcx>(
let LitToConstInput { lit, ty, neg } = lit_input;
let trunc = |n| {
let param_ty = ty::ParamEnv::reveal_all().and(ty);
- let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size;
+ let width = tcx
+ .layout_of(param_ty)
+ .map_err(|_| {
+ LitToConstError::Reported(tcx.sess.delay_span_bug(
+ DUMMY_SP,
+ format!("couldn't compute width of literal: {:?}", lit_input.lit),
+ ))
+ })?
+ .size;
trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
let result = width.truncate(n);
trace!("trunc result: {}", result);
@@ -137,12 +152,20 @@ pub(crate) fn lit_to_mir_constant<'tcx>(
(ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => {
trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })?
}
- (ast::LitKind::Float(n, _), ty::Float(fty)) => {
- parse_float_into_constval(*n, *fty, neg).ok_or(LitToConstError::Reported)?
- }
+ (ast::LitKind::Float(n, _), ty::Float(fty)) => parse_float_into_constval(*n, *fty, neg)
+ .ok_or_else(|| {
+ LitToConstError::Reported(tcx.sess.delay_span_bug(
+ DUMMY_SP,
+ format!("couldn't parse float literal: {:?}", lit_input.lit),
+ ))
+ })?,
(ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)),
(ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)),
- (ast::LitKind::Err, _) => return Err(LitToConstError::Reported),
+ (ast::LitKind::Err, _) => {
+ return Err(LitToConstError::Reported(
+ tcx.sess.delay_span_bug(DUMMY_SP, "encountered LitKind::Err during mir build"),
+ ));
+ }
_ => return Err(LitToConstError::TypeError),
};