@@ -2330,22 +2330,43 @@ impl<'tcx> Const<'tcx> {
23302330 tcx : TyCtxt < ' tcx > ,
23312331 param_env : ParamEnv < ' tcx > ,
23322332 ) -> & 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+
23352352 match self . val {
23362353 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+ }
23492370 } ,
23502371 _ => self ,
23512372 }
0 commit comments