11use super :: { ConstEvalResult , ErrorHandled , GlobalId } ;
22
3+ use crate :: infer:: canonical:: { Canonical , OriginalQueryValues } ;
4+ use crate :: infer:: InferCtxt ;
35use crate :: mir;
46use crate :: ty:: subst:: { InternalSubsts , SubstsRef } ;
57use crate :: ty:: { self , TyCtxt } ;
@@ -19,7 +21,7 @@ impl<'tcx> TyCtxt<'tcx> {
1921 let instance = ty:: Instance :: new ( def_id, substs) ;
2022 let cid = GlobalId { instance, promoted : None } ;
2123 let param_env = self . param_env ( def_id) . with_reveal_all ( ) ;
22- self . const_eval_validated ( param_env. and ( cid) )
24+ self . const_eval_validated ( Canonical :: empty ( param_env. and ( cid) ) )
2325 }
2426
2527 /// Resolves and evaluates a constant.
@@ -38,25 +40,23 @@ impl<'tcx> TyCtxt<'tcx> {
3840 substs : SubstsRef < ' tcx > ,
3941 span : Option < Span > ,
4042 ) -> ConstEvalResult < ' tcx > {
41- let instance = ty:: Instance :: resolve ( self , param_env, def_id, substs) ;
42- if let Some ( instance) = instance {
43- self . const_eval_instance ( param_env, instance, span)
44- } else {
45- Err ( ErrorHandled :: TooGeneric )
46- }
43+ self . infer_ctxt ( )
44+ . enter ( |ref infcx| infcx. const_eval_resolve ( param_env, def_id, substs, span) )
4745 }
4846
47+ /// Evaluates the constant represented by the instance.
4948 pub fn const_eval_instance (
5049 self ,
5150 param_env : ty:: ParamEnv < ' tcx > ,
5251 instance : ty:: Instance < ' tcx > ,
5352 span : Option < Span > ,
5453 ) -> ConstEvalResult < ' tcx > {
5554 let cid = GlobalId { instance, promoted : None } ;
55+ let canonical = Canonical :: empty ( param_env. and ( cid) ) ;
5656 if let Some ( span) = span {
57- self . at ( span) . const_eval_validated ( param_env . and ( cid ) )
57+ self . at ( span) . const_eval_validated ( canonical )
5858 } else {
59- self . const_eval_validated ( param_env . and ( cid ) )
59+ self . const_eval_validated ( canonical )
6060 }
6161 }
6262
@@ -68,6 +68,55 @@ impl<'tcx> TyCtxt<'tcx> {
6868 ) -> ConstEvalResult < ' tcx > {
6969 let cid = GlobalId { instance, promoted : Some ( promoted) } ;
7070 let param_env = ty:: ParamEnv :: reveal_all ( ) ;
71- self . const_eval_validated ( param_env. and ( cid) )
71+ self . const_eval_validated ( Canonical :: empty ( param_env. and ( cid) ) )
72+ }
73+ }
74+
75+ impl < ' a , ' tcx > InferCtxt < ' a , ' tcx > {
76+ /// Evaluates the constant represented by the instance.
77+ ///
78+ /// The given `ParamEnv` and `Instance` can contain inference variables from this inference
79+ /// context.
80+ pub fn const_eval_instance (
81+ & self ,
82+ param_env : ty:: ParamEnv < ' tcx > ,
83+ instance : ty:: Instance < ' tcx > ,
84+ span : Option < Span > ,
85+ ) -> ConstEvalResult < ' tcx > {
86+ let cid = GlobalId { instance, promoted : None } ;
87+ let mut orig_values = OriginalQueryValues :: default ( ) ;
88+ let canonical = self . canonicalize_query ( & param_env. and ( cid) , & mut orig_values) ;
89+ if let Some ( span) = span {
90+ self . tcx . at ( span) . const_eval_validated ( canonical)
91+ } else {
92+ self . tcx . const_eval_validated ( canonical)
93+ }
94+ }
95+
96+ /// Resolves and evaluates a constant.
97+ ///
98+ /// The constant can be located on a trait like `<A as B>::C`, in which case the given
99+ /// substitutions and environment are used to resolve the constant. Alternatively if the
100+ /// constant has generic parameters in scope the substitutions are used to evaluate the value of
101+ /// the constant. For example in `fn foo<T>() { let _ = [0; bar::<T>()]; }` the repeat count
102+ /// constant `bar::<T>()` requires a substitution for `T`, if the substitution for `T` is still
103+ /// too generic for the constant to be evaluated then `Err(ErrorHandled::TooGeneric)` is
104+ /// returned.
105+ ///
106+ /// The given `ParamEnv` and `substs` can contain inference variables from this inference
107+ /// context.
108+ pub fn const_eval_resolve (
109+ & self ,
110+ param_env : ty:: ParamEnv < ' tcx > ,
111+ def_id : DefId ,
112+ substs : SubstsRef < ' tcx > ,
113+ span : Option < Span > ,
114+ ) -> ConstEvalResult < ' tcx > {
115+ let instance = ty:: Instance :: resolve ( self , param_env, def_id, substs) ;
116+ if let Some ( instance) = instance {
117+ self . const_eval_instance ( param_env, instance, span)
118+ } else {
119+ Err ( ErrorHandled :: TooGeneric )
120+ }
72121 }
73122}
0 commit comments