]>
Commit | Line | Data |
---|---|---|
1b1a35ee | 1 | use super::{ErrorHandled, EvalToConstValueResult, GlobalId}; |
dfeec247 XL |
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. | |
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 | } |