rust/compiler/rustc_mir_build/src/build/expr/as_constant.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

87 lines
3.7 KiB
Rust
Raw Normal View History

2015-08-18 17:59:21 -04:00
//! See docs in build/expr/mod.rs
use crate::build::{lit_to_mir_constant, Builder};
2022-03-11 12:07:53 +01:00
use rustc_hir::def_id::DefId;
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
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!
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;
match *kind {
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) => {
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
}
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
}
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));
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-08-18 17:59:21 -04:00
}
}