]>
Commit | Line | Data |
---|---|---|
dfeec247 XL |
1 | use super::{ConstEvalResult, ErrorHandled, 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) -> ConstEvalResult<'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 | |
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 }; | |
21 | let param_env = self.param_env(def_id).with_reveal_all(); | |
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>, | |
37 | def_id: DefId, | |
38 | substs: SubstsRef<'tcx>, | |
39 | promoted: Option<mir::Promoted>, | |
40 | span: Option<Span>, | |
41 | ) -> ConstEvalResult<'tcx> { | |
42 | let instance = ty::Instance::resolve(self, param_env, def_id, substs); | |
43 | if let Some(instance) = instance { | |
74b04a01 XL |
44 | let cid = GlobalId { instance, promoted }; |
45 | self.const_eval_global_id(param_env, cid, span) | |
dfeec247 XL |
46 | } else { |
47 | Err(ErrorHandled::TooGeneric) | |
48 | } | |
49 | } | |
50 | ||
51 | pub fn const_eval_instance( | |
52 | self, | |
53 | param_env: ty::ParamEnv<'tcx>, | |
54 | instance: ty::Instance<'tcx>, | |
55 | span: Option<Span>, | |
56 | ) -> ConstEvalResult<'tcx> { | |
74b04a01 | 57 | self.const_eval_global_id(param_env, GlobalId { instance, promoted: None }, span) |
dfeec247 XL |
58 | } |
59 | ||
74b04a01 XL |
60 | /// Evaluate a constant. |
61 | pub fn const_eval_global_id( | |
dfeec247 XL |
62 | self, |
63 | param_env: ty::ParamEnv<'tcx>, | |
74b04a01 XL |
64 | cid: GlobalId<'tcx>, |
65 | span: Option<Span>, | |
dfeec247 | 66 | ) -> ConstEvalResult<'tcx> { |
74b04a01 XL |
67 | // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should |
68 | // improve caching of queries. | |
69 | let inputs = self.erase_regions(¶m_env.and(cid)); | |
70 | if let Some(span) = span { | |
71 | self.at(span).const_eval_validated(inputs) | |
72 | } else { | |
73 | self.const_eval_validated(inputs) | |
74 | } | |
dfeec247 XL |
75 | } |
76 | } |