]> git.lizzy.rs Git - rust.git/blob - src/librustc/mir/interpret/queries.rs
Add simpler entry points to const eval for common usages.
[rust.git] / src / librustc / mir / interpret / queries.rs
1 use super::{ConstEvalResult, ErrorHandled, GlobalId};
2
3 use crate::mir;
4 use crate::hir::def_id::DefId;
5 use crate::ty::{self, TyCtxt};
6 use crate::ty::subst::{InternalSubsts, SubstsRef};
7 use syntax_pos::Span;
8
9
10 impl<'tcx> TyCtxt<'tcx> {
11
12     /// Evaluates a constant without providing any substitutions. This is useful to evaluate consts
13     /// that can't take any generic arguments like statics, const items or enum discriminants. If a
14     /// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
15     pub fn const_eval_poly(self, def_id: DefId) -> ConstEvalResult<'tcx> {
16         // In some situations def_id will have substitutions within scope, but they aren't allowed
17         // to be used. So we can't use `Instance::mono`, instead we feed unresolved substitutions
18         // into `const_eval` which will return `ErrorHandled::ToGeneric` if any og them are
19         // encountered.
20         let substs = InternalSubsts::identity_for_item(self, def_id);
21         let instance = ty::Instance::new(def_id, substs);
22         let cid = GlobalId {
23             instance,
24             promoted: None,
25         };
26         let param_env = self.param_env(def_id);
27         self.const_eval_validated(param_env.and(cid))
28     }
29
30     /// Resolves and evaluates a constant.
31     ///
32     /// The constant can be located on a trait like `<A as B>::C`, in which case the given
33     /// substitutions and environment are used to resolve the constant. Alternatively if the
34     /// constant has generic parameters in scope the substitutions are used to evaluate the value of
35     /// the constant. For example in `fn foo<T>() { let _ = [0; bar::<T>()]; }` the repeat count
36     /// constant `bar::<T>()` requires a substitution for `T`, if the substitution for `T` is still
37     /// too generic for the constant to be evaluated then `Err(ErrorHandled::TooGeneric)` is
38     /// returned.
39     pub fn const_eval_resolve(
40         self,
41         param_env: ty::ParamEnv<'tcx>,
42         def_id: DefId,
43         substs: SubstsRef<'tcx>,
44         span: Option<Span>
45     ) -> ConstEvalResult<'tcx> {
46         let instance = ty::Instance::resolve(
47             self,
48             param_env,
49             def_id,
50             substs,
51         );
52         if let Some(instance) = instance {
53             self.const_eval_instance(param_env, instance, span)
54         } else {
55             Err(ErrorHandled::TooGeneric)
56         }
57     }
58
59     pub fn const_eval_instance(
60         self,
61         param_env: ty::ParamEnv<'tcx>,
62         instance: ty::Instance<'tcx>,
63         span: Option<Span>
64     ) -> ConstEvalResult<'tcx> {
65         let cid = GlobalId {
66             instance,
67             promoted: None,
68         };
69         if let Some(span) = span {
70             self.at(span).const_eval_validated(param_env.and(cid))
71         } else {
72             self.const_eval_validated(param_env.and(cid))
73         }
74     }
75
76     /// Evaluate a promoted constant.
77     pub fn const_eval_promoted(
78         self,
79         instance: ty::Instance<'tcx>,
80         promoted: mir::Promoted
81     ) -> ConstEvalResult<'tcx> {
82         let cid = GlobalId {
83             instance,
84             promoted: Some(promoted),
85         };
86         let param_env = ty::ParamEnv::reveal_all();
87         self.const_eval_validated(param_env.and(cid))
88     }
89 }