diff options
Diffstat (limited to '')
-rw-r--r-- | compiler/rustc_mir_build/src/build/expr/as_constant.rs | 163 |
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), }; |