Skip to content

Commit de30d31

Browse files
committed
rustc: fix ty::Const::eval's handling of inference variables.
1 parent 25d8a94 commit de30d31

File tree

1 file changed

+35
-14
lines changed

1 file changed

+35
-14
lines changed

src/librustc/ty/sty.rs

+35-14
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)