@@ -2339,43 +2339,41 @@ impl<'tcx> Const<'tcx> {
2339
2339
/// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
2340
2340
/// unevaluated constant.
2341
2341
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 {
2343
2343
let param_env_and_substs = param_env. with_reveal_all ( ) . and ( substs) ;
2344
2344
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
+ } ;
2349
2360
2361
+ // FIXME(eddyb) maybe the `const_eval_*` methods should take
2362
+ // `ty::ParamEnvAnd<SubstsRef>` instead of having them separate.
2350
2363
let ( param_env, substs) = param_env_and_substs. into_parts ( ) ;
2351
-
2352
2364
// try to resolve e.g. associated constants to their definition on an impl, and then
2353
2365
// 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 ,
2377
2374
}
2378
- _ => self ,
2375
+ } else {
2376
+ self
2379
2377
}
2380
2378
}
2381
2379
0 commit comments