]> git.proxmox.com Git - rustc.git/blame - src/librustc/mir/interpret/queries.rs
New upstream version 1.43.0+dfsg1
[rustc.git] / src / librustc / mir / interpret / queries.rs
CommitLineData
dfeec247
XL
1use super::{ConstEvalResult, ErrorHandled, GlobalId};
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.
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(&param_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}