2015-08-18 17:59:21 -04:00
|
|
|
//! See docs in build/expr/mod.rs
|
|
|
|
|
2022-04-12 18:14:28 +02:00
|
|
|
use crate::build::{lit_to_mir_constant, Builder};
|
2022-03-11 12:07:53 +01:00
|
|
|
use rustc_hir::def_id::DefId;
|
2022-03-25 10:06:10 +01:00
|
|
|
use rustc_middle::mir::interpret::{ConstValue, LitToConstError, LitToConstInput, Scalar};
|
2020-03-29 16:41:09 +02:00
|
|
|
use rustc_middle::mir::*;
|
2021-04-04 18:42:17 +02:00
|
|
|
use rustc_middle::thir::*;
|
2022-03-11 12:07:53 +01:00
|
|
|
use rustc_middle::ty::subst::SubstsRef;
|
|
|
|
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt};
|
2015-08-18 17:59:21 -04:00
|
|
|
|
2019-06-01 13:38:36 +02:00
|
|
|
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
2015-08-18 17:59:21 -04:00
|
|
|
/// Compile `expr`, yielding a compile-time constant. Assumes that
|
|
|
|
/// `expr` is a valid compile-time constant!
|
2021-04-03 19:58:46 +02:00
|
|
|
crate fn as_constant(&mut self, expr: &Expr<'tcx>) -> Constant<'tcx> {
|
2022-03-11 12:07:53 +01:00
|
|
|
let create_uneval_from_def_id =
|
|
|
|
|tcx: TyCtxt<'tcx>, def_id: DefId, ty: Ty<'tcx>, substs: SubstsRef<'tcx>| {
|
|
|
|
let uneval = ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs);
|
|
|
|
tcx.mk_const(ty::ConstS { val: ty::ConstKind::Unevaluated(uneval), ty })
|
|
|
|
};
|
|
|
|
|
2015-08-18 17:59:21 -04:00
|
|
|
let this = self;
|
2022-03-11 12:07:53 +01:00
|
|
|
let tcx = this.tcx;
|
2021-03-06 22:24:04 +01:00
|
|
|
let Expr { ty, temp_lifetime: _, span, ref kind } = *expr;
|
2021-03-08 16:18:03 +00:00
|
|
|
match *kind {
|
2021-04-03 19:58:46 +02:00
|
|
|
ExprKind::Scope { region_scope: _, lint_level: _, value } => {
|
|
|
|
this.as_constant(&this.thir[value])
|
|
|
|
}
|
2022-03-11 12:07:53 +01:00
|
|
|
ExprKind::Literal { lit, neg } => {
|
2022-03-23 19:41:35 +01:00
|
|
|
let literal =
|
2022-04-08 11:56:21 +02:00
|
|
|
match lit_to_mir_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg }) {
|
2022-03-23 19:41:35 +01:00
|
|
|
Ok(c) => c,
|
|
|
|
Err(LitToConstError::Reported) => ConstantKind::Ty(tcx.const_error(ty)),
|
|
|
|
Err(LitToConstError::TypeError) => {
|
2022-03-25 10:06:10 +01:00
|
|
|
bug!("encountered type error in `lit_to_mir_constant")
|
2022-03-23 19:41:35 +01:00
|
|
|
}
|
|
|
|
};
|
2022-03-11 12:07:53 +01:00
|
|
|
|
2022-04-13 22:51:34 +02:00
|
|
|
Constant { span, user_ty: None, literal }
|
2022-03-11 12:07:53 +01:00
|
|
|
}
|
2022-03-23 08:47:11 +01:00
|
|
|
ExprKind::NonHirLiteral { lit, user_ty } => {
|
2022-03-11 12:07:53 +01:00
|
|
|
let user_ty = user_ty.map(|user_ty| {
|
|
|
|
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
|
|
|
|
span,
|
|
|
|
user_ty,
|
|
|
|
inferred_ty: ty,
|
|
|
|
})
|
|
|
|
});
|
|
|
|
|
|
|
|
let literal = ConstantKind::Val(ConstValue::Scalar(Scalar::Int(lit)), ty);
|
|
|
|
|
|
|
|
Constant { span, user_ty: user_ty, literal }
|
|
|
|
}
|
|
|
|
ExprKind::NamedConst { def_id, substs, user_ty } => {
|
|
|
|
let user_ty = user_ty.map(|user_ty| {
|
|
|
|
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
|
|
|
|
span,
|
|
|
|
user_ty,
|
|
|
|
inferred_ty: ty,
|
|
|
|
})
|
|
|
|
});
|
|
|
|
let literal = ConstantKind::Ty(create_uneval_from_def_id(tcx, def_id, ty, substs));
|
|
|
|
|
|
|
|
Constant { user_ty, span, literal }
|
|
|
|
}
|
2022-03-15 16:32:40 +01:00
|
|
|
ExprKind::ConstParam { param, def_id: _ } => {
|
|
|
|
let const_param =
|
|
|
|
tcx.mk_const(ty::ConstS { val: ty::ConstKind::Param(param), ty: expr.ty });
|
|
|
|
let literal = ConstantKind::Ty(const_param);
|
2022-03-11 12:07:53 +01:00
|
|
|
|
2022-03-15 16:20:46 +01:00
|
|
|
Constant { user_ty: None, span, literal }
|
2022-03-11 12:07:53 +01:00
|
|
|
}
|
|
|
|
ExprKind::ConstBlock { did: def_id, substs } => {
|
|
|
|
let literal = ConstantKind::Ty(create_uneval_from_def_id(tcx, def_id, ty, substs));
|
|
|
|
|
|
|
|
Constant { user_ty: None, span, literal }
|
2021-02-24 21:29:09 +01:00
|
|
|
}
|
2022-03-07 13:51:59 +01:00
|
|
|
ExprKind::StaticRef { alloc_id, ty, .. } => {
|
2022-03-11 12:07:53 +01:00
|
|
|
let const_val = ConstValue::Scalar(Scalar::from_pointer(alloc_id.into(), &tcx));
|
2022-03-07 13:51:59 +01:00
|
|
|
let literal = ConstantKind::Val(const_val, ty);
|
|
|
|
|
|
|
|
Constant { span, user_ty: None, literal }
|
2021-03-12 13:46:39 +00:00
|
|
|
}
|
2021-03-06 22:24:04 +01:00
|
|
|
_ => span_bug!(span, "expression is not a valid constant {:?}", kind),
|
2015-09-10 15:44:44 -04:00
|
|
|
}
|
2015-08-18 17:59:21 -04:00
|
|
|
}
|
|
|
|
}
|