@@ -2330,22 +2330,43 @@ impl<'tcx> Const<'tcx> {
2330
2330
tcx : TyCtxt < ' tcx > ,
2331
2331
param_env : ParamEnv < ' tcx > ,
2332
2332
) -> & Const < ' tcx > {
2333
- // FIXME(const_generics): this doesn't work right now,
2334
- // because it tries to relate an `Infer` to a `Param`.
2333
+ let try_const_eval = |did, param_env : ParamEnv < ' tcx > , substs| {
2334
+ let param_env_and_substs = param_env. with_reveal_all ( ) . and ( substs) ;
2335
+
2336
+ // Avoid querying `tcx.const_eval(...)` with any e.g. inference vars.
2337
+ if param_env_and_substs. has_local_value ( ) {
2338
+ return None ;
2339
+ }
2340
+
2341
+ let ( param_env, substs) = param_env_and_substs. into_parts ( ) ;
2342
+
2343
+ // try to resolve e.g. associated constants to their definition on an impl
2344
+ let instance = ty:: Instance :: resolve ( tcx, param_env, did, substs) ?;
2345
+ let gid = GlobalId {
2346
+ instance,
2347
+ promoted : None ,
2348
+ } ;
2349
+ tcx. const_eval ( param_env. and ( gid) ) . ok ( )
2350
+ } ;
2351
+
2335
2352
match self . val {
2336
2353
ConstKind :: Unevaluated ( did, substs) => {
2337
- // if `substs` has no unresolved components, use and empty param_env
2338
- let ( param_env, substs) = param_env. with_reveal_all ( ) . and ( substs) . into_parts ( ) ;
2339
- // try to resolve e.g. associated constants to their definition on an impl
2340
- let instance = match ty:: Instance :: resolve ( tcx, param_env, did, substs) {
2341
- Some ( instance) => instance,
2342
- None => return self ,
2343
- } ;
2344
- let gid = GlobalId {
2345
- instance,
2346
- promoted : None ,
2347
- } ;
2348
- tcx. const_eval ( param_env. and ( gid) ) . unwrap_or ( self )
2354
+ // HACK(eddyb) when substs contain e.g. inference variables,
2355
+ // attempt using identity substs instead, that will succeed
2356
+ // when the expression doesn't depend on any parameters.
2357
+ // FIXME(eddyb) make `const_eval` a canonical query instead,
2358
+ // that would properly handle inference variables in `substs`.
2359
+ if substs. has_local_value ( ) {
2360
+ let identity_substs = InternalSubsts :: identity_for_item ( tcx, did) ;
2361
+ // The `ParamEnv` needs to match the `identity_substs`.
2362
+ let identity_param_env = tcx. param_env ( did) ;
2363
+ match try_const_eval ( did, identity_param_env, identity_substs) {
2364
+ Some ( ct) => ct. subst ( tcx, substs) ,
2365
+ None => self ,
2366
+ }
2367
+ } else {
2368
+ try_const_eval ( did, param_env, substs) . unwrap_or ( self )
2369
+ }
2349
2370
} ,
2350
2371
_ => self ,
2351
2372
}
0 commit comments