]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_middle/src/mir/interpret/queries.rs
New upstream version 1.52.0~beta.3+dfsg1
[rustc.git] / compiler / rustc_middle / src / mir / interpret / queries.rs
1 use super::{ErrorHandled, EvalToConstValueResult, GlobalId};
2
3 use crate::mir;
4 use crate::ty::subst::{InternalSubsts, SubstsRef};
5 use crate::ty::{self, TyCtxt};
6 use rustc_hir::def_id::DefId;
7 use rustc_span::Span;
8
9 impl<'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.
13 pub fn const_eval_poly(self, def_id: DefId) -> EvalToConstValueResult<'tcx> {
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
16 // into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are
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 };
21 let param_env = self.param_env(def_id).with_reveal_all_normalized(self);
22 self.const_eval_global_id(param_env, cid, None)
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 #[instrument(level = "debug", skip(self))]
35 pub fn const_eval_resolve(
36 self,
37 param_env: ty::ParamEnv<'tcx>,
38 def: ty::WithOptConstParam<DefId>,
39 substs: SubstsRef<'tcx>,
40 promoted: Option<mir::Promoted>,
41 span: Option<Span>,
42 ) -> EvalToConstValueResult<'tcx> {
43 match ty::Instance::resolve_opt_const_arg(self, param_env, def, substs) {
44 Ok(Some(instance)) => {
45 let cid = GlobalId { instance, promoted };
46 self.const_eval_global_id(param_env, cid, span)
47 }
48 Ok(None) => Err(ErrorHandled::TooGeneric),
49 Err(error_reported) => Err(ErrorHandled::Reported(error_reported)),
50 }
51 }
52
53 pub fn const_eval_instance(
54 self,
55 param_env: ty::ParamEnv<'tcx>,
56 instance: ty::Instance<'tcx>,
57 span: Option<Span>,
58 ) -> EvalToConstValueResult<'tcx> {
59 self.const_eval_global_id(param_env, GlobalId { instance, promoted: None }, span)
60 }
61
62 /// Evaluate a constant.
63 pub fn const_eval_global_id(
64 self,
65 param_env: ty::ParamEnv<'tcx>,
66 cid: GlobalId<'tcx>,
67 span: Option<Span>,
68 ) -> EvalToConstValueResult<'tcx> {
69 // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
70 // improve caching of queries.
71 let inputs = self.erase_regions(param_env.and(cid));
72 if let Some(span) = span {
73 self.at(span).eval_to_const_value_raw(inputs)
74 } else {
75 self.eval_to_const_value_raw(inputs)
76 }
77 }
78
79 /// Evaluate a static's initializer, returning the allocation of the initializer's memory.
80 pub fn eval_static_initializer(
81 self,
82 def_id: DefId,
83 ) -> Result<&'tcx mir::Allocation, ErrorHandled> {
84 trace!("eval_static_initializer: Need to compute {:?}", def_id);
85 assert!(self.is_static(def_id));
86 let instance = ty::Instance::mono(self, def_id);
87 let gid = GlobalId { instance, promoted: None };
88 self.eval_to_allocation(gid, ty::ParamEnv::reveal_all())
89 }
90
91 /// Evaluate anything constant-like, returning the allocation of the final memory.
92 fn eval_to_allocation(
93 self,
94 gid: GlobalId<'tcx>,
95 param_env: ty::ParamEnv<'tcx>,
96 ) -> Result<&'tcx mir::Allocation, ErrorHandled> {
97 trace!("eval_to_allocation: Need to compute {:?}", gid);
98 let raw_const = self.eval_to_allocation_raw(param_env.and(gid))?;
99 Ok(self.global_alloc(raw_const.alloc_id).unwrap_memory())
100 }
101 }