Skip to content

Commit b2b1a50

Browse files
Rollup merge of rust-lang#113321 - BoxyUwU:move_constkind_to_typeir, r=oli-obk
Move `ty::ConstKind` to `rustc_type_ir` Needed this in another PR for custom debug impls, and this will also be required to move the new solver into a separate crate that does not use `TyCtxt` so that r-a and friends can depend on the trait solver. Rebased on top of rust-lang#113325, only the second and third commits needs reviewing
2 parents 0334b64 + 62174bf commit b2b1a50

File tree

22 files changed

+459
-250
lines changed

22 files changed

+459
-250
lines changed

compiler/rustc_codegen_cranelift/src/base.rs

-1
Original file line numberDiff line numberDiff line change
@@ -706,7 +706,6 @@ fn codegen_stmt<'tcx>(
706706
let times = fx
707707
.monomorphize(times)
708708
.eval(fx.tcx, ParamEnv::reveal_all())
709-
.kind()
710709
.try_to_bits(fx.tcx.data_layout.pointer_size)
711710
.unwrap();
712711
if operand.layout().size.bytes() == 0 {

compiler/rustc_middle/src/mir/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2329,7 +2329,7 @@ impl<'tcx> ConstantKind<'tcx> {
23292329
pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
23302330
match self {
23312331
Self::Ty(c) => {
2332-
if let Some(val) = c.kind().try_eval_for_mir(tcx, param_env) {
2332+
if let Some(val) = c.try_eval_for_mir(tcx, param_env) {
23332333
match val {
23342334
Ok(val) => Self::Val(val, c.ty()),
23352335
Err(guar) => Self::Ty(ty::Const::new_error(tcx, guar, self.ty())),
@@ -2867,7 +2867,7 @@ fn pretty_print_const_value<'tcx>(
28672867
}
28682868
}
28692869
(ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => {
2870-
let n = n.kind().try_to_bits(tcx.data_layout.pointer_size).unwrap();
2870+
let n = n.try_to_bits(tcx.data_layout.pointer_size).unwrap();
28712871
// cast is ok because we already checked for pointer size (32 or 64 bit) above
28722872
let range = AllocRange { start: offset, size: Size::from_bytes(n) };
28732873
let byte_str = alloc.inner().get_bytes_strip_provenance(&tcx, range).unwrap();

compiler/rustc_middle/src/ty/consts.rs

+153-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::middle::resolve_bound_vars as rbv;
2-
use crate::mir::interpret::LitToConstInput;
3-
use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
2+
use crate::mir::interpret::{AllocId, ConstValue, LitToConstInput, Scalar};
3+
use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
44
use rustc_data_structures::intern::Interned;
55
use rustc_error_messages::MultiSpan;
66
use rustc_hir as hir;
@@ -14,9 +14,13 @@ mod valtree;
1414

1515
pub use int::*;
1616
pub use kind::*;
17+
use rustc_span::ErrorGuaranteed;
1718
use rustc_span::DUMMY_SP;
19+
use rustc_target::abi::Size;
1820
pub use valtree::*;
1921

22+
use super::sty::ConstKind;
23+
2024
/// Use this rather than `ConstData`, whenever possible.
2125
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
2226
#[rustc_pass_by_value]
@@ -32,6 +36,16 @@ pub struct ConstData<'tcx> {
3236
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
3337
static_assert_size!(ConstData<'_>, 40);
3438

39+
enum EvalMode {
40+
Typeck,
41+
Mir,
42+
}
43+
44+
enum EvalResult<'tcx> {
45+
ValTree(ty::ValTree<'tcx>),
46+
ConstVal(ConstValue<'tcx>),
47+
}
48+
3549
impl<'tcx> Const<'tcx> {
3650
#[inline]
3751
pub fn ty(self) -> Ty<'tcx> {
@@ -40,7 +54,7 @@ impl<'tcx> Const<'tcx> {
4054

4155
#[inline]
4256
pub fn kind(self) -> ConstKind<'tcx> {
43-
self.0.kind
57+
self.0.kind.clone()
4458
}
4559

4660
#[inline]
@@ -293,12 +307,12 @@ impl<'tcx> Const<'tcx> {
293307
assert_eq!(self.ty(), ty);
294308
let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
295309
// if `ty` does not depend on generic parameters, use an empty param_env
296-
self.kind().eval(tcx, param_env).try_to_bits(size)
310+
self.eval(tcx, param_env).try_to_bits(size)
297311
}
298312

299313
#[inline]
300314
pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> {
301-
self.kind().eval(tcx, param_env).try_to_bool()
315+
self.eval(tcx, param_env).try_to_bool()
302316
}
303317

304318
#[inline]
@@ -307,14 +321,14 @@ impl<'tcx> Const<'tcx> {
307321
tcx: TyCtxt<'tcx>,
308322
param_env: ParamEnv<'tcx>,
309323
) -> Option<u64> {
310-
self.kind().eval(tcx, param_env).try_to_target_usize(tcx)
324+
self.eval(tcx, param_env).try_to_target_usize(tcx)
311325
}
312326

313327
#[inline]
314328
/// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
315329
/// unevaluated constant.
316330
pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Const<'tcx> {
317-
if let Some(val) = self.kind().try_eval_for_typeck(tcx, param_env) {
331+
if let Some(val) = self.try_eval_for_typeck(tcx, param_env) {
318332
match val {
319333
Ok(val) => ty::Const::new_value(tcx, val, self.ty()),
320334
Err(guar) => ty::Const::new_error(tcx, guar, self.ty()),
@@ -339,6 +353,138 @@ impl<'tcx> Const<'tcx> {
339353
.unwrap_or_else(|| bug!("expected usize, got {:#?}", self))
340354
}
341355

356+
#[inline]
357+
/// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
358+
/// return `None`.
359+
// FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged.
360+
pub fn try_eval_for_mir(
361+
self,
362+
tcx: TyCtxt<'tcx>,
363+
param_env: ParamEnv<'tcx>,
364+
) -> Option<Result<ConstValue<'tcx>, ErrorGuaranteed>> {
365+
match self.try_eval_inner(tcx, param_env, EvalMode::Mir) {
366+
Some(Ok(EvalResult::ValTree(_))) => unreachable!(),
367+
Some(Ok(EvalResult::ConstVal(v))) => Some(Ok(v)),
368+
Some(Err(e)) => Some(Err(e)),
369+
None => None,
370+
}
371+
}
372+
373+
#[inline]
374+
/// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
375+
/// return `None`.
376+
// FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged.
377+
pub fn try_eval_for_typeck(
378+
self,
379+
tcx: TyCtxt<'tcx>,
380+
param_env: ParamEnv<'tcx>,
381+
) -> Option<Result<ty::ValTree<'tcx>, ErrorGuaranteed>> {
382+
match self.try_eval_inner(tcx, param_env, EvalMode::Typeck) {
383+
Some(Ok(EvalResult::ValTree(v))) => Some(Ok(v)),
384+
Some(Ok(EvalResult::ConstVal(_))) => unreachable!(),
385+
Some(Err(e)) => Some(Err(e)),
386+
None => None,
387+
}
388+
}
389+
390+
#[inline]
391+
fn try_eval_inner(
392+
self,
393+
tcx: TyCtxt<'tcx>,
394+
param_env: ParamEnv<'tcx>,
395+
eval_mode: EvalMode,
396+
) -> Option<Result<EvalResult<'tcx>, ErrorGuaranteed>> {
397+
assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}");
398+
if let ConstKind::Unevaluated(unevaluated) = self.kind() {
399+
use crate::mir::interpret::ErrorHandled;
400+
401+
// HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
402+
// also does later, but we want to do it before checking for
403+
// inference variables.
404+
// Note that we erase regions *before* calling `with_reveal_all_normalized`,
405+
// so that we don't try to invoke this query with
406+
// any region variables.
407+
408+
// HACK(eddyb) when the query key would contain inference variables,
409+
// attempt using identity substs and `ParamEnv` instead, that will succeed
410+
// when the expression doesn't depend on any parameters.
411+
// FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
412+
// we can call `infcx.const_eval_resolve` which handles inference variables.
413+
let param_env_and = if (param_env, unevaluated).has_non_region_infer() {
414+
tcx.param_env(unevaluated.def).and(ty::UnevaluatedConst {
415+
def: unevaluated.def,
416+
substs: InternalSubsts::identity_for_item(tcx, unevaluated.def),
417+
})
418+
} else {
419+
tcx.erase_regions(param_env)
420+
.with_reveal_all_normalized(tcx)
421+
.and(tcx.erase_regions(unevaluated))
422+
};
423+
424+
// FIXME(eddyb) maybe the `const_eval_*` methods should take
425+
// `ty::ParamEnvAnd` instead of having them separate.
426+
let (param_env, unevaluated) = param_env_and.into_parts();
427+
// try to resolve e.g. associated constants to their definition on an impl, and then
428+
// evaluate the const.
429+
match eval_mode {
430+
EvalMode::Typeck => {
431+
match tcx.const_eval_resolve_for_typeck(param_env, unevaluated, None) {
432+
// NOTE(eddyb) `val` contains no lifetimes/types/consts,
433+
// and we use the original type, so nothing from `substs`
434+
// (which may be identity substs, see above),
435+
// can leak through `val` into the const we return.
436+
Ok(val) => Some(Ok(EvalResult::ValTree(val?))),
437+
Err(ErrorHandled::TooGeneric) => None,
438+
Err(ErrorHandled::Reported(e)) => Some(Err(e.into())),
439+
}
440+
}
441+
EvalMode::Mir => {
442+
match tcx.const_eval_resolve(param_env, unevaluated.expand(), None) {
443+
// NOTE(eddyb) `val` contains no lifetimes/types/consts,
444+
// and we use the original type, so nothing from `substs`
445+
// (which may be identity substs, see above),
446+
// can leak through `val` into the const we return.
447+
Ok(val) => Some(Ok(EvalResult::ConstVal(val))),
448+
Err(ErrorHandled::TooGeneric) => None,
449+
Err(ErrorHandled::Reported(e)) => Some(Err(e.into())),
450+
}
451+
}
452+
}
453+
} else {
454+
None
455+
}
456+
}
457+
458+
#[inline]
459+
pub fn try_to_value(self) -> Option<ty::ValTree<'tcx>> {
460+
if let ConstKind::Value(val) = self.kind() { Some(val) } else { None }
461+
}
462+
463+
#[inline]
464+
pub fn try_to_scalar(self) -> Option<Scalar<AllocId>> {
465+
self.try_to_value()?.try_to_scalar()
466+
}
467+
468+
#[inline]
469+
pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
470+
self.try_to_value()?.try_to_scalar_int()
471+
}
472+
473+
#[inline]
474+
pub fn try_to_bits(self, size: Size) -> Option<u128> {
475+
self.try_to_scalar_int()?.to_bits(size).ok()
476+
}
477+
478+
#[inline]
479+
pub fn try_to_bool(self) -> Option<bool> {
480+
self.try_to_scalar_int()?.try_into().ok()
481+
}
482+
483+
#[inline]
484+
pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
485+
self.try_to_value()?.try_to_target_usize(tcx)
486+
}
487+
342488
pub fn is_ct_infer(self) -> bool {
343489
matches!(self.kind(), ty::ConstKind::Infer(_))
344490
}

0 commit comments

Comments
 (0)