Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove the ty field from type system Consts #125958

Merged
merged 11 commits into from
Jun 6, 2024
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
@@ -346,7 +346,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
} else {
let tcx = self.tcx();
let maybe_uneval = match constant.const_ {
Const::Ty(ct) => match ct.kind() {
Const::Ty(_, ct) => match ct.kind() {
ty::ConstKind::Unevaluated(_) => {
bug!("should not encounter unevaluated Const::Ty here, got {:?}", ct)
}
@@ -1856,7 +1856,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {

if let Operand::Constant(constant) = op {
let maybe_uneval = match constant.const_ {
Const::Val(..) | Const::Ty(_) => None,
Const::Val(..) | Const::Ty(_, _) => None,
Const::Unevaluated(uv, _) => Some(uv),
};

4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/type_check/relate_tys.rs
Original file line number Diff line number Diff line change
@@ -193,7 +193,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
types: &mut |_bound_ty: ty::BoundTy| {
unreachable!("we only replace regions in nll_relate, not types")
},
consts: &mut |_bound_var: ty::BoundVar, _ty| {
consts: &mut |_bound_var: ty::BoundVar| {
unreachable!("we only replace regions in nll_relate, not consts")
},
};
@@ -231,7 +231,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
types: &mut |_bound_ty: ty::BoundTy| {
unreachable!("we only replace regions in nll_relate, not types")
},
consts: &mut |_bound_var: ty::BoundVar, _ty| {
consts: &mut |_bound_var: ty::BoundVar| {
unreachable!("we only replace regions in nll_relate, not consts")
},
};
1 change: 1 addition & 0 deletions compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
Original file line number Diff line number Diff line change
@@ -133,6 +133,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
.expect_const()
.eval(fx.tcx, ty::ParamEnv::reveal_all(), span)
.unwrap()
.1
.unwrap_branch();

assert_eq!(x.layout(), y.layout());
1 change: 1 addition & 0 deletions compiler/rustc_codegen_llvm/src/intrinsic.rs
Original file line number Diff line number Diff line change
@@ -1201,6 +1201,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
.expect_const()
.eval(tcx, ty::ParamEnv::reveal_all(), span)
.unwrap()
.1
.unwrap_branch();
let n = idx.len() as u64;

71 changes: 38 additions & 33 deletions compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
Original file line number Diff line number Diff line change
@@ -693,41 +693,46 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
ty::ConstKind::Param(param) => {
write!(output, "{}", param.name)
}
_ => match ct.ty().kind() {
ty::Int(ity) => {
let bits = ct.eval_bits(tcx, ty::ParamEnv::reveal_all());
let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
write!(output, "{val}")
}
ty::Uint(_) => {
let val = ct.eval_bits(tcx, ty::ParamEnv::reveal_all());
write!(output, "{val}")
}
ty::Bool => {
let val = ct.try_eval_bool(tcx, ty::ParamEnv::reveal_all()).unwrap();
write!(output, "{val}")
}
_ => {
// If we cannot evaluate the constant to a known type, we fall back
// to emitting a stable hash value of the constant. This isn't very pretty
// but we get a deterministic, virtually unique value for the constant.
//
// Let's only emit 64 bits of the hash value. That should be plenty for
// avoiding collisions and will make the emitted type names shorter.
let hash_short = tcx.with_stable_hashing_context(|mut hcx| {
let mut hasher = StableHasher::new();
let ct = ct.eval(tcx, ty::ParamEnv::reveal_all(), DUMMY_SP).unwrap();
hcx.while_hashing_spans(false, |hcx| ct.hash_stable(hcx, &mut hasher));
hasher.finish::<Hash64>()
});

if cpp_like_debuginfo(tcx) {
write!(output, "CONST${hash_short:x}")
} else {
write!(output, "{{CONST#{hash_short:x}}}")
ty::ConstKind::Value(ty, _) => {
match ty.kind() {
ty::Int(ity) => {
// FIXME: directly extract the bits from a valtree instead of evaluating an
// alreay evaluated `Const` in order to get the bits.
let bits = ct.eval_bits(tcx, ty::ParamEnv::reveal_all());
let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
write!(output, "{val}")
}
ty::Uint(_) => {
let val = ct.eval_bits(tcx, ty::ParamEnv::reveal_all());
write!(output, "{val}")
}
ty::Bool => {
let val = ct.try_eval_bool(tcx, ty::ParamEnv::reveal_all()).unwrap();
write!(output, "{val}")
}
_ => {
// If we cannot evaluate the constant to a known type, we fall back
// to emitting a stable hash value of the constant. This isn't very pretty
// but we get a deterministic, virtually unique value for the constant.
//
// Let's only emit 64 bits of the hash value. That should be plenty for
// avoiding collisions and will make the emitted type names shorter.
let hash_short = tcx.with_stable_hashing_context(|mut hcx| {
let mut hasher = StableHasher::new();
let ct = ct.eval(tcx, ty::ParamEnv::reveal_all(), DUMMY_SP).unwrap();
hcx.while_hashing_spans(false, |hcx| ct.hash_stable(hcx, &mut hasher));
hasher.finish::<Hash64>()
});

if cpp_like_debuginfo(tcx) {
write!(output, "CONST${hash_short:x}")
} else {
write!(output, "{{CONST#{hash_short:x}}}")
}
}
}
},
}
_ => bug!("Invalid `Const` during codegen: {:?}", ct),
}
.unwrap();
}
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/src/mir/constant.rs
Original file line number Diff line number Diff line change
@@ -40,10 +40,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
) -> Result<Option<ty::ValTree<'tcx>>, ErrorHandled> {
let uv = match self.monomorphize(constant.const_) {
mir::Const::Unevaluated(uv, _) => uv.shrink(),
mir::Const::Ty(c) => match c.kind() {
mir::Const::Ty(_, c) => match c.kind() {
// A constant that came from a const generic but was then used as an argument to old-style
// simd_shuffle (passing as argument instead of as a generic param).
rustc_type_ir::ConstKind::Value(valtree) => return Ok(Some(valtree)),
rustc_type_ir::ConstKind::Value(_, valtree) => return Ok(Some(valtree)),
other => span_bug!(constant.span, "{other:#?}"),
},
// We should never encounter `Const::Val` unless MIR opts (like const prop) evaluate
6 changes: 3 additions & 3 deletions compiler/rustc_const_eval/src/check_consts/qualifs.rs
Original file line number Diff line number Diff line change
@@ -357,15 +357,15 @@ where

// Check the qualifs of the value of `const` items.
let uneval = match constant.const_ {
Const::Ty(ct)
Const::Ty(_, ct)
if matches!(
ct.kind(),
ty::ConstKind::Param(_) | ty::ConstKind::Error(_) | ty::ConstKind::Value(_)
ty::ConstKind::Param(_) | ty::ConstKind::Error(_) | ty::ConstKind::Value(_, _)
) =>
{
None
}
Const::Ty(c) => {
Const::Ty(_, c) => {
bug!("expected ConstKind::Param or ConstKind::Value here, found {:?}", c)
}
Const::Unevaluated(uv, _) => Some(uv),
3 changes: 0 additions & 3 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
@@ -2198,9 +2198,6 @@ fn param_env_with_gat_bounds<'tcx>(
tcx,
ty::INNERMOST,
ty::BoundVar::from_usize(bound_vars.len() - 1),
tcx.type_of(param.def_id)
.no_bound_vars()
.expect("const parameter types cannot be generic"),
)
.into()
}
12 changes: 2 additions & 10 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
@@ -396,16 +396,8 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
Ty::new_error_with_message(self.tcx(), span, "bad placeholder type")
}

fn ct_infer(&self, ty: Ty<'tcx>, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> {
let ty = self.tcx.fold_regions(ty, |r, _| match *r {
rustc_type_ir::RegionKind::ReStatic => r,

// This is never reached in practice. If it ever is reached,
// `ReErased` should be changed to `ReStatic`, and any other region
// left alone.
r => bug!("unexpected region: {r:?}"),
});
ty::Const::new_error_with_message(self.tcx(), ty, span, "bad placeholder constant")
fn ct_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> {
ty::Const::new_error_with_message(self.tcx(), span, "bad placeholder constant")
}

fn probe_ty_param_bounds(
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Original file line number Diff line number Diff line change
@@ -196,7 +196,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
.type_of(param.def_id.to_def_id())
.no_bound_vars()
.expect("const parameters cannot be generic");
let ct = icx.lowerer().lower_const_param(param.hir_id, ct_ty);
let ct = icx.lowerer().lower_const_param(param.hir_id);
predicates
.insert((ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx), param.span));
}
6 changes: 1 addition & 5 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
Original file line number Diff line number Diff line change
@@ -368,11 +368,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
},
)
});
let ty = tcx
.type_of(param.def_id)
.no_bound_vars()
.expect("ct params cannot have early bound vars");
ty::Const::new_error(tcx, guar, ty).into()
ty::Const::new_error(tcx, guar).into()
}
};
num_bound_vars += 1;
54 changes: 23 additions & 31 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
@@ -111,12 +111,7 @@ pub trait HirTyLowerer<'tcx> {
fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx>;

/// Returns the const to use when a const is omitted.
fn ct_infer(
&self,
ty: Ty<'tcx>,
param: Option<&ty::GenericParamDef>,
span: Span,
) -> Const<'tcx>;
fn ct_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx>;

/// Probe bounds in scope where the bounded type coincides with the given type parameter.
///
@@ -439,15 +434,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {

fn provided_kind(
&mut self,
preceding_args: &[ty::GenericArg<'tcx>],
_preceding_args: &[ty::GenericArg<'tcx>],
param: &ty::GenericParamDef,
arg: &GenericArg<'tcx>,
) -> ty::GenericArg<'tcx> {
let tcx = self.lowerer.tcx();

if let Err(incorrect) = self.incorrect_args {
if incorrect.invalid_args.contains(&(param.index as usize)) {
return param.to_error(tcx, preceding_args);
return param.to_error(tcx);
}
}

@@ -487,12 +482,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
ty::Const::from_anon_const(tcx, did).into()
}
(&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => {
let ty = tcx
.at(self.span)
.type_of(param.def_id)
.no_bound_vars()
.expect("const parameter types cannot be generic");
self.lowerer.ct_infer(ty, Some(param), inf.span).into()
self.lowerer.ct_infer(Some(param), inf.span).into()
}
(kind, arg) => span_bug!(
self.span,
@@ -511,7 +501,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {

if let Err(incorrect) = self.incorrect_args {
if incorrect.invalid_args.contains(&(param.index as usize)) {
return param.to_error(tcx, preceding_args);
return param.to_error(tcx);
}
}
match param.kind {
@@ -548,7 +538,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
.no_bound_vars()
.expect("const parameter types cannot be generic");
if let Err(guar) = ty.error_reported() {
return ty::Const::new_error(tcx, guar, ty).into();
return ty::Const::new_error(tcx, guar).into();
}
// FIXME(effects) see if we should special case effect params here
if !infer_args && has_default {
@@ -557,10 +547,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
.into()
} else {
if infer_args {
self.lowerer.ct_infer(ty, Some(param), self.span).into()
self.lowerer.ct_infer(Some(param), self.span).into()
} else {
// We've already errored above about the mismatch.
ty::Const::new_misc_error(tcx, ty).into()
ty::Const::new_misc_error(tcx).into()
}
}
}
@@ -1908,7 +1898,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
///
/// Early-bound const parameters get lowered to [`ty::ConstKind::Param`]
/// and late-bound ones to [`ty::ConstKind::Bound`].
pub(crate) fn lower_const_param(&self, hir_id: HirId, param_ty: Ty<'tcx>) -> Const<'tcx> {
pub(crate) fn lower_const_param(&self, hir_id: HirId) -> Const<'tcx> {
let tcx = self.tcx();
match tcx.named_bound_var(hir_id) {
Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
@@ -1918,12 +1908,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&def_id];
let name = tcx.item_name(def_id);
ty::Const::new_param(tcx, ty::ParamConst::new(index, name), param_ty)
ty::Const::new_param(tcx, ty::ParamConst::new(index, name))
}
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index), param_ty)
ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index))
}
Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar, param_ty),
Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar),
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", hir_id),
}
}
@@ -2139,7 +2129,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
hir::TyKind::Array(ty, length) => {
let length = match length {
hir::ArrayLen::Infer(inf) => self.ct_infer(tcx.types.usize, None, inf.span),
hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
hir::ArrayLen::Body(constant) => {
ty::Const::from_anon_const(tcx, constant.def_id)
}
@@ -2170,17 +2160,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
_ => (expr, None),
};
let c = match &expr.kind {
let (c, c_ty) = match &expr.kind {
hir::ExprKind::Lit(lit) => {
let lit_input =
LitToConstInput { lit: &lit.node, ty, neg: neg.is_some() };
match tcx.lit_to_const(lit_input) {
let ct = match tcx.lit_to_const(lit_input) {
Ok(c) => c,
Err(LitToConstError::Reported(err)) => {
ty::Const::new_error(tcx, err, ty)
ty::Const::new_error(tcx, err)
}
Err(LitToConstError::TypeError) => todo!(),
}
};
(ct, ty)
}

hir::ExprKind::Path(hir::QPath::Resolved(
@@ -2198,19 +2189,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
.type_of(def_id)
.no_bound_vars()
.expect("const parameter types cannot be generic");
self.lower_const_param(expr.hir_id, ty)
let ct = self.lower_const_param(expr.hir_id);
(ct, ty)
}

_ => {
let err = tcx
.dcx()
.emit_err(crate::errors::NonConstRange { span: expr.span });
ty::Const::new_error(tcx, err, ty)
(ty::Const::new_error(tcx, err), Ty::new_error(tcx, err))
}
};
self.record_ty(expr.hir_id, c.ty(), expr.span);
self.record_ty(expr.hir_id, c_ty, expr.span);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 what is this used for, when do we access the type of constants in the TypeckResults?

not something we have to look at in this PR

if let Some((id, span)) = neg {
self.record_ty(id, c.ty(), span);
self.record_ty(id, c_ty, span);
}
c
};
Original file line number Diff line number Diff line change
@@ -143,9 +143,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// `trait_object_dummy_self`, so check for that.
let references_self = match pred.skip_binder().term.unpack() {
ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()),
ty::TermKind::Const(c) => {
c.ty().walk().any(|arg| arg == dummy_self.into())
}
// FIXME(associated_const_equality): We should walk the const instead of not doing anything
ty::TermKind::Const(_) => false,
Copy link
Member

@fmease fmease Jun 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, indeed. You can leave it as is. I need to work on assoc const items inside trait obj tys anyway. Adding one more FIXME is fine.

I've been meaning to fix trait_object_dummy_self getting leaked via const projections (#123456, #123140, #125957) for a while now (but it's ugly).

};

// If the projection output contains `Self`, force the user to
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/demand.rs
Original file line number Diff line number Diff line change
@@ -350,7 +350,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
lt_op: |_| self.tcx.lifetimes.re_erased,
ct_op: |ct| {
if let ty::ConstKind::Infer(_) = ct.kind() {
self.next_const_var(ct.ty(), DUMMY_SP)
self.next_const_var(DUMMY_SP)
} else {
ct
}
Loading
Loading