]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_middle/src/mir/interpret/queries.rs
New upstream version 1.50.0+dfsg1
[rustc.git] / compiler / rustc_middle / src / mir / interpret / queries.rs
CommitLineData
1b1a35ee 1use super::{ErrorHandled, EvalToConstValueResult, GlobalId};
dfeec247
XL
2
3use crate::mir;
4use crate::ty::subst::{InternalSubsts, SubstsRef};
5use crate::ty::{self, TyCtxt};
6use rustc_hir::def_id::DefId;
7use rustc_span::Span;
8
9impl<'tcx> TyCtxt<'tcx> {
10 /// Evaluates a constant without providing any substitutions. This is useful to evaluate consts
11 /// that can't take any generic arguments like statics, const items or enum discriminants. If a
12 /// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
1b1a35ee 13 pub fn const_eval_poly(self, def_id: DefId) -> EvalToConstValueResult<'tcx> {
dfeec247
XL
14 // In some situations def_id will have substitutions within scope, but they aren't allowed
15 // to be used. So we can't use `Instance::mono`, instead we feed unresolved substitutions
74b04a01 16 // into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are
dfeec247
XL
17 // encountered.
18 let substs = InternalSubsts::identity_for_item(self, def_id);
19 let instance = ty::Instance::new(def_id, substs);
20 let cid = GlobalId { instance, promoted: None };
3dfed10e 21 let param_env = self.param_env(def_id).with_reveal_all_normalized(self);
74b04a01 22 self.const_eval_global_id(param_env, cid, None)
dfeec247
XL
23 }
24
25 /// Resolves and evaluates a constant.
26 ///
27 /// The constant can be located on a trait like `<A as B>::C`, in which case the given
28 /// substitutions and environment are used to resolve the constant. Alternatively if the
29 /// constant has generic parameters in scope the substitutions are used to evaluate the value of
30 /// the constant. For example in `fn foo<T>() { let _ = [0; bar::<T>()]; }` the repeat count
31 /// constant `bar::<T>()` requires a substitution for `T`, if the substitution for `T` is still
32 /// too generic for the constant to be evaluated then `Err(ErrorHandled::TooGeneric)` is
33 /// returned.
34 pub fn const_eval_resolve(
35 self,
36 param_env: ty::ParamEnv<'tcx>,
3dfed10e 37 def: ty::WithOptConstParam<DefId>,
dfeec247
XL
38 substs: SubstsRef<'tcx>,
39 promoted: Option<mir::Promoted>,
40 span: Option<Span>,
1b1a35ee 41 ) -> EvalToConstValueResult<'tcx> {
3dfed10e 42 match ty::Instance::resolve_opt_const_arg(self, param_env, def, substs) {
f9f354fc
XL
43 Ok(Some(instance)) => {
44 let cid = GlobalId { instance, promoted };
45 self.const_eval_global_id(param_env, cid, span)
46 }
47 Ok(None) => Err(ErrorHandled::TooGeneric),
48 Err(error_reported) => Err(ErrorHandled::Reported(error_reported)),
dfeec247
XL
49 }
50 }
51
52 pub fn const_eval_instance(
53 self,
54 param_env: ty::ParamEnv<'tcx>,
55 instance: ty::Instance<'tcx>,
56 span: Option<Span>,
1b1a35ee 57 ) -> EvalToConstValueResult<'tcx> {
74b04a01 58 self.const_eval_global_id(param_env, GlobalId { instance, promoted: None }, span)
dfeec247
XL
59 }
60
74b04a01
XL
61 /// Evaluate a constant.
62 pub fn const_eval_global_id(
dfeec247
XL
63 self,
64 param_env: ty::ParamEnv<'tcx>,
74b04a01
XL
65 cid: GlobalId<'tcx>,
66 span: Option<Span>,
1b1a35ee 67 ) -> EvalToConstValueResult<'tcx> {
74b04a01
XL
68 // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
69 // improve caching of queries.
fc512014 70 let inputs = self.erase_regions(param_env.and(cid));
74b04a01 71 if let Some(span) = span {
1b1a35ee 72 self.at(span).eval_to_const_value_raw(inputs)
74b04a01 73 } else {
1b1a35ee 74 self.eval_to_const_value_raw(inputs)
74b04a01 75 }
dfeec247 76 }
3dfed10e
XL
77
78 /// Evaluate a static's initializer, returning the allocation of the initializer's memory.
79 pub fn eval_static_initializer(
80 self,
81 def_id: DefId,
82 ) -> Result<&'tcx mir::Allocation, ErrorHandled> {
83 trace!("eval_static_initializer: Need to compute {:?}", def_id);
84 assert!(self.is_static(def_id));
85 let instance = ty::Instance::mono(self, def_id);
86 let gid = GlobalId { instance, promoted: None };
87 self.eval_to_allocation(gid, ty::ParamEnv::reveal_all())
88 }
89
90 /// Evaluate anything constant-like, returning the allocation of the final memory.
91 fn eval_to_allocation(
92 self,
93 gid: GlobalId<'tcx>,
94 param_env: ty::ParamEnv<'tcx>,
95 ) -> Result<&'tcx mir::Allocation, ErrorHandled> {
96 trace!("eval_to_allocation: Need to compute {:?}", gid);
1b1a35ee 97 let raw_const = self.eval_to_allocation_raw(param_env.and(gid))?;
3dfed10e
XL
98 Ok(self.global_alloc(raw_const.alloc_id).unwrap_memory())
99 }
dfeec247 100}