@@ -2339,43 +2339,41 @@ impl<'tcx> Const<'tcx> {
23392339 /// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
23402340 /// unevaluated constant.
23412341 pub fn eval ( & self , tcx : TyCtxt < ' tcx > , param_env : ParamEnv < ' tcx > ) -> & Const < ' tcx > {
2342- let try_const_eval = | did, param_env : ParamEnv < ' tcx > , substs, promoted| {
2342+ if let ConstKind :: Unevaluated ( did, substs, promoted) = self . val {
23432343 let param_env_and_substs = param_env. with_reveal_all ( ) . and ( substs) ;
23442344
2345- // Avoid querying `tcx.const_eval(...)` with any inference vars.
2346- if param_env_and_substs. needs_infer ( ) {
2347- return None ;
2348- }
2345+ // HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
2346+ // also does later, but we want to do it before checking for
2347+ // inference variables.
2348+ let param_env_and_substs = tcx. erase_regions ( & param_env_and_substs) ;
2349+
2350+ // HACK(eddyb) when the query key would contain inference variables,
2351+ // attempt using identity substs and `ParamEnv` instead, that will succeed
2352+ // when the expression doesn't depend on any parameters.
2353+ // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
2354+ // we can call `infcx.const_eval_resolve` which handles inference variables.
2355+ let param_env_and_substs = if param_env_and_substs. needs_infer ( ) {
2356+ tcx. param_env ( did) . and ( InternalSubsts :: identity_for_item ( tcx, did) )
2357+ } else {
2358+ param_env_and_substs
2359+ } ;
23492360
2361+ // FIXME(eddyb) maybe the `const_eval_*` methods should take
2362+ // `ty::ParamEnvAnd<SubstsRef>` instead of having them separate.
23502363 let ( param_env, substs) = param_env_and_substs. into_parts ( ) ;
2351-
23522364 // try to resolve e.g. associated constants to their definition on an impl, and then
23532365 // evaluate the const.
2354- tcx. const_eval_resolve ( param_env, did, substs, promoted, None )
2355- . ok ( )
2356- . map ( |val| Const :: from_value ( tcx, val, self . ty ) )
2357- } ;
2358-
2359- match self . val {
2360- ConstKind :: Unevaluated ( did, substs, promoted) => {
2361- // HACK(eddyb) when substs contain inference variables,
2362- // attempt using identity substs instead, that will succeed
2363- // when the expression doesn't depend on any parameters.
2364- // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
2365- // we can call `infcx.const_eval_resolve` which handles inference variables.
2366- if substs. needs_infer ( ) {
2367- let identity_substs = InternalSubsts :: identity_for_item ( tcx, did) ;
2368- // The `ParamEnv` needs to match the `identity_substs`.
2369- let identity_param_env = tcx. param_env ( did) ;
2370- match try_const_eval ( did, identity_param_env, identity_substs, promoted) {
2371- Some ( ct) => ct. subst ( tcx, substs) ,
2372- None => self ,
2373- }
2374- } else {
2375- try_const_eval ( did, param_env, substs, promoted) . unwrap_or ( self )
2376- }
2366+ match tcx. const_eval_resolve ( param_env, did, substs, promoted, None ) {
2367+ // NOTE(eddyb) `val` contains no lifetimes/types/consts,
2368+ // and we use the original type, so nothing from `substs`
2369+ // (which may be identity substs, see above),
2370+ // can leak through `val` into the const we return.
2371+ Ok ( val) => Const :: from_value ( tcx, val, self . ty ) ,
2372+
2373+ Err ( _) => self ,
23772374 }
2378- _ => self ,
2375+ } else {
2376+ self
23792377 }
23802378 }
23812379
0 commit comments