Auto merge of #125958 - BoxyUwU:remove_const_ty, r=lcnr

Remove the `ty` field from type system `Const`s

Fixes #125556
Fixes #122908

Part of the work on `adt_const_params`/`generic_const_param_types`/`min_generic_const_exprs`/generally making the compiler nicer. cc rust-lang/project-const-generics#44

Please review commit-by-commit otherwise I wasted a lot of time not just squashing this into a giant mess (and also it'll be SO much nicer because theres a lot of fluff changes mixed in with other more careful changes if looking via File Changes

---

Why do this?
- The `ty` field keeps causing ICEs and weird behaviour due to it either being treated as "part of the const" or it being forgotten about leading to ICEs.
- As we move forward with `adt_const_params` and a potential `min_generic_const_exprs` it's going to become more complex to actually lower the correct `Ty<'tcx>`
- It muddles the idea behind how we check `Const` arguments have the correct type. By having the `ty` field it may seem like we ought to be relating it when we relate two types, or that its generally important information about the `Const`.
- Brings the compiler more in line with `a-mir-formality` as that also tracks the type of type system `Const`s via `ConstArgHasType` bounds in the env instead of on the `Const` itself.
- A lot of stuff is a lot nicer when you dont have to pass around the type of a const lol. Everywhere we construct `Const` is now significantly nicer 😅

See #125671's description for some more information about the `ty` field

---

General summary of changes in this PR:

- Add `Ty` to `ConstKind::Value` as otherwise there is no way to implement `ConstArgHasType` to ensure that const arguments are correctly typed for the parameter when we stop creating anon consts for all const args. It's also just incredibly difficult/annoying to thread the correct `Ty` around to a bunch of ctfe functions otherwise.
-  Fully implement `ConstArgHasType` in both the old and new solver. Since it now has no reliance on the `ty` field it serves its originally intended purpose of being able to act as a double check that trait vs impls have correctly typed const parameters. It also will now be able to be responsible for checking types of const arguments to parameters under `min_generic_const_exprs`.
- Add `Ty` to `mir::Const::Ty`. I dont have a great understanding of why mir constants are setup like this to be honest. Regardless they need to be able to determine the type of the const and the easiest way to make this happen was to simply store the `Ty` along side the `ty::Const`. Maybe we can do better here in the future but I'd have to spend way more time looking at everywhere we use `mir::Const`.
- rustdoc has its own `Const` which also has a `ty` field. It was relatively easy to remove this.

---

r? `@lcnr` `@compiler-errors`
This commit is contained in:
bors 2024-06-06 03:41:23 +00:00
commit 003a902792
149 changed files with 1159 additions and 1228 deletions

View File

@ -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),
};

View File

@ -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")
},
};

View File

@ -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());

View File

@ -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;

View File

@ -693,8 +693,11 @@ 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::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}")
@ -727,7 +730,9 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
write!(output, "{{CONST#{hash_short:x}}}")
}
}
},
}
}
_ => bug!("Invalid `Const` during codegen: {:?}", ct),
}
.unwrap();
}

View File

@ -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

View File

@ -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),

View File

@ -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()
}

View File

@ -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(

View File

@ -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));
}

View File

@ -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;

View File

@ -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,7 +434,7 @@ 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> {
@ -447,7 +442,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);
}
}
@ -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);
if let Some((id, span)) = neg {
self.record_ty(id, c.ty(), span);
self.record_ty(id, c_ty, span);
}
c
};

View File

@ -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,
};
// If the projection output contains `Self`, force the user to

View File

@ -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
}

View File

@ -436,7 +436,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn lower_array_length(&self, length: &hir::ArrayLen<'tcx>) -> ty::Const<'tcx> {
match length {
hir::ArrayLen::Infer(inf) => self.ct_infer(self.tcx.types.usize, None, inf.span),
hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
hir::ArrayLen::Body(anon_const) => {
let span = self.tcx.def_span(anon_const.def_id);
let c = ty::Const::from_anon_const(self.tcx, anon_const.def_id);
@ -1292,20 +1292,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&GenericParamDefKind::Const { has_default, is_host_effect },
GenericArg::Infer(inf),
) => {
let tcx = self.fcx.tcx();
if has_default && is_host_effect {
self.fcx.var_for_effect(param)
} else {
self.fcx
.ct_infer(
tcx.type_of(param.def_id)
.no_bound_vars()
.expect("const parameter types cannot be generic"),
Some(param),
inf.span,
)
.into()
self.fcx.ct_infer(Some(param), inf.span).into()
}
}
_ => unreachable!(),

View File

@ -237,12 +237,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
}
}
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> {
// FIXME ideally this shouldn't use unwrap
match param {
Some(
@ -252,7 +247,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
},
) => self.var_for_effect(param).as_const().unwrap(),
Some(param) => self.var_for_def(span, param).as_const().unwrap(),
None => self.next_const_var(ty, span),
None => self.next_const_var(span),
}
}

View File

@ -406,16 +406,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
self.cfcx.ty_infer(Some(param), inf.span).into()
}
(GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
let tcx = self.cfcx.tcx();
self.cfcx
.ct_infer(
tcx.type_of(param.def_id)
.no_bound_vars()
.expect("const parameter types cannot be generic"),
Some(param),
inf.span,
)
.into()
self.cfcx.ct_infer(Some(param), inf.span).into()
}
(kind, arg) => {
bug!("mismatched method arg kind {kind:?} in turbofish: {arg:?}")

View File

@ -2096,9 +2096,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP))
.into(),
GenericArgKind::Type(_) => self.next_ty_var(DUMMY_SP).into(),
GenericArgKind::Const(arg) => {
self.next_const_var(arg.ty(), DUMMY_SP).into()
}
GenericArgKind::Const(_) => self.next_const_var(DUMMY_SP).into(),
}
} else {
arg

View File

@ -2409,7 +2409,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
min_len: u64,
) -> (Option<Ty<'tcx>>, Ty<'tcx>) {
let len = match len.eval(self.tcx, self.param_env, span) {
Ok(val) => val
// FIXME(BoxyUwU): Assert the `Ty` is a `usize`?
Ok((_, val)) => val
.try_to_scalar()
.and_then(|scalar| scalar.try_to_int().ok())
.and_then(|int| int.try_to_target_usize(self.tcx).ok()),

View File

@ -863,7 +863,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> {
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
self.handle_term(ct, ty::Const::outer_exclusive_binder, |tcx, guar| {
ty::Const::new_error(tcx, guar, ct.ty())
ty::Const::new_error(tcx, guar)
})
.super_fold_with(self)
}

View File

@ -462,7 +462,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
// any equated inference vars correctly!
let root_vid = self.infcx.unwrap().root_const_var(vid);
if root_vid != vid {
ct = ty::Const::new_var(self.tcx, root_vid, ct.ty());
ct = ty::Const::new_var(self.tcx, root_vid);
vid = root_vid;
}
@ -481,7 +481,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
ui = ty::UniverseIndex::ROOT;
}
return self.canonicalize_const_var(
CanonicalVarInfo { kind: CanonicalVarKind::Const(ui, ct.ty()) },
CanonicalVarInfo { kind: CanonicalVarKind::Const(ui) },
ct,
);
}
@ -510,9 +510,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
}
ty::ConstKind::Placeholder(placeholder) => {
return self.canonicalize_const_var(
CanonicalVarInfo {
kind: CanonicalVarKind::PlaceholderConst(placeholder, ct.ty()),
},
CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderConst(placeholder) },
ct,
);
}
@ -719,9 +717,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
CanonicalVarKind::Region(u) => {
CanonicalVarKind::Region(reverse_universe_map[&u])
}
CanonicalVarKind::Const(u, t) => {
CanonicalVarKind::Const(reverse_universe_map[&u], t)
}
CanonicalVarKind::Const(u) => CanonicalVarKind::Const(reverse_universe_map[&u]),
CanonicalVarKind::PlaceholderTy(placeholder) => {
CanonicalVarKind::PlaceholderTy(ty::Placeholder {
universe: reverse_universe_map[&placeholder.universe],
@ -734,14 +730,11 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
..placeholder
})
}
CanonicalVarKind::PlaceholderConst(placeholder, t) => {
CanonicalVarKind::PlaceholderConst(
ty::Placeholder {
CanonicalVarKind::PlaceholderConst(placeholder) => {
CanonicalVarKind::PlaceholderConst(ty::Placeholder {
universe: reverse_universe_map[&placeholder.universe],
..placeholder
},
t,
)
})
}
},
})
@ -806,6 +799,6 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
!self.infcx.is_some_and(|infcx| const_var != infcx.shallow_resolve_const(const_var))
);
let var = self.canonical_var(info, const_var.into());
ty::Const::new_bound(self.tcx, self.binder_index, var, self.fold_ty(const_var.ty()))
ty::Const::new_bound(self.tcx, self.binder_index, var)
}
}

View File

@ -70,7 +70,7 @@ where
GenericArgKind::Type(ty) => ty,
r => bug!("{:?} is a type but value is {:?}", bound_ty, r),
},
consts: &mut |bound_ct: ty::BoundVar, _| match var_values[bound_ct].unpack() {
consts: &mut |bound_ct: ty::BoundVar| match var_values[bound_ct].unpack() {
GenericArgKind::Const(ct) => ct,
c => bug!("{:?} is a const but value is {:?}", bound_ct, c),
},

View File

@ -143,8 +143,8 @@ impl<'tcx> InferCtxt<'tcx> {
ty::Region::new_placeholder(self.tcx, placeholder_mapped).into()
}
CanonicalVarKind::Const(ui, ty) => {
self.next_const_var_in_universe(ty, span, universe_map(ui)).into()
CanonicalVarKind::Const(ui) => {
self.next_const_var_in_universe(span, universe_map(ui)).into()
}
CanonicalVarKind::Effect => {
let vid = self
@ -153,13 +153,12 @@ impl<'tcx> InferCtxt<'tcx> {
.effect_unification_table()
.new_key(EffectVarValue::Unknown)
.vid;
ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(vid), self.tcx.types.bool)
.into()
ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(vid)).into()
}
CanonicalVarKind::PlaceholderConst(ty::PlaceholderConst { universe, bound }, ty) => {
CanonicalVarKind::PlaceholderConst(ty::PlaceholderConst { universe, bound }) => {
let universe_mapped = universe_map(universe);
let placeholder_mapped = ty::PlaceholderConst { universe: universe_mapped, bound };
ty::Const::new_placeholder(self.tcx, placeholder_mapped, ty).into()
ty::Const::new_placeholder(self.tcx, placeholder_mapped).into()
}
}
}

View File

@ -543,9 +543,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
match arg.unpack() {
GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
GenericArgKind::Type(_) => self.next_ty_var(DUMMY_SP).into(),
GenericArgKind::Const(arg) => {
self.next_const_var(arg.ty(), DUMMY_SP).into()
}
GenericArgKind::Const(_) => self.next_const_var(DUMMY_SP).into(),
}
}))
.unwrap();

View File

@ -79,7 +79,6 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
&mut self,
input: Result<ty::Const<'tcx>, ty::InferConst>,
freshener: F,
ty: Ty<'tcx>,
) -> ty::Const<'tcx>
where
F: FnOnce(u32) -> ty::InferConst,
@ -91,7 +90,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
Entry::Vacant(entry) => {
let index = self.const_freshen_count;
self.const_freshen_count += 1;
let ct = ty::Const::new_infer(self.infcx.tcx, freshener(index), ty);
let ct = ty::Const::new_infer(self.infcx.tcx, freshener(index));
entry.insert(ct);
ct
}
@ -149,7 +148,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> {
ty::InferConst::Var(inner.const_unification_table().find(v).vid)
});
drop(inner);
self.freshen_const(input, ty::InferConst::Fresh, ct.ty())
self.freshen_const(input, ty::InferConst::Fresh)
}
ty::ConstKind::Infer(ty::InferConst::EffectVar(v)) => {
let mut inner = self.infcx.inner.borrow_mut();
@ -158,7 +157,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> {
ty::InferConst::EffectVar(inner.effect_unification_table().find(v).vid)
});
drop(inner);
self.freshen_const(input, ty::InferConst::Fresh, ct.ty())
self.freshen_const(input, ty::InferConst::Fresh)
}
ty::ConstKind::Infer(ty::InferConst::Fresh(i)) => {
if i >= self.const_freshen_count {
@ -177,7 +176,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> {
}
ty::ConstKind::Param(_)
| ty::ConstKind::Value(_)
| ty::ConstKind::Value(_, _)
| ty::ConstKind::Unevaluated(..)
| ty::ConstKind::Expr(..)
| ty::ConstKind::Error(_) => ct.super_fold_with(self),

View File

@ -392,18 +392,18 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
self.opportunistic_resolve_float_var(vid)
}
fn opportunistic_resolve_ct_var(&self, vid: ConstVid, ty: Ty<'tcx>) -> ty::Const<'tcx> {
fn opportunistic_resolve_ct_var(&self, vid: ConstVid) -> ty::Const<'tcx> {
match self.probe_const_var(vid) {
Ok(ct) => ct,
Err(_) => ty::Const::new_var(self.tcx, self.root_const_var(vid), ty),
Err(_) => ty::Const::new_var(self.tcx, self.root_const_var(vid)),
}
}
fn opportunistic_resolve_effect_var(&self, vid: EffectVid, ty: Ty<'tcx>) -> ty::Const<'tcx> {
fn opportunistic_resolve_effect_var(&self, vid: EffectVid) -> ty::Const<'tcx> {
match self.probe_effect_var(vid) {
Some(ct) => ct,
None => {
ty::Const::new_infer(self.tcx, InferConst::EffectVar(self.root_effect_var(vid)), ty)
ty::Const::new_infer(self.tcx, InferConst::EffectVar(self.root_effect_var(vid)))
}
}
}
@ -832,9 +832,7 @@ impl<'tcx> InferCtxt<'tcx> {
(0..table.len())
.map(|i| ty::EffectVid::from_usize(i))
.filter(|&vid| table.probe_value(vid).is_unknown())
.map(|v| {
ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(v), self.tcx.types.bool)
})
.map(|v| ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(v)))
.collect()
}
@ -993,27 +991,22 @@ impl<'tcx> InferCtxt<'tcx> {
Ty::new_var(self.tcx, vid)
}
pub fn next_const_var(&self, ty: Ty<'tcx>, span: Span) -> ty::Const<'tcx> {
self.next_const_var_with_origin(ty, ConstVariableOrigin { span, param_def_id: None })
pub fn next_const_var(&self, span: Span) -> ty::Const<'tcx> {
self.next_const_var_with_origin(ConstVariableOrigin { span, param_def_id: None })
}
pub fn next_const_var_with_origin(
&self,
ty: Ty<'tcx>,
origin: ConstVariableOrigin,
) -> ty::Const<'tcx> {
pub fn next_const_var_with_origin(&self, origin: ConstVariableOrigin) -> ty::Const<'tcx> {
let vid = self
.inner
.borrow_mut()
.const_unification_table()
.new_key(ConstVariableValue::Unknown { origin, universe: self.universe() })
.vid;
ty::Const::new_var(self.tcx, vid, ty)
ty::Const::new_var(self.tcx, vid)
}
pub fn next_const_var_in_universe(
&self,
ty: Ty<'tcx>,
span: Span,
universe: ty::UniverseIndex,
) -> ty::Const<'tcx> {
@ -1024,7 +1017,7 @@ impl<'tcx> InferCtxt<'tcx> {
.const_unification_table()
.new_key(ConstVariableValue::Unknown { origin, universe })
.vid;
ty::Const::new_var(self.tcx, vid, ty)
ty::Const::new_var(self.tcx, vid)
}
pub fn next_const_var_id(&self, origin: ConstVariableOrigin) -> ConstVid {
@ -1135,15 +1128,7 @@ impl<'tcx> InferCtxt<'tcx> {
.const_unification_table()
.new_key(ConstVariableValue::Unknown { origin, universe: self.universe() })
.vid;
ty::Const::new_var(
self.tcx,
const_var_id,
self.tcx
.type_of(param.def_id)
.no_bound_vars()
.expect("const parameter types cannot be generic"),
)
.into()
ty::Const::new_var(self.tcx, const_var_id).into()
}
}
}
@ -1157,7 +1142,7 @@ impl<'tcx> InferCtxt<'tcx> {
.no_bound_vars()
.expect("const parameter types cannot be generic");
debug_assert_eq!(self.tcx.types.bool, ty);
ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(effect_vid), ty).into()
ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(effect_vid)).into()
}
/// Given a set of generics defined on a type or impl, returns the generic parameters mapping each
@ -1314,7 +1299,7 @@ impl<'tcx> InferCtxt<'tcx> {
| ty::ConstKind::Bound(_, _)
| ty::ConstKind::Placeholder(_)
| ty::ConstKind::Unevaluated(_)
| ty::ConstKind::Value(_)
| ty::ConstKind::Value(_, _)
| ty::ConstKind::Error(_)
| ty::ConstKind::Expr(_) => ct,
}
@ -1469,10 +1454,10 @@ impl<'tcx> InferCtxt<'tcx> {
.or_insert_with(|| self.infcx.next_ty_var(self.span).into())
.expect_ty()
}
fn replace_const(&mut self, bv: ty::BoundVar, ty: Ty<'tcx>) -> ty::Const<'tcx> {
fn replace_const(&mut self, bv: ty::BoundVar) -> ty::Const<'tcx> {
self.map
.entry(bv)
.or_insert_with(|| self.infcx.next_const_var(ty, self.span).into())
.or_insert_with(|| self.infcx.next_const_var(self.span).into())
.expect_const()
}
}
@ -1526,11 +1511,14 @@ impl<'tcx> InferCtxt<'tcx> {
&self,
param_env: ty::ParamEnv<'tcx>,
unevaluated: ty::UnevaluatedConst<'tcx>,
ty: Ty<'tcx>,
span: Span,
) -> Result<ty::Const<'tcx>, ErrorHandled> {
match self.const_eval_resolve(param_env, unevaluated, span) {
Ok(Some(val)) => Ok(ty::Const::new_value(self.tcx, val, ty)),
Ok(Some(val)) => Ok(ty::Const::new_value(
self.tcx,
val,
self.tcx.type_of(unevaluated.def).instantiate(self.tcx, unevaluated.args),
)),
Ok(None) => {
let tcx = self.tcx;
let def_id = unevaluated.def;
@ -1964,11 +1952,6 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>(
fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
if let ty::ConstKind::Infer(_) = c.kind() {
let ty = c.ty();
// If the type references param or infer then ICE ICE ICE
if ty.has_non_region_param() || ty.has_non_region_infer() {
bug!("const `{c}`'s type should not reference params or types");
}
ty::Const::new_placeholder(
self.tcx,
ty::PlaceholderConst {
@ -1979,7 +1962,6 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>(
idx
}),
},
ty,
)
} else {
c.super_fold_with(self)

View File

@ -653,7 +653,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
{
variable_table.union(vid, new_var_id);
}
Ok(ty::Const::new_var(self.tcx(), new_var_id, c.ty()))
Ok(ty::Const::new_var(self.tcx(), new_var_id))
}
}
}
@ -671,11 +671,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
args,
args,
)?;
Ok(ty::Const::new_unevaluated(
self.tcx(),
ty::UnevaluatedConst { def, args },
c.ty(),
))
Ok(ty::Const::new_unevaluated(self.tcx(), ty::UnevaluatedConst { def, args }))
}
ty::ConstKind::Placeholder(placeholder) => {
if self.for_universe.can_name(placeholder.universe) {

View File

@ -43,11 +43,10 @@ impl<'tcx> InferCtxt<'tcx> {
ty::PlaceholderType { universe: next_universe, bound: bound_ty },
)
},
consts: &mut |bound_var: ty::BoundVar, ty| {
consts: &mut |bound_var: ty::BoundVar| {
ty::Const::new_placeholder(
self.tcx,
ty::PlaceholderConst { universe: next_universe, bound: bound_var },
ty,
)
},
};

View File

@ -244,7 +244,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for InferenceFudger<'a, 'tcx> {
// Recreate it with a fresh variable here.
let idx = vid.index() - self.const_vars.0.start.index();
let origin = self.const_vars.1[idx];
self.infcx.next_const_var_with_origin(ct.ty(), origin)
self.infcx.next_const_var_with_origin(origin)
} else {
ct
}

View File

@ -204,7 +204,9 @@ pub enum Const<'tcx> {
/// Any way of turning `ty::Const` into `ConstValue` should go through `valtree_to_const_val`;
/// this ensures that we consistently produce "clean" values without data in the padding or
/// anything like that.
Ty(ty::Const<'tcx>),
///
/// FIXME(BoxyUwU): We should remove this `Ty` and look up the type for params via `ParamEnv`
Ty(Ty<'tcx>, ty::Const<'tcx>),
/// An unevaluated mir constant which is not part of the type system.
///
@ -237,7 +239,15 @@ impl<'tcx> Const<'tcx> {
#[inline(always)]
pub fn ty(&self) -> Ty<'tcx> {
match self {
Const::Ty(c) => c.ty(),
Const::Ty(ty, ct) => {
match ct.kind() {
// Dont use the outter ty as on invalid code we can wind up with them not being the same.
// this then results in allowing const eval to add `1_i64 + 1_usize` in cases where the mir
// was originally `({N: usize} + 1_usize)` under `generic_const_exprs`.
ty::ConstKind::Value(ty, _) => ty,
_ => *ty,
}
}
Const::Val(_, ty) | Const::Unevaluated(_, ty) => *ty,
}
}
@ -247,8 +257,8 @@ impl<'tcx> Const<'tcx> {
#[inline]
pub fn is_required_const(&self) -> bool {
match self {
Const::Ty(c) => match c.kind() {
ty::ConstKind::Value(_) => false, // already a value, cannot error
Const::Ty(_, c) => match c.kind() {
ty::ConstKind::Value(_, _) => false, // already a value, cannot error
_ => true,
},
Const::Val(..) => false, // already a value, cannot error
@ -259,8 +269,8 @@ impl<'tcx> Const<'tcx> {
#[inline]
pub fn try_to_scalar(self) -> Option<Scalar> {
match self {
Const::Ty(c) => match c.kind() {
ty::ConstKind::Value(valtree) if c.ty().is_primitive() => {
Const::Ty(_, c) => match c.kind() {
ty::ConstKind::Value(ty, valtree) if ty.is_primitive() => {
// A valtree of a type where leaves directly represent the scalar const value.
// Just checking whether it is a leaf is insufficient as e.g. references are leafs
// but the leaf value is the value they point to, not the reference itself!
@ -278,8 +288,8 @@ impl<'tcx> Const<'tcx> {
// This is equivalent to `self.try_to_scalar()?.try_to_int().ok()`, but measurably faster.
match self {
Const::Val(ConstValue::Scalar(Scalar::Int(x)), _) => Some(x),
Const::Ty(c) => match c.kind() {
ty::ConstKind::Value(valtree) if c.ty().is_primitive() => {
Const::Ty(_, c) => match c.kind() {
ty::ConstKind::Value(ty, valtree) if ty.is_primitive() => {
Some(valtree.unwrap_leaf())
}
_ => None,
@ -306,11 +316,11 @@ impl<'tcx> Const<'tcx> {
span: Span,
) -> Result<ConstValue<'tcx>, ErrorHandled> {
match self {
Const::Ty(c) => {
Const::Ty(_, c) => {
// We want to consistently have a "clean" value for type system constants (i.e., no
// data hidden in the padding), so we always go through a valtree here.
let val = c.eval(tcx, param_env, span)?;
Ok(tcx.valtree_to_const_val((self.ty(), val)))
let (ty, val) = c.eval(tcx, param_env, span)?;
Ok(tcx.valtree_to_const_val((ty, val)))
}
Const::Unevaluated(uneval, _) => {
// FIXME: We might want to have a `try_eval`-like function on `Unevaluated`
@ -326,7 +336,7 @@ impl<'tcx> Const<'tcx> {
match self.eval(tcx, param_env, DUMMY_SP) {
Ok(val) => Self::Val(val, self.ty()),
Err(ErrorHandled::Reported(guar, _span)) => {
Self::Ty(ty::Const::new_error(tcx, guar.into(), self.ty()))
Self::Ty(Ty::new_error(tcx, guar.into()), ty::Const::new_error(tcx, guar.into()))
}
Err(ErrorHandled::TooGeneric(_span)) => self,
}
@ -338,15 +348,16 @@ impl<'tcx> Const<'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> Option<Scalar> {
match self {
Const::Ty(c) if c.ty().is_primitive() => {
if let Const::Ty(_, c) = self
&& let ty::ConstKind::Value(ty, val) = c.kind()
&& ty.is_primitive()
{
// Avoid the `valtree_to_const_val` query. Can only be done on primitive types that
// are valtree leaves, and *not* on references. (References should return the
// pointer here, which valtrees don't represent.)
let val = c.eval(tcx, param_env, DUMMY_SP).ok()?;
Some(val.unwrap_leaf().into())
}
_ => self.eval(tcx, param_env, DUMMY_SP).ok()?.try_to_scalar(),
} else {
self.eval(tcx, param_env, DUMMY_SP).ok()?.try_to_scalar()
}
}
@ -439,14 +450,14 @@ impl<'tcx> Const<'tcx> {
Self::Val(val, ty)
}
pub fn from_ty_const(c: ty::Const<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
pub fn from_ty_const(c: ty::Const<'tcx>, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
match c.kind() {
ty::ConstKind::Value(valtree) => {
ty::ConstKind::Value(ty, valtree) => {
// Make sure that if `c` is normalized, then the return value is normalized.
let const_val = tcx.valtree_to_const_val((c.ty(), valtree));
Self::Val(const_val, c.ty())
let const_val = tcx.valtree_to_const_val((ty, valtree));
Self::Val(const_val, ty)
}
_ => Self::Ty(c),
_ => Self::Ty(ty, c),
}
}
@ -458,12 +469,12 @@ impl<'tcx> Const<'tcx> {
// - valtrees purposefully generate new allocations
// - ConstValue::Slice also generate new allocations
match self {
Const::Ty(c) => match c.kind() {
Const::Ty(_, c) => match c.kind() {
ty::ConstKind::Param(..) => true,
// A valtree may be a reference. Valtree references correspond to a
// different allocation each time they are evaluated. Valtrees for primitive
// types are fine though.
ty::ConstKind::Value(_) => c.ty().is_primitive(),
ty::ConstKind::Value(ty, _) => ty.is_primitive(),
ty::ConstKind::Unevaluated(..) | ty::ConstKind::Expr(..) => false,
// This can happen if evaluation of a constant failed. The result does not matter
// much since compilation is doomed.
@ -517,7 +528,7 @@ impl<'tcx> UnevaluatedConst<'tcx> {
impl<'tcx> Display for Const<'tcx> {
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
match *self {
Const::Ty(c) => pretty_print_const(c, fmt, true),
Const::Ty(_, c) => pretty_print_const(c, fmt, true),
Const::Val(val, ty) => pretty_print_const_value(val, ty, fmt),
// FIXME(valtrees): Correctly print mir constants.
Const::Unevaluated(c, _ty) => {

View File

@ -1313,12 +1313,12 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
};
let val = match const_ {
Const::Ty(ct) => match ct.kind() {
Const::Ty(_, ct) => match ct.kind() {
ty::ConstKind::Param(p) => format!("ty::Param({p})"),
ty::ConstKind::Unevaluated(uv) => {
format!("ty::Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.args,)
}
ty::ConstKind::Value(val) => format!("ty::Valtree({})", fmt_valtree(&val)),
ty::ConstKind::Value(_, val) => format!("ty::Valtree({})", fmt_valtree(&val)),
// No `ty::` prefix since we also use this to represent errors from `mir::Unevaluated`.
ty::ConstKind::Error(_) => "Error".to_string(),
// These variants shouldn't exist in the MIR.
@ -1417,7 +1417,7 @@ pub fn write_allocations<'tcx>(
impl<'tcx> Visitor<'tcx> for CollectAllocIds {
fn visit_constant(&mut self, c: &ConstOperand<'tcx>, _: Location) {
match c.const_ {
Const::Ty(_) | Const::Unevaluated(..) => {}
Const::Ty(_, _) | Const::Unevaluated(..) => {}
Const::Val(val, _) => {
self.0.extend(alloc_ids_from_const_val(val));
}

View File

@ -895,7 +895,7 @@ macro_rules! make_mir_visitor {
self.visit_span($(& $mutability)? *span);
match const_ {
Const::Ty(ct) => self.visit_ty_const($(&$mutability)? *ct, location),
Const::Ty(_, ct) => self.visit_ty_const($(&$mutability)? *ct, location),
Const::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
Const::Unevaluated(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
}

View File

@ -616,6 +616,8 @@ pub enum SelectionError<'tcx> {
/// We can thus not know whether the hidden type implements an auto trait, so
/// we should not presume anything about it.
OpaqueTypeAutoTraitLeakageUnknown(DefId),
/// Error for a `ConstArgHasType` goal
ConstArgHasWrongType { ct: ty::Const<'tcx>, ct_ty: Ty<'tcx>, expected_ty: Ty<'tcx> },
}
#[derive(Clone, Debug, TypeVisitable)]

View File

@ -53,7 +53,7 @@ impl<'tcx> TyCtxt<'tcx> {
fn fold_const(&mut self, c: Const<'tcx>) -> Const<'tcx> {
let ct = match c.kind() {
ty::ConstKind::Unevaluated(uv) => match self.tcx.thir_abstract_const(uv.def) {
Err(e) => ty::Const::new_error(self.tcx, e, c.ty()),
Err(e) => ty::Const::new_error(self.tcx, e),
Ok(Some(bac)) => {
let args = self.tcx.erase_regions(uv.args);
let bac = bac.instantiate(self.tcx, args);

View File

@ -350,8 +350,8 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Const<'tcx> {
fn decode(decoder: &mut D) -> Self {
let consts: ty::ConstData<'tcx> = Decodable::decode(decoder);
decoder.interner().mk_ct_from_kind(consts.kind, consts.ty)
let kind: ty::ConstKind<'tcx> = Decodable::decode(decoder);
decoder.interner().mk_ct_from_kind(kind)
}
}

View File

@ -6,7 +6,7 @@ use rustc_error_messages::MultiSpan;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::LocalDefId;
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
use rustc_macros::HashStable;
use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
use tracing::{debug, instrument};
@ -24,12 +24,11 @@ pub type ConstKind<'tcx> = ir::ConstKind<TyCtxt<'tcx>>;
pub type UnevaluatedConst<'tcx> = ir::UnevaluatedConst<TyCtxt<'tcx>>;
#[cfg(target_pointer_width = "64")]
rustc_data_structures::static_assert_size!(ConstKind<'_>, 24);
rustc_data_structures::static_assert_size!(ConstKind<'_>, 32);
/// Use this rather than `ConstData`, whenever possible.
#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)]
#[rustc_pass_by_value]
pub struct Const<'tcx>(pub(super) Interned<'tcx, WithCachedTypeInfo<ConstData<'tcx>>>);
pub struct Const<'tcx>(pub(super) Interned<'tcx, WithCachedTypeInfo<ConstKind<'tcx>>>);
impl<'tcx> rustc_type_ir::inherent::IntoKind for Const<'tcx> {
type Kind = ConstKind<'tcx>;
@ -49,26 +48,11 @@ impl<'tcx> rustc_type_ir::visit::Flags for Const<'tcx> {
}
}
/// Typed constant value.
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
#[derive(HashStable, TyEncodable, TyDecodable)]
pub struct ConstData<'tcx> {
pub ty: Ty<'tcx>,
pub kind: ConstKind<'tcx>,
}
#[cfg(target_pointer_width = "64")]
rustc_data_structures::static_assert_size!(ConstData<'_>, 32);
impl<'tcx> Const<'tcx> {
#[inline]
pub fn ty(self) -> Ty<'tcx> {
self.0.ty
}
#[inline]
pub fn kind(self) -> ConstKind<'tcx> {
self.0.kind
let a: &ConstKind<'tcx> = self.0.0;
*a
}
// FIXME(compiler-errors): Think about removing this.
@ -84,28 +68,28 @@ impl<'tcx> Const<'tcx> {
}
#[inline]
pub fn new(tcx: TyCtxt<'tcx>, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
tcx.mk_ct_from_kind(kind, ty)
pub fn new(tcx: TyCtxt<'tcx>, kind: ty::ConstKind<'tcx>) -> Const<'tcx> {
tcx.mk_ct_from_kind(kind)
}
#[inline]
pub fn new_param(tcx: TyCtxt<'tcx>, param: ty::ParamConst, ty: Ty<'tcx>) -> Const<'tcx> {
Const::new(tcx, ty::ConstKind::Param(param), ty)
pub fn new_param(tcx: TyCtxt<'tcx>, param: ty::ParamConst) -> Const<'tcx> {
Const::new(tcx, ty::ConstKind::Param(param))
}
#[inline]
pub fn new_var(tcx: TyCtxt<'tcx>, infer: ty::ConstVid, ty: Ty<'tcx>) -> Const<'tcx> {
Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Var(infer)), ty)
pub fn new_var(tcx: TyCtxt<'tcx>, infer: ty::ConstVid) -> Const<'tcx> {
Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Var(infer)))
}
#[inline]
pub fn new_fresh(tcx: TyCtxt<'tcx>, fresh: u32, ty: Ty<'tcx>) -> Const<'tcx> {
Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Fresh(fresh)), ty)
pub fn new_fresh(tcx: TyCtxt<'tcx>, fresh: u32) -> Const<'tcx> {
Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Fresh(fresh)))
}
#[inline]
pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst, ty: Ty<'tcx>) -> Const<'tcx> {
Const::new(tcx, ty::ConstKind::Infer(infer), ty)
pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst) -> Const<'tcx> {
Const::new(tcx, ty::ConstKind::Infer(infer))
}
#[inline]
@ -113,50 +97,40 @@ impl<'tcx> Const<'tcx> {
tcx: TyCtxt<'tcx>,
debruijn: ty::DebruijnIndex,
var: ty::BoundVar,
ty: Ty<'tcx>,
) -> Const<'tcx> {
Const::new(tcx, ty::ConstKind::Bound(debruijn, var), ty)
Const::new(tcx, ty::ConstKind::Bound(debruijn, var))
}
#[inline]
pub fn new_placeholder(
tcx: TyCtxt<'tcx>,
placeholder: ty::PlaceholderConst,
ty: Ty<'tcx>,
) -> Const<'tcx> {
Const::new(tcx, ty::ConstKind::Placeholder(placeholder), ty)
pub fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderConst) -> Const<'tcx> {
Const::new(tcx, ty::ConstKind::Placeholder(placeholder))
}
#[inline]
pub fn new_unevaluated(
tcx: TyCtxt<'tcx>,
uv: ty::UnevaluatedConst<'tcx>,
ty: Ty<'tcx>,
) -> Const<'tcx> {
Const::new(tcx, ty::ConstKind::Unevaluated(uv), ty)
pub fn new_unevaluated(tcx: TyCtxt<'tcx>, uv: ty::UnevaluatedConst<'tcx>) -> Const<'tcx> {
Const::new(tcx, ty::ConstKind::Unevaluated(uv))
}
#[inline]
pub fn new_value(tcx: TyCtxt<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
Const::new(tcx, ty::ConstKind::Value(val), ty)
Const::new(tcx, ty::ConstKind::Value(ty, val))
}
#[inline]
pub fn new_expr(tcx: TyCtxt<'tcx>, expr: ty::Expr<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
Const::new(tcx, ty::ConstKind::Expr(expr), ty)
pub fn new_expr(tcx: TyCtxt<'tcx>, expr: ty::Expr<'tcx>) -> Const<'tcx> {
Const::new(tcx, ty::ConstKind::Expr(expr))
}
#[inline]
pub fn new_error(tcx: TyCtxt<'tcx>, e: ty::ErrorGuaranteed, ty: Ty<'tcx>) -> Const<'tcx> {
Const::new(tcx, ty::ConstKind::Error(e), ty)
pub fn new_error(tcx: TyCtxt<'tcx>, e: ty::ErrorGuaranteed) -> Const<'tcx> {
Const::new(tcx, ty::ConstKind::Error(e))
}
/// Like [Ty::new_error] but for constants.
#[track_caller]
pub fn new_misc_error(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
pub fn new_misc_error(tcx: TyCtxt<'tcx>) -> Const<'tcx> {
Const::new_error_with_message(
tcx,
ty,
DUMMY_SP,
"ty::ConstKind::Error constructed but no error reported",
)
@ -166,52 +140,33 @@ impl<'tcx> Const<'tcx> {
#[track_caller]
pub fn new_error_with_message<S: Into<MultiSpan>>(
tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>,
span: S,
msg: &'static str,
) -> Const<'tcx> {
let reported = tcx.dcx().span_delayed_bug(span, msg);
Const::new_error(tcx, reported, ty)
Const::new_error(tcx, reported)
}
}
impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst, ty: Ty<'tcx>) -> Self {
Const::new_infer(tcx, infer, ty)
fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst) -> Self {
Const::new_infer(tcx, infer)
}
fn new_var(tcx: TyCtxt<'tcx>, vid: ty::ConstVid, ty: Ty<'tcx>) -> Self {
Const::new_var(tcx, vid, ty)
fn new_var(tcx: TyCtxt<'tcx>, vid: ty::ConstVid) -> Self {
Const::new_var(tcx, vid)
}
fn new_bound(
interner: TyCtxt<'tcx>,
debruijn: ty::DebruijnIndex,
var: ty::BoundVar,
ty: Ty<'tcx>,
) -> Self {
Const::new_bound(interner, debruijn, var, ty)
fn new_bound(interner: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
Const::new_bound(interner, debruijn, var)
}
fn new_anon_bound(
tcx: TyCtxt<'tcx>,
debruijn: ty::DebruijnIndex,
var: ty::BoundVar,
ty: Ty<'tcx>,
) -> Self {
Const::new_bound(tcx, debruijn, var, ty)
fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
Const::new_bound(tcx, debruijn, var)
}
fn new_unevaluated(
interner: TyCtxt<'tcx>,
uv: ty::UnevaluatedConst<'tcx>,
ty: Ty<'tcx>,
) -> Self {
Const::new_unevaluated(interner, uv, ty)
}
fn ty(self) -> Ty<'tcx> {
self.ty()
fn new_unevaluated(interner: TyCtxt<'tcx>, uv: ty::UnevaluatedConst<'tcx>) -> Self {
Const::new_unevaluated(interner, uv)
}
}
@ -241,7 +196,6 @@ impl<'tcx> Const<'tcx> {
def: def.to_def_id(),
args: GenericArgs::identity_for_item(tcx, def.to_def_id()),
},
ty,
),
}
}
@ -293,9 +247,6 @@ impl<'tcx> Const<'tcx> {
_,
&hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. },
)) => {
// Use the type from the param's definition, since we can resolve it,
// not the expected parameter type from WithOptConstParam.
let param_ty = tcx.type_of(def_id).instantiate_identity();
match tcx.named_bound_var(expr.hir_id) {
Some(rbv::ResolvedArg::EarlyBound(_)) => {
// Find the name and index of the const parameter by indexing the generics of
@ -304,19 +255,12 @@ impl<'tcx> Const<'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);
Some(ty::Const::new_param(tcx, ty::ParamConst::new(index, name), param_ty))
Some(ty::Const::new_param(tcx, ty::ParamConst::new(index, name)))
}
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
Some(ty::Const::new_bound(
tcx,
debruijn,
ty::BoundVar::from_u32(index),
param_ty,
))
}
Some(rbv::ResolvedArg::Error(guar)) => {
Some(ty::Const::new_error(tcx, guar, param_ty))
Some(ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index)))
}
Some(rbv::ResolvedArg::Error(guar)) => Some(ty::Const::new_error(tcx, guar)),
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
}
}
@ -363,7 +307,7 @@ impl<'tcx> Const<'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
span: Span,
) -> Result<ValTree<'tcx>, ErrorHandled> {
) -> Result<(Ty<'tcx>, ValTree<'tcx>), ErrorHandled> {
assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}");
match self.kind() {
ConstKind::Unevaluated(unevaluated) => {
@ -381,9 +325,9 @@ impl<'tcx> Const<'tcx> {
);
return Err(e.into());
};
Ok(c)
Ok((tcx.type_of(unevaluated.def).instantiate(tcx, unevaluated.args), c))
}
ConstKind::Value(val) => Ok(val),
ConstKind::Value(ty, val) => Ok((ty, val)),
ConstKind::Error(g) => Err(g.into()),
ConstKind::Param(_)
| ConstKind::Infer(_)
@ -397,8 +341,8 @@ impl<'tcx> Const<'tcx> {
#[inline]
pub fn normalize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self {
match self.eval(tcx, param_env, DUMMY_SP) {
Ok(val) => Self::new_value(tcx, val, self.ty()),
Err(ErrorHandled::Reported(r, _span)) => Self::new_error(tcx, r.into(), self.ty()),
Ok((ty, val)) => Self::new_value(tcx, val, ty),
Err(ErrorHandled::Reported(r, _span)) => Self::new_error(tcx, r.into()),
Err(ErrorHandled::TooGeneric(_span)) => self,
}
}
@ -408,8 +352,10 @@ impl<'tcx> Const<'tcx> {
self,
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> Option<Scalar> {
self.eval(tcx, param_env, DUMMY_SP).ok()?.try_to_scalar()
) -> Option<(Ty<'tcx>, Scalar)> {
let (ty, val) = self.eval(tcx, param_env, DUMMY_SP).ok()?;
let val = val.try_to_scalar()?;
Some((ty, val))
}
#[inline]
@ -420,8 +366,10 @@ impl<'tcx> Const<'tcx> {
self,
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
) -> Option<ScalarInt> {
self.try_eval_scalar(tcx, param_env)?.try_to_int().ok()
) -> Option<(Ty<'tcx>, ScalarInt)> {
let (ty, scalar) = self.try_eval_scalar(tcx, param_env)?;
let val = scalar.try_to_int().ok()?;
Some((ty, val))
}
#[inline]
@ -429,18 +377,17 @@ impl<'tcx> Const<'tcx> {
/// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it
/// contains const generic parameters or pointers).
pub fn try_eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<u128> {
let int = self.try_eval_scalar_int(tcx, param_env)?;
let size =
tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(self.ty())).ok()?.size;
let (ty, scalar) = self.try_eval_scalar_int(tcx, param_env)?;
let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
// if `ty` does not depend on generic parameters, use an empty param_env
int.try_to_bits(size).ok()
scalar.try_to_bits(size).ok()
}
#[inline]
/// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u128 {
self.try_eval_bits(tcx, param_env)
.unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", self.ty(), self))
.unwrap_or_else(|| bug!("failed to evalate {:#?} to bits", self))
}
#[inline]
@ -449,12 +396,14 @@ impl<'tcx> Const<'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
) -> Option<u64> {
self.try_eval_scalar_int(tcx, param_env)?.try_to_target_usize(tcx).ok()
let (_, scalar) = self.try_eval_scalar_int(tcx, param_env)?;
scalar.try_to_target_usize(tcx).ok()
}
#[inline]
pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> {
self.try_eval_scalar_int(tcx, param_env)?.try_into().ok()
let (_, scalar) = self.try_eval_scalar_int(tcx, param_env)?;
scalar.try_into().ok()
}
#[inline]
@ -467,7 +416,7 @@ impl<'tcx> Const<'tcx> {
/// Panics if self.kind != ty::ConstKind::Value
pub fn to_valtree(self) -> ty::ValTree<'tcx> {
match self.kind() {
ty::ConstKind::Value(valtree) => valtree,
ty::ConstKind::Value(_, valtree) => valtree,
_ => bug!("expected ConstKind::Value, got {:?}", self.kind()),
}
}
@ -475,7 +424,7 @@ impl<'tcx> Const<'tcx> {
/// Attempts to convert to a `ValTree`
pub fn try_to_valtree(self) -> Option<ty::ValTree<'tcx>> {
match self.kind() {
ty::ConstKind::Value(valtree) => Some(valtree),
ty::ConstKind::Value(_, valtree) => Some(valtree),
_ => None,
}
}

View File

@ -104,10 +104,12 @@ impl<'tcx> Expr<'tcx> {
tcx: TyCtxt<'tcx>,
func_ty: Ty<'tcx>,
func_expr: Const<'tcx>,
arguments: impl Iterator<Item = Const<'tcx>>,
arguments: impl IntoIterator<Item = Const<'tcx>>,
) -> Self {
let args = tcx.mk_args_from_iter::<_, ty::GenericArg<'tcx>>(
[func_ty.into(), func_expr.into()].into_iter().chain(arguments.map(|ct| ct.into())),
[func_ty.into(), func_expr.into()]
.into_iter()
.chain(arguments.into_iter().map(|ct| ct.into())),
);
Self { kind: ExprKind::FunctionCall, args }
@ -155,7 +157,7 @@ impl<'tcx> Expr<'tcx> {
Self { kind, args }
}
pub fn args(&self) -> ty::GenericArgsRef<'tcx> {
pub fn args(self) -> ty::GenericArgsRef<'tcx> {
self.args
}
}

View File

@ -28,10 +28,10 @@ use crate::traits::solve::{
};
use crate::ty::predicate::ExistentialPredicateStableCmpExt as _;
use crate::ty::{
self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, ConstData,
GenericParamDefKind, ImplPolarity, List, ListWithCachedTypeInfo, ParamConst, ParamTy, Pattern,
PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicatePolarity,
Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, Visibility,
self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, GenericParamDefKind,
ImplPolarity, List, ListWithCachedTypeInfo, ParamConst, ParamTy, Pattern, PatternKind,
PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicatePolarity, Region,
RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, Visibility,
};
use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
use rustc_ast::{self as ast, attr};
@ -268,7 +268,7 @@ pub struct CtxtInterners<'tcx> {
clauses: InternedSet<'tcx, ListWithCachedTypeInfo<Clause<'tcx>>>,
projs: InternedSet<'tcx, List<ProjectionKind>>,
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
const_: InternedSet<'tcx, WithCachedTypeInfo<ConstData<'tcx>>>,
const_: InternedSet<'tcx, WithCachedTypeInfo<ty::ConstKind<'tcx>>>,
pat: InternedSet<'tcx, PatternKind<'tcx>>,
const_allocation: InternedSet<'tcx, Allocation>,
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
@ -338,18 +338,18 @@ impl<'tcx> CtxtInterners<'tcx> {
#[inline(never)]
fn intern_const(
&self,
data: ty::ConstData<'tcx>,
kind: ty::ConstKind<'tcx>,
sess: &Session,
untracked: &Untracked,
) -> Const<'tcx> {
Const(Interned::new_unchecked(
self.const_
.intern(data, |data: ConstData<'_>| {
let flags = super::flags::FlagComputation::for_const(&data.kind, data.ty);
let stable_hash = self.stable_hash(&flags, sess, untracked, &data);
.intern(kind, |kind: ty::ConstKind<'_>| {
let flags = super::flags::FlagComputation::for_const_kind(&kind);
let stable_hash = self.stable_hash(&flags, sess, untracked, &kind);
InternedInSet(self.arena.alloc(WithCachedTypeInfo {
internee: data,
internee: kind,
stable_hash,
flags: flags.flags,
outer_exclusive_binder: flags.outer_exclusive_binder,
@ -601,18 +601,15 @@ impl<'tcx> CommonConsts<'tcx> {
};
CommonConsts {
unit: mk_const(ty::ConstData {
kind: ty::ConstKind::Value(ty::ValTree::zst()),
ty: types.unit,
}),
true_: mk_const(ty::ConstData {
kind: ty::ConstKind::Value(ty::ValTree::Leaf(ty::ScalarInt::TRUE)),
ty: types.bool,
}),
false_: mk_const(ty::ConstData {
kind: ty::ConstKind::Value(ty::ValTree::Leaf(ty::ScalarInt::FALSE)),
ty: types.bool,
}),
unit: mk_const(ty::ConstKind::Value(types.unit, ty::ValTree::zst())),
true_: mk_const(ty::ConstKind::Value(
types.bool,
ty::ValTree::Leaf(ty::ScalarInt::TRUE),
)),
false_: mk_const(ty::ConstKind::Value(
types.bool,
ty::ValTree::Leaf(ty::ScalarInt::FALSE),
)),
}
}
}
@ -2225,9 +2222,9 @@ impl<'tcx> TyCtxt<'tcx> {
}
#[inline]
pub fn mk_ct_from_kind(self, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
pub fn mk_ct_from_kind(self, kind: ty::ConstKind<'tcx>) -> Const<'tcx> {
self.interners.intern_const(
ty::ConstData { kind, ty },
kind,
self.sess,
// This is only used to create a stable hashing context.
&self.untracked,
@ -2252,14 +2249,10 @@ impl<'tcx> TyCtxt<'tcx> {
ty::Region::new_early_param(self, param.to_early_bound_region_data()).into()
}
GenericParamDefKind::Type { .. } => Ty::new_param(self, param.index, param.name).into(),
GenericParamDefKind::Const { .. } => ty::Const::new_param(
self,
ParamConst { index: param.index, name: param.name },
self.type_of(param.def_id)
.no_bound_vars()
.expect("const parameter types cannot be generic"),
)
.into(),
GenericParamDefKind::Const { .. } => {
ty::Const::new_param(self, ParamConst { index: param.index, name: param.name })
.into()
}
}
}

View File

@ -337,7 +337,7 @@ impl DeepRejectCtxt {
| ty::ConstKind::Error(_) => {
return true;
}
ty::ConstKind::Value(impl_val) => impl_val,
ty::ConstKind::Value(_, impl_val) => impl_val,
ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => {
bug!("unexpected impl arg: {:?}", impl_ct)
}
@ -357,7 +357,7 @@ impl DeepRejectCtxt {
ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => {
true
}
ty::ConstKind::Value(obl_val) => obl_val == impl_val,
ty::ConstKind::Value(_, obl_val) => obl_val == impl_val,
ty::ConstKind::Infer(_) => true,

View File

@ -28,10 +28,9 @@ impl FlagComputation {
result
}
pub fn for_const(c: &ty::ConstKind<'_>, t: Ty<'_>) -> FlagComputation {
pub fn for_const_kind(kind: &ty::ConstKind<'_>) -> FlagComputation {
let mut result = FlagComputation::new();
result.add_const_kind(c);
result.add_ty(t);
result.add_const_kind(kind);
result
}
@ -373,7 +372,7 @@ impl FlagComputation {
self.add_flags(TypeFlags::HAS_CT_PLACEHOLDER);
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
}
ty::ConstKind::Value(_) => {}
ty::ConstKind::Value(ty, _) => self.add_ty(ty),
ty::ConstKind::Expr(e) => self.add_args(e.args()),
ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_ERROR),
}

View File

@ -134,13 +134,13 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
pub trait BoundVarReplacerDelegate<'tcx> {
fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx>;
fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx>;
fn replace_const(&mut self, bv: ty::BoundVar, ty: Ty<'tcx>) -> ty::Const<'tcx>;
fn replace_const(&mut self, bv: ty::BoundVar) -> ty::Const<'tcx>;
}
pub struct FnMutDelegate<'a, 'tcx> {
pub regions: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a),
pub types: &'a mut (dyn FnMut(ty::BoundTy) -> Ty<'tcx> + 'a),
pub consts: &'a mut (dyn FnMut(ty::BoundVar, Ty<'tcx>) -> ty::Const<'tcx> + 'a),
pub consts: &'a mut (dyn FnMut(ty::BoundVar) -> ty::Const<'tcx> + 'a),
}
impl<'a, 'tcx> BoundVarReplacerDelegate<'tcx> for FnMutDelegate<'a, 'tcx> {
@ -150,8 +150,8 @@ impl<'a, 'tcx> BoundVarReplacerDelegate<'tcx> for FnMutDelegate<'a, 'tcx> {
fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> {
(self.types)(bt)
}
fn replace_const(&mut self, bv: ty::BoundVar, ty: Ty<'tcx>) -> ty::Const<'tcx> {
(self.consts)(bv, ty)
fn replace_const(&mut self, bv: ty::BoundVar) -> ty::Const<'tcx> {
(self.consts)(bv)
}
}
@ -224,7 +224,7 @@ where
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
match ct.kind() {
ty::ConstKind::Bound(debruijn, bound_const) if debruijn == self.current_index => {
let ct = self.delegate.replace_const(bound_const, ct.ty());
let ct = self.delegate.replace_const(bound_const);
debug_assert!(!ct.has_vars_bound_above(ty::INNERMOST));
ty::fold::shift_vars(self.tcx, ct, self.current_index.as_u32())
}
@ -282,7 +282,7 @@ impl<'tcx> TyCtxt<'tcx> {
let delegate = FnMutDelegate {
regions: &mut replace_regions,
types: &mut |b| bug!("unexpected bound ty in binder: {b:?}"),
consts: &mut |b, ty| bug!("unexpected bound ct in binder: {b:?} {ty}"),
consts: &mut |b| bug!("unexpected bound ct in binder: {b:?}"),
};
let mut replacer = BoundVarReplacer::new(self, delegate);
value.fold_with(&mut replacer)
@ -353,9 +353,7 @@ impl<'tcx> TyCtxt<'tcx> {
ty::BoundTy { var: shift_bv(t.var), kind: t.kind },
)
},
consts: &mut |c, ty: Ty<'tcx>| {
ty::Const::new_bound(self, ty::INNERMOST, shift_bv(c), ty)
},
consts: &mut |c| ty::Const::new_bound(self, ty::INNERMOST, shift_bv(c)),
},
)
}
@ -398,12 +396,12 @@ impl<'tcx> TyCtxt<'tcx> {
.expect_ty();
Ty::new_bound(self.tcx, ty::INNERMOST, BoundTy { var, kind })
}
fn replace_const(&mut self, bv: ty::BoundVar, ty: Ty<'tcx>) -> ty::Const<'tcx> {
fn replace_const(&mut self, bv: ty::BoundVar) -> ty::Const<'tcx> {
let entry = self.map.entry(bv);
let index = entry.index();
let var = ty::BoundVar::from_usize(index);
let () = entry.or_insert_with(|| ty::BoundVariableKind::Const).expect_const();
ty::Const::new_bound(self.tcx, ty::INNERMOST, var, ty)
ty::Const::new_bound(self.tcx, ty::INNERMOST, var)
}
}

View File

@ -228,7 +228,7 @@ impl<'tcx> GenericArg<'tcx> {
ptr.cast::<WithCachedTypeInfo<ty::TyKind<'tcx>>>().as_ref(),
))),
CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked(
ptr.cast::<WithCachedTypeInfo<ty::ConstData<'tcx>>>().as_ref(),
ptr.cast::<WithCachedTypeInfo<ty::ConstKind<'tcx>>>().as_ref(),
))),
_ => intrinsics::unreachable(),
}
@ -454,11 +454,11 @@ impl<'tcx> GenericArgs<'tcx> {
def_id: DefId,
original_args: &[GenericArg<'tcx>],
) -> GenericArgsRef<'tcx> {
ty::GenericArgs::for_item(tcx, def_id, |def, args| {
ty::GenericArgs::for_item(tcx, def_id, |def, _| {
if let Some(arg) = original_args.get(def.index as usize) {
*arg
} else {
def.to_error(tcx, args)
def.to_error(tcx)
}
})
}

View File

@ -100,19 +100,11 @@ impl GenericParamDef {
}
}
pub fn to_error<'tcx>(
&self,
tcx: TyCtxt<'tcx>,
preceding_args: &[ty::GenericArg<'tcx>],
) -> ty::GenericArg<'tcx> {
pub fn to_error<'tcx>(&self, tcx: TyCtxt<'tcx>) -> ty::GenericArg<'tcx> {
match &self.kind {
ty::GenericParamDefKind::Lifetime => ty::Region::new_error_misc(tcx).into(),
ty::GenericParamDefKind::Type { .. } => Ty::new_misc_error(tcx).into(),
ty::GenericParamDefKind::Const { .. } => ty::Const::new_misc_error(
tcx,
tcx.type_of(self.def_id).instantiate(tcx, preceding_args),
)
.into(),
ty::GenericParamDefKind::Const { .. } => ty::Const::new_misc_error(tcx).into(),
}
}
}

View File

@ -385,9 +385,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
),
}
}
ty::Array(inner, len)
if len.ty() == tcx.types.usize && tcx.features().transmute_generic_consts =>
{
ty::Array(inner, len) if tcx.features().transmute_generic_consts => {
let len_eval = len.try_eval_target_usize(tcx, param_env);
if len_eval == Some(0) {
return Ok(SizeSkeleton::Known(Size::from_bytes(0)));

View File

@ -87,7 +87,7 @@ pub use self::closure::{
CAPTURE_STRUCT_LOCAL,
};
pub use self::consts::{
Const, ConstData, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree,
Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree,
};
pub use self::context::{
tls, CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift,
@ -617,7 +617,7 @@ impl<'tcx> Term<'tcx> {
ptr.cast::<WithCachedTypeInfo<ty::TyKind<'tcx>>>().as_ref(),
))),
CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked(
ptr.cast::<WithCachedTypeInfo<ty::ConstData<'tcx>>>().as_ref(),
ptr.cast::<WithCachedTypeInfo<ty::ConstKind<'tcx>>>().as_ref(),
))),
_ => core::intrinsics::unreachable(),
}
@ -934,6 +934,30 @@ pub struct Placeholder<T> {
pub universe: UniverseIndex,
pub bound: T,
}
impl Placeholder<BoundVar> {
pub fn find_const_ty_from_env<'tcx>(self, env: ParamEnv<'tcx>) -> Ty<'tcx> {
let mut candidates = env.caller_bounds().iter().filter_map(|clause| {
// `ConstArgHasType` are never desugared to be higher ranked.
match clause.kind().skip_binder() {
ty::ClauseKind::ConstArgHasType(placeholder_ct, ty) => {
assert!(!(placeholder_ct, ty).has_escaping_bound_vars());
match placeholder_ct.kind() {
ty::ConstKind::Placeholder(placeholder_ct) if placeholder_ct == self => {
Some(ty)
}
_ => None,
}
}
_ => None,
}
});
let ty = candidates.next().unwrap();
assert!(candidates.next().is_none());
ty
}
}
pub type PlaceholderRegion = Placeholder<BoundRegion>;

View File

@ -216,7 +216,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
})
.emit_unless(self.ignore_errors);
ty::Const::new_error(self.tcx, guar, ct.ty())
ty::Const::new_error(self.tcx, guar)
}
}
}

View File

@ -1459,23 +1459,6 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
return Ok(());
}
macro_rules! print_underscore {
() => {{
if print_ty {
self.typed_value(
|this| {
write!(this, "_")?;
Ok(())
},
|this| this.print_type(ct.ty()),
": ",
)?;
} else {
write!(self, "_")?;
}
}};
}
match ct.kind() {
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) => {
match self.tcx().def_kind(def) {
@ -1508,11 +1491,11 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
ty::InferConst::Var(ct_vid) if let Some(name) = self.const_infer_name(ct_vid) => {
p!(write("{}", name))
}
_ => print_underscore!(),
_ => write!(self, "_")?,
},
ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)),
ty::ConstKind::Value(value) => {
return self.pretty_print_const_valtree(value, ct.ty(), print_ty);
ty::ConstKind::Value(ty, value) => {
return self.pretty_print_const_valtree(value, ty, print_ty);
}
ty::ConstKind::Bound(debruijn, bound_var) => {
@ -1666,7 +1649,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
ty::Ref(_, inner, _) => {
if let ty::Array(elem, len) = inner.kind() {
if let ty::Uint(ty::UintTy::U8) = elem.kind() {
if let ty::ConstKind::Value(ty::ValTree::Leaf(int)) = len.kind() {
if let ty::ConstKind::Value(_, ty::ValTree::Leaf(int)) = len.kind() {
match self.tcx().try_get_global_alloc(prov.alloc_id()) {
Some(GlobalAlloc::Memory(alloc)) => {
let len = int.assert_bits(self.tcx().data_layout.pointer_size);

View File

@ -646,24 +646,25 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>(
true
}
(ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2,
(ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => a_val == b_val,
(ty::ConstKind::Value(_, a_val), ty::ConstKind::Value(_, b_val)) => a_val == b_val,
// While this is slightly incorrect, it shouldn't matter for `min_const_generics`
// and is the better alternative to waiting until `generic_const_exprs` can
// be stabilized.
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.def == bu.def => {
assert_eq!(a.ty(), b.ty());
if cfg!(debug_assertions) {
let a_ty = tcx.type_of(au.def).instantiate(tcx, au.args);
let b_ty = tcx.type_of(bu.def).instantiate(tcx, bu.args);
assert_eq!(a_ty, b_ty);
}
let args = relation.relate_with_variance(
ty::Variance::Invariant,
ty::VarianceDiagInfo::default(),
au.args,
bu.args,
)?;
return Ok(ty::Const::new_unevaluated(
tcx,
ty::UnevaluatedConst { def: au.def, args },
a.ty(),
));
return Ok(ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst { def: au.def, args }));
}
(ty::ConstKind::Expr(ae), ty::ConstKind::Expr(be)) => {
match (ae.kind, be.kind) {
@ -676,7 +677,7 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>(
}
let args = relation.relate(ae.args(), be.args())?;
return Ok(ty::Const::new_expr(tcx, ty::Expr::new(ae.kind, args), a.ty()));
return Ok(ty::Const::new_expr(tcx, ty::Expr::new(ae.kind, args)));
}
_ => false,
};

View File

@ -201,26 +201,21 @@ impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::Const<'tcx> {
f: &mut core::fmt::Formatter<'_>,
) -> core::fmt::Result {
// If this is a value, we spend some effort to make it look nice.
if let ConstKind::Value(_) = this.data.kind() {
if let ConstKind::Value(_, _) = this.data.kind() {
return ty::tls::with(move |tcx| {
// Somehow trying to lift the valtree results in lifetime errors, so we lift the
// entire constant.
let lifted = tcx.lift(*this.data).unwrap();
let ConstKind::Value(valtree) = lifted.kind() else {
let ConstKind::Value(ty, valtree) = lifted.kind() else {
bug!("we checked that this is a valtree")
};
let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
cx.pretty_print_const_valtree(valtree, lifted.ty(), /*print_ty*/ true)?;
cx.pretty_print_const_valtree(valtree, ty, /*print_ty*/ true)?;
f.write_str(&cx.into_buffer())
});
}
// Fall back to something verbose.
write!(
f,
"{kind:?}: {ty:?}",
ty = &this.map(|data| data.ty()),
kind = &this.map(|data| data.kind())
)
write!(f, "{kind:?}", kind = &this.map(|data| data.kind()))
}
}
@ -647,7 +642,6 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> {
self,
folder: &mut F,
) -> Result<Self, F::Error> {
let ty = self.ty().try_fold_with(folder)?;
let kind = match self.kind() {
ConstKind::Param(p) => ConstKind::Param(p.try_fold_with(folder)?),
ConstKind::Infer(i) => ConstKind::Infer(i.try_fold_with(folder)?),
@ -656,21 +650,18 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> {
}
ConstKind::Placeholder(p) => ConstKind::Placeholder(p.try_fold_with(folder)?),
ConstKind::Unevaluated(uv) => ConstKind::Unevaluated(uv.try_fold_with(folder)?),
ConstKind::Value(v) => ConstKind::Value(v.try_fold_with(folder)?),
ConstKind::Value(t, v) => {
ConstKind::Value(t.try_fold_with(folder)?, v.try_fold_with(folder)?)
}
ConstKind::Error(e) => ConstKind::Error(e.try_fold_with(folder)?),
ConstKind::Expr(e) => ConstKind::Expr(e.try_fold_with(folder)?),
};
if ty != self.ty() || kind != self.kind() {
Ok(folder.interner().mk_ct_from_kind(kind, ty))
} else {
Ok(self)
}
if kind != self.kind() { Ok(folder.interner().mk_ct_from_kind(kind)) } else { Ok(self) }
}
}
impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> {
fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
try_visit!(self.ty().visit_with(visitor));
match self.kind() {
ConstKind::Param(p) => p.visit_with(visitor),
ConstKind::Infer(i) => i.visit_with(visitor),
@ -680,7 +671,10 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> {
}
ConstKind::Placeholder(p) => p.visit_with(visitor),
ConstKind::Unevaluated(uv) => uv.visit_with(visitor),
ConstKind::Value(v) => v.visit_with(visitor),
ConstKind::Value(t, v) => {
try_visit!(t.visit_with(visitor));
v.visit_with(visitor)
}
ConstKind::Error(e) => e.visit_with(visitor),
ConstKind::Expr(e) => e.visit_with(visitor),
}

View File

@ -21,6 +21,7 @@ use rustc_span::symbol::{sym, Symbol};
use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
use rustc_target::spec::abi;
use rustc_type_ir::visit::TypeVisitableExt;
use std::assert_matches::debug_assert_matches;
use std::borrow::Cow;
use std::iter;
@ -339,6 +340,27 @@ impl ParamConst {
pub fn for_def(def: &ty::GenericParamDef) -> ParamConst {
ParamConst::new(def.index, def.name)
}
pub fn find_ty_from_env<'tcx>(self, env: ParamEnv<'tcx>) -> Ty<'tcx> {
let mut candidates = env.caller_bounds().iter().filter_map(|clause| {
// `ConstArgHasType` are never desugared to be higher ranked.
match clause.kind().skip_binder() {
ty::ClauseKind::ConstArgHasType(param_ct, ty) => {
assert!(!(param_ct, ty).has_escaping_bound_vars());
match param_ct.kind() {
ty::ConstKind::Param(param_ct) if param_ct.index == self.index => Some(ty),
_ => None,
}
}
_ => None,
}
});
let ty = candidates.next().unwrap();
assert!(candidates.next().is_none());
ty
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]

View File

@ -212,21 +212,19 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
}
},
GenericArgKind::Lifetime(_) => {}
GenericArgKind::Const(parent_ct) => {
stack.push(parent_ct.ty().into());
match parent_ct.kind() {
GenericArgKind::Const(parent_ct) => match parent_ct.kind() {
ty::ConstKind::Infer(_)
| ty::ConstKind::Param(_)
| ty::ConstKind::Placeholder(_)
| ty::ConstKind::Bound(..)
| ty::ConstKind::Value(_)
| ty::ConstKind::Error(_) => {}
ty::ConstKind::Value(ty, _) => stack.push(ty.into()),
ty::ConstKind::Expr(expr) => stack.extend(expr.args().iter().rev()),
ty::ConstKind::Unevaluated(ct) => {
stack.extend(ct.args.iter().rev());
}
}
}
},
}
}

View File

@ -7,7 +7,7 @@ use rustc_middle::mir::interpret::{Allocation, LitToConstError, LitToConstInput,
use rustc_middle::mir::*;
use rustc_middle::thir::*;
use rustc_middle::ty::{
self, CanonicalUserType, CanonicalUserTypeAnnotation, TyCtxt, UserTypeAnnotationIndex,
self, CanonicalUserType, CanonicalUserTypeAnnotation, Ty, TyCtxt, UserTypeAnnotationIndex,
};
use rustc_middle::{bug, span_bug};
use rustc_target::abi::Size;
@ -51,7 +51,7 @@ pub(crate) fn as_constant_inner<'tcx>(
{
Ok(c) => c,
Err(LitToConstError::Reported(guar)) => {
Const::Ty(ty::Const::new_error(tcx, guar, ty))
Const::Ty(Ty::new_error(tcx, guar), ty::Const::new_error(tcx, guar))
}
Err(LitToConstError::TypeError) => {
bug!("encountered type error in `lit_to_mir_constant`")
@ -83,8 +83,8 @@ pub(crate) fn as_constant_inner<'tcx>(
ConstOperand { user_ty, span, const_ }
}
ExprKind::ConstParam { param, def_id: _ } => {
let const_param = ty::Const::new_param(tcx, param, expr.ty);
let const_ = Const::Ty(const_param);
let const_param = ty::Const::new_param(tcx, param);
let const_ = Const::Ty(expr.ty, const_param);
ConstOperand { user_ty: None, span, const_ }
}

View File

@ -101,9 +101,9 @@ impl<'tcx> ConstToPat<'tcx> {
// level of indirection can be eliminated
let have_valtree =
matches!(cv, mir::Const::Ty(c) if matches!(c.kind(), ty::ConstKind::Value(_)));
matches!(cv, mir::Const::Ty(_, c) if matches!(c.kind(), ty::ConstKind::Value(_, _)));
let inlined_const_as_pat = match cv {
mir::Const::Ty(c) => match c.kind() {
mir::Const::Ty(_, c) => match c.kind() {
ty::ConstKind::Param(_)
| ty::ConstKind::Infer(_)
| ty::ConstKind::Bound(_, _)
@ -113,8 +113,8 @@ impl<'tcx> ConstToPat<'tcx> {
| ty::ConstKind::Expr(_) => {
span_bug!(self.span, "unexpected const in `to_pat`: {:?}", c.kind())
}
ty::ConstKind::Value(valtree) => {
self.recur(valtree, cv.ty()).unwrap_or_else(|_: FallbackToOpaqueConst| {
ty::ConstKind::Value(ty, valtree) => {
self.recur(valtree, ty).unwrap_or_else(|_: FallbackToOpaqueConst| {
Box::new(Pat {
span: self.span,
ty: cv.ty(),
@ -336,9 +336,9 @@ impl<'tcx> ConstToPat<'tcx> {
ty::Ref(_, pointee_ty, ..) => match *pointee_ty.kind() {
// `&str` is represented as a valtree, let's keep using this
// optimization for now.
ty::Str => {
PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) }
}
ty::Str => PatKind::Constant {
value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)),
},
// All other references are converted into deref patterns and then recursively
// convert the dereferenced constant to a pattern that is the sub-pattern of the
// deref pattern.
@ -382,13 +382,15 @@ impl<'tcx> ConstToPat<'tcx> {
self.saw_const_match_error.set(Some(e));
return Err(FallbackToOpaqueConst);
} else {
PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) }
PatKind::Constant {
value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)),
}
}
}
ty::Pat(..) | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => {
// The raw pointers we see here have been "vetted" by valtree construction to be
// just integers, so we simply allow them.
PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) }
PatKind::Constant { value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)) }
}
ty::FnPtr(..) => {
unreachable!(

View File

@ -580,7 +580,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
.tcx
.const_eval_global_id_for_typeck(param_env_reveal_all, cid, span)
.map(|val| match val {
Some(valtree) => mir::Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)),
Some(valtree) => mir::Const::Ty(ty, ty::Const::new_value(self.tcx, valtree, ty)),
None => mir::Const::Val(
self.tcx
.const_eval_global_id(param_env_reveal_all, cid, span)
@ -659,7 +659,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
};
if let Some(lit_input) = lit_input {
match tcx.at(expr.span).lit_to_const(lit_input) {
Ok(c) => return self.const_to_pat(Const::Ty(c), id, span).kind,
Ok(c) => return self.const_to_pat(Const::Ty(ty, c), id, span).kind,
// If an error occurred, ignore that it's a literal
// and leave reporting the error up to const eval of
// the unevaluated constant below.
@ -681,8 +681,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
// but something more principled, like a trait query checking whether this can be turned into a valtree.
if let Ok(Some(valtree)) = self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, span)
{
let subpattern =
self.const_to_pat(Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)), id, span);
let subpattern = self.const_to_pat(
Const::Ty(ty, ty::Const::new_value(self.tcx, valtree, ty)),
id,
span,
);
PatKind::InlineConstant { subpattern, def: def_id }
} else {
// If that fails, convert it to an opaque constant pattern.
@ -720,10 +723,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
_ => span_bug!(expr.span, "not a literal: {:?}", expr),
};
let lit_input =
LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg };
let ct_ty = self.typeck_results.expr_ty(expr);
let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg };
match self.tcx.at(expr.span).lit_to_const(lit_input) {
Ok(constant) => self.const_to_pat(Const::Ty(constant), expr.hir_id, lit.span).kind,
Ok(constant) => {
self.const_to_pat(Const::Ty(ct_ty, constant), expr.hir_id, lit.span).kind
}
Err(LitToConstError::Reported(e)) => PatKind::Error(e),
Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"),
}

View File

@ -203,7 +203,8 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
&& let operand_ty = operand.ty(self.local_decls, self.tcx)
&& let Some(operand_ty) = operand_ty.builtin_deref(true)
&& let ty::Array(_, len) = operand_ty.kind()
&& let Some(len) = Const::Ty(*len).try_eval_scalar_int(self.tcx, self.param_env)
&& let Some(len) = Const::Ty(self.tcx.types.usize, *len)
.try_eval_scalar_int(self.tcx, self.param_env)
{
state.insert_value_idx(target_len, FlatSet::Elem(len.into()), self.map());
}
@ -221,7 +222,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
Rvalue::Len(place) => {
let place_ty = place.ty(self.local_decls, self.tcx);
if let ty::Array(_, len) = place_ty.ty.kind() {
Const::Ty(*len)
Const::Ty(self.tcx.types.usize, *len)
.try_eval_scalar(self.tcx, self.param_env)
.map_or(FlatSet::Top, FlatSet::Elem)
} else if let [ProjectionElem::Deref] = place.projection[..] {

View File

@ -1118,7 +1118,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
// Trivial case: we are fetching a statically known length.
let place_ty = place.ty(self.local_decls, self.tcx).ty;
if let ty::Array(_, len) = place_ty.kind() {
return self.insert_constant(Const::from_ty_const(*len, self.tcx));
return self.insert_constant(Const::from_ty_const(
*len,
self.tcx.types.usize,
self.tcx,
));
}
let mut inner = self.simplify_place_value(place, location)?;
@ -1140,7 +1144,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
&& let Some(to) = to.builtin_deref(true)
&& let ty::Slice(..) = to.kind()
{
return self.insert_constant(Const::from_ty_const(*len, self.tcx));
return self.insert_constant(Const::from_ty_const(
*len,
self.tcx.types.usize,
self.tcx,
));
}
// Fallback: a symbolic `Len`.

View File

@ -150,7 +150,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
return;
}
let const_ = Const::from_ty_const(len, self.tcx);
let const_ = Const::from_ty_const(len, self.tcx.types.usize, self.tcx);
let constant = ConstOperand { span: source_info.span, const_, user_ty: None };
*rvalue = Rvalue::Use(Operand::Constant(Box::new(constant)));
}

View File

@ -95,7 +95,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
*rvalue = Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
span: rustc_span::DUMMY_SP,
user_ty: None,
const_: Const::from_ty_const(len, self.tcx),
const_: Const::from_ty_const(len, self.tcx.types.usize, self.tcx),
})));
}
self.super_rvalue(rvalue, loc);

View File

@ -263,7 +263,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
fn visit_constant(&mut self, ct: &mir::ConstOperand<'tcx>, location: Location) {
match ct.const_ {
mir::Const::Ty(c) => {
mir::Const::Ty(_, c) => {
c.visit_with(self);
}
mir::Const::Unevaluated(mir::UnevaluatedConst { def, args: _, promoted }, ty) => {

View File

@ -386,23 +386,15 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
}
fn fold_const(&mut self, c: I::Const) -> I::Const {
// We could canonicalize all consts with static types, but the only ones we
// *really* need to worry about are the ones that we end up putting into `CanonicalVarKind`
// since canonical vars can't reference other canonical vars.
let ty = c
.ty()
.fold_with(&mut RegionsToStatic { interner: self.interner(), binder: ty::INNERMOST });
let kind = match c.kind() {
ty::ConstKind::Infer(i) => match i {
ty::InferConst::Var(vid) => {
// We compare `kind`s here because we've folded the `ty` with `RegionsToStatic`
// so we'll get a mismatch in types if it actually changed any regions.
assert_eq!(
self.infcx.opportunistic_resolve_ct_var(vid, ty).kind(),
c.kind(),
"region vid should have been resolved fully before canonicalization"
self.infcx.opportunistic_resolve_ct_var(vid),
c,
"const vid should have been resolved fully before canonicalization"
);
CanonicalVarKind::Const(self.infcx.universe_of_ct(vid).unwrap(), ty)
CanonicalVarKind::Const(self.infcx.universe_of_ct(vid).unwrap())
}
ty::InferConst::EffectVar(_) => CanonicalVarKind::Effect,
ty::InferConst::Fresh(_) => todo!(),
@ -410,23 +402,21 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode {
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
PlaceholderLike::new(placeholder.universe(), self.variables.len().into()),
ty,
),
CanonicalizeMode::Response { .. } => {
CanonicalVarKind::PlaceholderConst(placeholder, ty)
CanonicalVarKind::PlaceholderConst(placeholder)
}
},
ty::ConstKind::Param(_) => match self.canonicalize_mode {
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
PlaceholderLike::new(ty::UniverseIndex::ROOT, self.variables.len().into()),
ty,
),
CanonicalizeMode::Response { .. } => panic!("param ty in response: {c:?}"),
},
// FIXME: See comment above -- we could fold the region separately or something.
ty::ConstKind::Bound(_, _)
| ty::ConstKind::Unevaluated(_)
| ty::ConstKind::Value(_)
| ty::ConstKind::Value(_, _)
| ty::ConstKind::Error(_)
| ty::ConstKind::Expr(_) => return c.super_fold_with(self),
};
@ -440,34 +430,6 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
}),
);
Const::new_anon_bound(self.interner(), self.binder_index, var, ty)
}
}
struct RegionsToStatic<I> {
interner: I,
binder: ty::DebruijnIndex,
}
impl<I: Interner> TypeFolder<I> for RegionsToStatic<I> {
fn interner(&self) -> I {
self.interner
}
fn fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T>
where
T: TypeFoldable<I>,
{
self.binder.shift_in(1);
let t = t.super_fold_with(self);
self.binder.shift_out(1);
t
}
fn fold_region(&mut self, r: I::Region) -> I::Region {
match r.kind() {
ty::ReBound(db, _) if self.binder > db => r,
_ => Region::new_static(self.interner()),
}
Const::new_anon_bound(self.interner(), self.binder_index, var)
}
}

View File

@ -58,8 +58,7 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I> for EagerRes
fn fold_const(&mut self, c: I::Const) -> I::Const {
match c.kind() {
ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
let ty = c.ty().fold_with(self);
let resolved = self.infcx.opportunistic_resolve_ct_var(vid, ty);
let resolved = self.infcx.opportunistic_resolve_ct_var(vid);
if c != resolved && resolved.has_infer() {
resolved.fold_with(self)
} else {
@ -67,9 +66,7 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I> for EagerRes
}
}
ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)) => {
let bool = Ty::new_bool(self.infcx.interner());
debug_assert_eq!(c.ty(), bool);
self.infcx.opportunistic_resolve_effect_var(vid, bool)
self.infcx.opportunistic_resolve_effect_var(vid)
}
_ => {
if c.has_infer() {

View File

@ -737,7 +737,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
// this). We show this to the user as `usize::MAX..` which is slightly incorrect but
// probably clear enough.
let c = ty.numeric_max_val(cx.tcx).unwrap();
let value = mir::Const::from_ty_const(c, cx.tcx);
let value = mir::Const::from_ty_const(c, ty.0, cx.tcx);
lo = PatRangeBoundary::Finite(value);
}
let hi = if let Some(hi) = range.hi.minus_one() {

View File

@ -68,6 +68,8 @@ fn compress<'tcx>(
fn encode_args<'tcx>(
tcx: TyCtxt<'tcx>,
args: GenericArgsRef<'tcx>,
for_def: DefId,
has_erased_self: bool,
dict: &mut FxHashMap<DictKey<'tcx>, usize>,
options: EncodeTyOptions,
) -> String {
@ -76,7 +78,8 @@ fn encode_args<'tcx>(
let args: Vec<GenericArg<'_>> = args.iter().collect();
if !args.is_empty() {
s.push('I');
for arg in args {
let def_generics = tcx.generics_of(for_def);
for (n, arg) in args.iter().enumerate() {
match arg.unpack() {
GenericArgKind::Lifetime(region) => {
s.push_str(&encode_region(region, dict));
@ -85,7 +88,10 @@ fn encode_args<'tcx>(
s.push_str(&encode_ty(tcx, ty, dict, options));
}
GenericArgKind::Const(c) => {
s.push_str(&encode_const(tcx, c, dict, options));
let n = n + (has_erased_self as usize);
let ct_ty =
tcx.type_of(def_generics.param_at(n, tcx).def_id).instantiate_identity();
s.push_str(&encode_const(tcx, c, ct_ty, dict, options));
}
}
}
@ -99,6 +105,7 @@ fn encode_args<'tcx>(
fn encode_const<'tcx>(
tcx: TyCtxt<'tcx>,
c: Const<'tcx>,
ct_ty: Ty<'tcx>,
dict: &mut FxHashMap<DictKey<'tcx>, usize>,
options: EncodeTyOptions,
) -> String {
@ -111,20 +118,20 @@ fn encode_const<'tcx>(
// L<element-type>E as literal argument
// Element type
s.push_str(&encode_ty(tcx, c.ty(), dict, options));
s.push_str(&encode_ty(tcx, ct_ty, dict, options));
}
// Literal arguments
ty::ConstKind::Value(..) => {
ty::ConstKind::Value(ct_ty, ..) => {
// L<element-type>[n]<element-value>E as literal argument
// Element type
s.push_str(&encode_ty(tcx, c.ty(), dict, options));
s.push_str(&encode_ty(tcx, ct_ty, dict, options));
// The only allowed types of const values are bool, u8, u16, u32,
// u64, u128, usize i8, i16, i32, i64, i128, isize, and char. The
// bool value false is encoded as 0 and true as 1.
match c.ty().kind() {
match ct_ty.kind() {
ty::Int(ity) => {
let bits = c.eval_bits(tcx, ty::ParamEnv::reveal_all());
let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
@ -142,7 +149,7 @@ fn encode_const<'tcx>(
let _ = write!(s, "{val}");
}
_ => {
bug!("encode_const: unexpected type `{:?}`", c.ty());
bug!("encode_const: unexpected type `{:?}`", ct_ty);
}
}
}
@ -231,15 +238,21 @@ fn encode_predicate<'tcx>(
ty::ExistentialPredicate::Trait(trait_ref) => {
let name = encode_ty_name(tcx, trait_ref.def_id);
let _ = write!(s, "u{}{}", name.len(), &name);
s.push_str(&encode_args(tcx, trait_ref.args, dict, options));
s.push_str(&encode_args(tcx, trait_ref.args, trait_ref.def_id, true, dict, options));
}
ty::ExistentialPredicate::Projection(projection) => {
let name = encode_ty_name(tcx, projection.def_id);
let _ = write!(s, "u{}{}", name.len(), &name);
s.push_str(&encode_args(tcx, projection.args, dict, options));
s.push_str(&encode_args(tcx, projection.args, projection.def_id, true, dict, options));
match projection.term.unpack() {
TermKind::Ty(ty) => s.push_str(&encode_ty(tcx, ty, dict, options)),
TermKind::Const(c) => s.push_str(&encode_const(tcx, c, dict, options)),
TermKind::Const(c) => s.push_str(&encode_const(
tcx,
c,
tcx.type_of(projection.def_id).instantiate(tcx, projection.args),
dict,
options,
)),
}
}
ty::ExistentialPredicate::AutoTrait(def_id) => {
@ -485,7 +498,7 @@ pub fn encode_ty<'tcx>(
// <subst>, as vendor extended type.
let name = encode_ty_name(tcx, def_id);
let _ = write!(s, "u{}{}", name.len(), &name);
s.push_str(&encode_args(tcx, args, dict, options));
s.push_str(&encode_args(tcx, args, def_id, false, dict, options));
compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
}
typeid.push_str(&s);
@ -529,7 +542,7 @@ pub fn encode_ty<'tcx>(
let mut s = String::new();
let name = encode_ty_name(tcx, *def_id);
let _ = write!(s, "u{}{}", name.len(), &name);
s.push_str(&encode_args(tcx, args, dict, options));
s.push_str(&encode_args(tcx, args, *def_id, false, dict, options));
compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
typeid.push_str(&s);
}
@ -541,7 +554,7 @@ pub fn encode_ty<'tcx>(
let name = encode_ty_name(tcx, *def_id);
let _ = write!(s, "u{}{}", name.len(), &name);
let parent_args = tcx.mk_args(args.as_coroutine_closure().parent_args());
s.push_str(&encode_args(tcx, parent_args, dict, options));
s.push_str(&encode_args(tcx, parent_args, *def_id, false, dict, options));
compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
typeid.push_str(&s);
}
@ -556,6 +569,8 @@ pub fn encode_ty<'tcx>(
s.push_str(&encode_args(
tcx,
tcx.mk_args(args.as_coroutine().parent_args()),
*def_id,
false,
dict,
options,
));

View File

@ -251,7 +251,9 @@ impl RustcInternal for MirConst {
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
let constant = tables.mir_consts[self.id];
match constant {
rustc_middle::mir::Const::Ty(ty) => rustc_middle::mir::Const::Ty(tcx.lift(ty).unwrap()),
rustc_middle::mir::Const::Ty(ty, ct) => {
rustc_middle::mir::Const::Ty(tcx.lift(ty).unwrap(), tcx.lift(ct).unwrap())
}
rustc_middle::mir::Const::Unevaluated(uneval, ty) => {
rustc_middle::mir::Const::Unevaluated(
tcx.lift(uneval).unwrap(),

View File

@ -398,7 +398,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
)));
}
Ok(mir::Const::Ty(ty::Const::zero_sized(tables.tcx, ty_internal)).stable(&mut *tables))
Ok(mir::Const::Ty(ty_internal, ty::Const::zero_sized(tables.tcx, ty_internal))
.stable(&mut *tables))
}
fn new_const_str(&self, value: &str) -> MirConst {

View File

@ -729,9 +729,9 @@ impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> {
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
let id = tables.intern_mir_const(tables.tcx.lift(*self).unwrap());
match *self {
mir::Const::Ty(c) => MirConst::new(
mir::Const::Ty(ty, c) => MirConst::new(
stable_mir::ty::ConstantKind::Ty(c.stable(tables)),
c.ty().stable(tables),
ty.stable(tables),
id,
),
mir::Const::Unevaluated(unev_const, ty) => {

View File

@ -415,7 +415,7 @@ pub fn mir_const_from_ty_const<'tcx>(
ty: Ty<'tcx>,
) -> stable_mir::ty::MirConst {
let kind = match ty_const.kind() {
ty::Value(val) => {
ty::Value(ty, val) => {
let val = match val {
ty::ValTree::Leaf(scalar) => ty::ValTree::Leaf(scalar),
ty::ValTree::Branch(branch) => {
@ -447,7 +447,7 @@ pub fn mir_const_from_ty_const<'tcx>(
ty::ExprCt(_) => unimplemented!(),
};
let stable_ty = tables.intern_ty(ty);
let id = tables.intern_mir_const(mir::Const::Ty(ty_const));
let id = tables.intern_mir_const(mir::Const::Ty(ty, ty_const));
stable_mir::ty::MirConst::new(kind, stable_ty, id)
}
@ -456,14 +456,15 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> {
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
let kind = match self.kind() {
ty::Value(val) => {
ty::Value(ty, val) => {
let val = match val {
ty::ValTree::Leaf(scalar) => ty::ValTree::Leaf(scalar),
ty::ValTree::Branch(branch) => {
ty::ValTree::Branch(tables.tcx.lift(branch).unwrap())
}
};
let ty = tables.tcx.lift(self.ty()).unwrap();
let ty = tables.tcx.lift(ty).unwrap();
let const_val = tables.tcx.valtree_to_const_val((ty, val));
if matches!(const_val, mir::ConstValue::ZeroSized) {
stable_mir::ty::TyConstKind::ZSTValue(ty.stable(tables))

View File

@ -270,15 +270,15 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> {
fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError> {
// only print integers
match (ct.kind(), ct.ty().kind()) {
(ty::ConstKind::Value(ty::ValTree::Leaf(scalar)), ty::Int(_) | ty::Uint(_)) => {
match ct.kind() {
ty::ConstKind::Value(ty, ty::ValTree::Leaf(scalar)) if ty.is_integral() => {
// The `pretty_print_const` formatting depends on -Zverbose-internals
// flag, so we cannot reuse it here.
let signed = matches!(ct.ty().kind(), ty::Int(_));
let signed = matches!(ty.kind(), ty::Int(_));
write!(
self,
"{:#?}",
ty::ConstInt::new(scalar, signed, ct.ty().is_ptr_sized_integral())
ty::ConstInt::new(scalar, signed, ty.is_ptr_sized_integral())
)?;
}
_ => self.write_str("_")?,

View File

@ -541,8 +541,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError> {
// We only mangle a typed value if the const can be evaluated.
let ct = ct.normalize(self.tcx, ty::ParamEnv::reveal_all());
match ct.kind() {
ty::ConstKind::Value(_) => {}
let (ct_ty, valtree) = match ct.kind() {
ty::ConstKind::Value(ty, val) => (ty, val),
// Placeholders (should be demangled as `_`).
// NOTE(eddyb) despite `Unevaluated` having a `DefId` (and therefore
@ -559,7 +559,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
self.push("p");
return Ok(());
}
}
};
if let Some(&i) = self.consts.get(&ct) {
self.print_backref(i)?;
@ -567,16 +567,15 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
}
let start = self.out.len();
let ty = ct.ty();
match ty.kind() {
match ct_ty.kind() {
ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => {
ty.print(self)?;
ct_ty.print(self)?;
let mut bits = ct.eval_bits(self.tcx, ty::ParamEnv::reveal_all());
// Negative integer values are mangled using `n` as a "sign prefix".
if let ty::Int(ity) = ty.kind() {
if let ty::Int(ity) = ct_ty.kind() {
let val =
Integer::from_int_ty(&self.tcx, *ity).size().sign_extend(bits) as i128;
if val < 0 {
@ -598,17 +597,16 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
match inner_ty.kind() {
ty::Str if mutbl.is_not() => {
match ct.kind() {
ty::ConstKind::Value(valtree) => {
let slice =
valtree.try_to_raw_bytes(self.tcx(), ty).unwrap_or_else(|| {
valtree.try_to_raw_bytes(self.tcx(), ct_ty).unwrap_or_else(|| {
bug!(
"expected to get raw bytes from valtree {:?} for type {:}",
valtree, ty
valtree,
ct_ty
)
});
let s = std::str::from_utf8(slice)
.expect("non utf8 str from MIR interpreter");
let s =
std::str::from_utf8(slice).expect("non utf8 str from MIR interpreter");
self.push("e");
@ -619,19 +617,12 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
self.push("_");
}
_ => {
bug!("symbol_names: unsupported `&str` constant: {:?}", ct);
}
}
}
_ => {
let pointee_ty = ct
.ty()
let pointee_ty = ct_ty
.builtin_deref(true)
.expect("tried to dereference on non-ptr type");
// FIXME(const_generics): add an assert that we only do this for valtrees.
let dereferenced_const = self.tcx.mk_ct_from_kind(ct.kind(), pointee_ty);
let dereferenced_const =
ty::Const::new_value(self.tcx, valtree, pointee_ty);
dereferenced_const.print(self)?;
}
}
@ -649,7 +640,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
Ok(())
};
match *ct.ty().kind() {
match *ct_ty.kind() {
ty::Array(..) | ty::Slice(_) => {
self.push("A");
print_field_list(self)?;
@ -698,7 +689,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
}
}
_ => {
bug!("symbol_names: unsupported constant of type `{}` ({:?})", ct.ty(), ct);
bug!("symbol_names: unsupported constant of type `{}` ({:?})", ct_ty, ct);
}
}

View File

@ -444,7 +444,7 @@ pub(in crate::solve) fn instantiate_canonical_state<'tcx, T: TypeFoldable<TyCtxt
infcx.next_region_var(RegionVariableOrigin::MiscVariable(span)).into()
}
ty::GenericArgKind::Type(_) => infcx.next_ty_var(span).into(),
ty::GenericArgKind::Const(ct) => infcx.next_const_var(ct.ty(), span).into(),
ty::GenericArgKind::Const(_) => infcx.next_const_var(span).into(),
};
orig_values.push(unconstrained);

View File

@ -609,8 +609,8 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
ty
}
pub(super) fn next_const_infer(&mut self, ty: Ty<'tcx>) -> ty::Const<'tcx> {
let ct = self.infcx.next_const_var(ty, DUMMY_SP);
pub(super) fn next_const_infer(&mut self) -> ty::Const<'tcx> {
let ct = self.infcx.next_const_var(DUMMY_SP);
self.inspect.add_var_value(ct);
ct
}
@ -620,7 +620,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
pub(super) fn next_term_infer_of_kind(&mut self, kind: ty::Term<'tcx>) -> ty::Term<'tcx> {
match kind.unpack() {
ty::TermKind::Ty(_) => self.next_ty_infer().into(),
ty::TermKind::Const(ct) => self.next_const_infer(ct.ty()).into(),
ty::TermKind::Const(_) => self.next_const_infer().into(),
}
}
@ -1037,14 +1037,19 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
&self,
param_env: ty::ParamEnv<'tcx>,
unevaluated: ty::UnevaluatedConst<'tcx>,
ty: Ty<'tcx>,
) -> Option<ty::Const<'tcx>> {
use rustc_middle::mir::interpret::ErrorHandled;
match self.infcx.const_eval_resolve(param_env, unevaluated, DUMMY_SP) {
Ok(Some(val)) => Some(ty::Const::new_value(self.interner(), val, ty)),
Ok(Some(val)) => Some(ty::Const::new_value(
self.interner(),
val,
self.interner()
.type_of(unevaluated.def)
.instantiate(self.interner(), unevaluated.args),
)),
Ok(None) | Err(ErrorHandled::TooGeneric(_)) => None,
Err(ErrorHandled::Reported(e, _)) => {
Some(ty::Const::new_error(self.interner(), e.into(), ty))
Some(ty::Const::new_error(self.interner(), e.into()))
}
}
}
@ -1124,7 +1129,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceAliasWithInfer<'_, '_, 'tcx> {
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
match ct.kind() {
ty::ConstKind::Unevaluated(..) if !ct.has_escaping_bound_vars() => {
let infer_ct = self.ecx.next_const_infer(ct.ty());
let infer_ct = self.ecx.next_const_infer();
let normalizes_to = ty::PredicateKind::AliasRelate(
ct.into(),
infer_ct.into(),

View File

@ -208,7 +208,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => {
let unconstrained_term = match term.unpack() {
ty::TermKind::Ty(_) => infcx.next_ty_var(span).into(),
ty::TermKind::Const(ct) => infcx.next_const_var(ct.ty(), span).into(),
ty::TermKind::Const(_) => infcx.next_const_var(span).into(),
};
let goal =
goal.with(infcx.tcx, ty::NormalizesTo { alias, term: unconstrained_term });

View File

@ -169,7 +169,7 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
// FIXME(generic_const_exprs): Implement handling for generic
// const expressions here.
if let Some(_normalized) = self.try_const_eval_resolve(param_env, uv, ct.ty()) {
if let Some(_normalized) = self.try_const_eval_resolve(param_env, uv) {
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
} else {
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
@ -178,7 +178,9 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
ty::ConstKind::Infer(_) => {
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
}
ty::ConstKind::Placeholder(_) | ty::ConstKind::Value(_) | ty::ConstKind::Error(_) => {
ty::ConstKind::Placeholder(_)
| ty::ConstKind::Value(_, _)
| ty::ConstKind::Error(_) => {
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
// We can freely ICE here as:
@ -198,30 +200,38 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
) -> QueryResult<'tcx> {
let (ct, ty) = goal.predicate;
// FIXME(BoxyUwU): Really we should not be calling `ct.ty()` for any variant
// other than `ConstKind::Value`. Unfortunately this would require looking in the
// env for any `ConstArgHasType` assumptions for parameters and placeholders. I
// have not yet gotten around to implementing this though.
//
// We do still stall on infer vars though as otherwise a goal like:
// `ConstArgHasType(?x: usize, usize)` can succeed even though it might later
// get unified with some const that is not of type `usize`.
match ct.kind() {
let ct_ty = match ct.kind() {
// FIXME: Ignore effect vars because canonicalization doesn't handle them correctly
// and if we stall on the var then we wind up creating ambiguity errors in a probe
// for this goal which contains an effect var. Which then ends up ICEing.
ty::ConstKind::Infer(ty::InferConst::Var(_)) => {
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
ty::ConstKind::Infer(ty::InferConst::EffectVar(_)) => {
return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
}
ty::ConstKind::Infer(_) => {
return self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
}
ty::ConstKind::Error(_) => {
return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
}
ty::ConstKind::Unevaluated(uv) => {
self.interner().type_of(uv.def).instantiate(self.interner(), uv.args)
}
ty::ConstKind::Expr(_) => unimplemented!(
"`feature(generic_const_exprs)` is not supported in the new trait solver"
),
ty::ConstKind::Param(_) => {
unreachable!("`ConstKind::Param` should have been canonicalized to `Placeholder`")
}
ty::ConstKind::Bound(_, _) => bug!("escaping bound vars in {:?}", ct),
ty::ConstKind::Value(ty, _) => ty,
ty::ConstKind::Placeholder(placeholder) => {
placeholder.find_const_ty_from_env(goal.param_env)
}
};
self.eq(goal.param_env, ct_ty, ty)?;
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
_ => {
self.eq(goal.param_env, ct.ty(), ty)?;
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
}
}
}
impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {

View File

@ -109,7 +109,6 @@ where
fn normalize_unevaluated_const(
&mut self,
ty: Ty<'tcx>,
uv: ty::UnevaluatedConst<'tcx>,
) -> Result<ty::Const<'tcx>, Vec<E>> {
let infcx = self.at.infcx;
@ -126,7 +125,7 @@ where
self.depth += 1;
let new_infer_ct = infcx.next_const_var(ty, self.at.cause.span);
let new_infer_ct = infcx.next_const_var(self.at.cause.span);
let obligation = Obligation::new(
tcx,
self.at.cause.clone(),
@ -143,7 +142,7 @@ where
let ct = infcx.resolve_vars_if_possible(new_infer_ct);
ct.try_fold_with(self)?
} else {
ty::Const::new_unevaluated(tcx, uv, ty).try_super_fold_with(self)?
ty::Const::new_unevaluated(tcx, uv).try_super_fold_with(self)?
};
self.depth -= 1;
@ -214,7 +213,7 @@ where
if uv.has_escaping_bound_vars() {
let (uv, mapped_regions, mapped_types, mapped_consts) =
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, uv);
let result = ensure_sufficient_stack(|| self.normalize_unevaluated_const(ct.ty(), uv))?;
let result = ensure_sufficient_stack(|| self.normalize_unevaluated_const(uv))?;
Ok(PlaceholderReplacer::replace_placeholders(
infcx,
mapped_regions,
@ -224,7 +223,7 @@ where
result,
))
} else {
ensure_sufficient_stack(|| self.normalize_unevaluated_const(ct.ty(), uv))
ensure_sufficient_stack(|| self.normalize_unevaluated_const(uv))
}
}
}

View File

@ -12,10 +12,6 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
if let Some(normalized_const) = self.try_const_eval_resolve(
goal.param_env,
ty::UnevaluatedConst::new(goal.predicate.alias.def_id, goal.predicate.alias.args),
self.interner()
.type_of(goal.predicate.alias.def_id)
.no_bound_vars()
.expect("const ty should not rely on other generics"),
) {
self.instantiate_normalizes_to_term(goal, normalized_const.into());
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)

View File

@ -201,13 +201,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
let error_response = |ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>, reason| {
let guar = tcx.dcx().span_delayed_bug(tcx.def_span(assoc_def.item.def_id), reason);
let error_term = match assoc_def.item.kind {
ty::AssocKind::Const => ty::Const::new_error(
tcx,
guar,
tcx.type_of(goal.predicate.def_id())
.instantiate(tcx, goal.predicate.alias.args),
)
.into(),
ty::AssocKind::Const => ty::Const::new_error(tcx, guar).into(),
ty::AssocKind::Type => Ty::new_error(tcx, guar).into(),
// This makes no sense...
ty::AssocKind::Fn => span_bug!(
@ -253,7 +247,6 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
ty::EarlyBinder::bind(
ty::Const::new_error_with_message(
tcx,
tcx.type_of(assoc_def.item.def_id).instantiate_identity(),
DUMMY_SP,
"associated const projection is not supported yet",
)

View File

@ -765,7 +765,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
unevaluated,
obligation.cause.span,
) {
Ok(Some(valtree)) => Ok(ty::Const::new_value(selcx.tcx(),valtree, c.ty())),
Ok(Some(valtree)) => Ok(ty::Const::new_value(selcx.tcx(),valtree, self.tcx.type_of(unevaluated.def).instantiate(self.tcx, unevaluated.args))),
Ok(None) => {
let tcx = self.tcx;
let reported =

View File

@ -529,7 +529,6 @@ fn plug_infer_with_placeholders<'tcx>(
ty::Const::new_placeholder(
self.infcx.tcx,
ty::Placeholder { universe: self.universe, bound: self.next_var() },
ct.ty(),
),
)
else {

View File

@ -34,7 +34,7 @@ pub fn is_const_evaluatable<'tcx>(
ty::ConstKind::Param(_)
| ty::ConstKind::Bound(_, _)
| ty::ConstKind::Placeholder(_)
| ty::ConstKind::Value(_)
| ty::ConstKind::Value(_, _)
| ty::ConstKind::Error(_) => return Ok(()),
ty::ConstKind::Infer(_) => return Err(NotConstEvaluatable::MentionsInfer),
};
@ -173,8 +173,7 @@ fn satisfied_from_param_env<'tcx>(
debug!("is_const_evaluatable: candidate={:?}", c);
if self.infcx.probe(|_| {
let ocx = ObligationCtxt::new(self.infcx);
ocx.eq(&ObligationCause::dummy(), self.param_env, c.ty(), self.ct.ty()).is_ok()
&& ocx.eq(&ObligationCause::dummy(), self.param_env, c, self.ct).is_ok()
ocx.eq(&ObligationCause::dummy(), self.param_env, c, self.ct).is_ok()
&& ocx.select_all_or_error().is_empty()
}) {
self.single_match = match self.single_match {
@ -215,7 +214,6 @@ fn satisfied_from_param_env<'tcx>(
if let Some(Ok(c)) = single_match {
let ocx = ObligationCtxt::new(infcx);
assert!(ocx.eq(&ObligationCause::dummy(), param_env, c.ty(), ct.ty()).is_ok());
assert!(ocx.eq(&ObligationCause::dummy(), param_env, c, ct).is_ok());
assert!(ocx.select_all_or_error().is_empty());
return true;

View File

@ -876,56 +876,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
}
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) => {
// Errors for `ConstEvaluatable` predicates show up as
// `SelectionError::ConstEvalFailure`,
// not `Unimplemented`.
span_bug!(
span,
"const-evaluatable requirement gave wrong error: `{:?}`",
obligation
)
}
ty::PredicateKind::ConstEquate(..) => {
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
// Errors for `ConstEquate` predicates show up as
// `SelectionError::ConstEvalFailure`,
// not `Unimplemented`.
| ty::PredicateKind::ConstEquate { .. }
// Ambiguous predicates should never error
| ty::PredicateKind::Ambiguous
| ty::PredicateKind::NormalizesTo { .. }
| ty::PredicateKind::AliasRelate { .. }
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType { .. }) => {
span_bug!(
span,
"const-equate requirement gave wrong error: `{:?}`",
"Unexpected `Predicate` for `SelectionError`: `{:?}`",
obligation
)
}
ty::PredicateKind::Ambiguous => span_bug!(span, "ambiguous"),
ty::PredicateKind::NormalizesTo(..) => span_bug!(
span,
"NormalizesTo predicate should never be the predicate cause of a SelectionError"
),
ty::PredicateKind::AliasRelate(..) => span_bug!(
span,
"AliasRelate predicate should never be the predicate cause of a SelectionError"
),
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
let mut diag = self.dcx().struct_span_err(
span,
format!("the constant `{ct}` is not of type `{ty}`"),
);
self.note_type_err(
&mut diag,
&obligation.cause,
None,
None,
TypeError::Sorts(ty::error::ExpectedFound::new(true, ty, ct.ty())),
false,
false,
);
diag
}
}
}
@ -988,6 +957,24 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
Overflow(_) => {
bug!("overflow should be handled before the `report_selection_error` path");
}
SelectionError::ConstArgHasWrongType { ct, ct_ty, expected_ty } => {
let mut diag = self.dcx().struct_span_err(
span,
format!("the constant `{ct}` is not of type `{expected_ty}`"),
);
self.note_type_err(
&mut diag,
&obligation.cause,
None,
None,
TypeError::Sorts(ty::error::ExpectedFound::new(true, expected_ty, ct_ty)),
false,
false,
);
diag
}
};
self.note_obligation_cause(&mut err, &obligation);

View File

@ -439,39 +439,52 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
// This is because this is not ever a useful obligation to report
// as the cause of an overflow.
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
// FIXME(BoxyUwU): Really we should not be calling `ct.ty()` for any variant
// other than `ConstKind::Value`. Unfortunately this would require looking in the
// env for any `ConstArgHasType` assumptions for parameters and placeholders. I
// don't really want to implement this in the old solver so I haven't.
//
// We do still stall on infer vars though as otherwise a goal like:
// `ConstArgHasType(?x: usize, usize)` can succeed even though it might later
// get unified with some const that is not of type `usize`.
let ct = self.selcx.infcx.shallow_resolve_const(ct);
match ct.kind() {
ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
let ct = infcx.shallow_resolve_const(ct);
let ct_ty = match ct.kind() {
ty::ConstKind::Infer(var) => {
let var = match var {
ty::InferConst::Var(vid) => TyOrConstInferVar::Const(vid),
ty::InferConst::EffectVar(vid) => TyOrConstInferVar::Effect(vid),
ty::InferConst::Fresh(_) => {
bug!("encountered fresh const in fulfill")
}
};
pending_obligation.stalled_on.clear();
pending_obligation.stalled_on.extend([TyOrConstInferVar::Const(vid)]);
ProcessResult::Unchanged
pending_obligation.stalled_on.extend([var]);
return ProcessResult::Unchanged;
}
ty::ConstKind::Error(_) => return ProcessResult::Changed(vec![]),
_ => {
match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq(
ty::ConstKind::Value(ty, _) => ty,
ty::ConstKind::Unevaluated(uv) => {
infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args)
}
// FIXME(generic_const_exprs): we should construct an alias like
// `<lhs_ty as Add<rhs_ty>>::Output` when this is an `Expr` representing
// `lhs + rhs`.
ty::ConstKind::Expr(_) => {
return ProcessResult::Changed(mk_pending(vec![]));
}
ty::ConstKind::Placeholder(_) => {
bug!("placeholder const {:?} in old solver", ct)
}
ty::ConstKind::Bound(_, _) => bug!("escaping bound vars in {:?}", ct),
ty::ConstKind::Param(param_ct) => {
param_ct.find_ty_from_env(obligation.param_env)
}
};
match infcx.at(&obligation.cause, obligation.param_env).eq(
// Only really excercised by generic_const_exprs
DefineOpaqueTypes::Yes,
ct.ty(),
ct_ty,
ty,
) {
Ok(inf_ok) => {
ProcessResult::Changed(mk_pending(inf_ok.into_obligations()))
}
Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())),
Err(_) => ProcessResult::Error(FulfillmentErrorCode::Select(
SelectionError::Unimplemented,
SelectionError::ConstArgHasWrongType { ct, ct_ty, expected_ty: ty },
)),
}
}
}
}
// General case overflow check. Allow `process_trait_obligation`
// and `process_projection_obligation` to handle checking for
@ -633,7 +646,6 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
match self.selcx.infcx.try_const_eval_resolve(
obligation.param_env,
unevaluated,
c.ty(),
obligation.cause.span,
) {
Ok(val) => Ok(val),

View File

@ -359,7 +359,7 @@ pub fn normalize_param_env_or_error<'tcx>(
// `ty::Const::normalize` can only work with properly preserved binders.
if c.has_escaping_bound_vars() {
return ty::Const::new_misc_error(self.0, c.ty());
return ty::Const::new_misc_error(self.0);
}
// While it is pretty sus to be evaluating things with an empty param env, it
// should actually be okay since without `feature(generic_const_exprs)` the only

View File

@ -523,16 +523,9 @@ fn normalize_to_error<'a, 'tcx>(
| ty::AliasTermKind::InherentTy
| ty::AliasTermKind::OpaqueTy
| ty::AliasTermKind::WeakTy => selcx.infcx.next_ty_var(cause.span).into(),
ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => selcx
.infcx
.next_const_var(
selcx
.tcx()
.type_of(projection_term.def_id)
.instantiate(selcx.tcx(), projection_term.args),
cause.span,
)
.into(),
ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => {
selcx.infcx.next_const_var(cause.span).into()
}
};
let trait_obligation = Obligation {
cause,
@ -744,8 +737,6 @@ fn project<'cx, 'tcx>(
obligation.predicate.def_id,
obligation.predicate.args,
),
tcx.type_of(obligation.predicate.def_id)
.instantiate(tcx, obligation.predicate.args),
)
.into(),
kind => {
@ -2071,15 +2062,14 @@ fn confirm_impl_candidate<'cx, 'tcx>(
// * `args` ends up as `[u32, S]`
let args = obligation.predicate.args.rebase_onto(tcx, trait_def_id, args);
let args = translate_args(selcx.infcx, param_env, impl_def_id, args, assoc_ty.defining_node);
let ty = tcx.type_of(assoc_ty.item.def_id);
let is_const = matches!(tcx.def_kind(assoc_ty.item.def_id), DefKind::AssocConst);
let term: ty::EarlyBinder<'tcx, ty::Term<'tcx>> = if is_const {
let did = assoc_ty.item.def_id;
let identity_args = crate::traits::GenericArgs::identity_for_item(tcx, did);
let uv = ty::UnevaluatedConst::new(did, identity_args);
ty.map_bound(|ty| ty::Const::new_unevaluated(tcx, uv, ty).into())
ty::EarlyBinder::bind(ty::Const::new_unevaluated(tcx, uv).into())
} else {
ty.map_bound(|ty| ty.into())
tcx.type_of(assoc_ty.item.def_id).map_bound(|ty| ty.into())
};
if !tcx.check_args_compatible(assoc_ty.item.def_id, args) {
let err = Ty::new_error_with_message(

View File

@ -665,9 +665,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, '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()
}

View File

@ -947,7 +947,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
match self.infcx.try_const_eval_resolve(
obligation.param_env,
unevaluated,
c.ty(),
obligation.cause.span,
) {
Ok(val) => Ok(val),
@ -995,21 +994,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig),
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
// FIXME(BoxyUwU): Really we should not be calling `ct.ty()` for any variant
// other than `ConstKind::Value`. Unfortunately this would require looking in the
// env for any `ConstArgHasType` assumptions for parameters and placeholders. I
// don't really want to implement this in the old solver so I haven't.
//
// We do still stall on infer vars though as otherwise a goal like:
// `ConstArgHasType(?x: usize, usize)` can succeed even though it might later
// get unified with some const that is not of type `usize`.
let ct = self.infcx.shallow_resolve_const(ct);
let ct_ty = match ct.kind() {
ty::ConstKind::Infer(ty::InferConst::Var(_)) => {
ty::ConstKind::Infer(_) => {
return Ok(EvaluatedToAmbig);
}
ty::ConstKind::Error(_) => return Ok(EvaluatedToOk),
_ => ct.ty(),
ty::ConstKind::Value(ty, _) => ty,
ty::ConstKind::Unevaluated(uv) => {
self.tcx().type_of(uv.def).instantiate(self.tcx(), uv.args)
}
// FIXME(generic_const_exprs): See comment in `fulfill.rs`
ty::ConstKind::Expr(_) => return Ok(EvaluatedToOk),
ty::ConstKind::Placeholder(_) => {
bug!("placeholder const {:?} in old solver", ct)
}
ty::ConstKind::Bound(_, _) => bug!("escaping bound vars in {:?}", ct),
ty::ConstKind::Param(param_ct) => {
param_ct.find_ty_from_env(obligation.param_env)
}
};
match self.infcx.at(&obligation.cause, obligation.param_env).eq(

View File

@ -483,7 +483,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> {
let universe = self.universe_for(debruijn);
let p = ty::PlaceholderConst { universe, bound: bound_const };
self.mapped_consts.insert(p, bound_const);
ty::Const::new_placeholder(self.infcx.tcx, p, ct.ty())
ty::Const::new_placeholder(self.infcx.tcx, p)
}
_ => ct.super_fold_with(self),
}
@ -626,7 +626,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
let db = ty::DebruijnIndex::from_usize(
self.universe_indices.len() - index + self.current_index.as_usize() - 1,
);
ty::Const::new_bound(self.infcx.tcx, db, *replace_var, ct.ty())
ty::Const::new_bound(self.infcx.tcx, db, *replace_var)
}
None => {
if ct.has_infer() {

View File

@ -135,7 +135,7 @@ mod rustc {
use rustc_middle::ty::ScalarInt;
use rustc_span::symbol::sym;
let Ok(cv) = c.eval(tcx, param_env, DUMMY_SP) else {
let Ok((ty, cv)) = c.eval(tcx, param_env, DUMMY_SP) else {
return Some(Self {
alignment: true,
lifetimes: true,
@ -144,7 +144,7 @@ mod rustc {
});
};
let adt_def = c.ty().ty_adt_def()?;
let adt_def = ty.ty_adt_def()?;
assert_eq!(
tcx.require_lang_item(LangItem::TransmuteOpts, None),

View File

@ -23,7 +23,7 @@ fn destructure_const<'tcx>(
tcx: TyCtxt<'tcx>,
const_: ty::Const<'tcx>,
) -> ty::DestructuredConst<'tcx> {
let ty::ConstKind::Value(valtree) = const_.kind() else {
let ty::ConstKind::Value(ct_ty, valtree) = const_.kind() else {
bug!("cannot destructure constant {:?}", const_)
};
@ -32,7 +32,7 @@ fn destructure_const<'tcx>(
_ => bug!("cannot destructure constant {:?}", const_),
};
let (fields, variant) = match const_.ty().kind() {
let (fields, variant) = match ct_ty.kind() {
ty::Array(inner_ty, _) | ty::Slice(inner_ty) => {
// construct the consts for the elements of the array/slice
let field_consts = branches
@ -121,7 +121,7 @@ fn recurse_build<'tcx>(
let sp = node.span;
match tcx.at(sp).lit_to_const(LitToConstInput { lit: &lit.node, ty: node.ty, neg }) {
Ok(c) => c,
Err(LitToConstError::Reported(guar)) => ty::Const::new_error(tcx, guar, node.ty),
Err(LitToConstError::Reported(guar)) => ty::Const::new_error(tcx, guar),
Err(LitToConstError::TypeError) => {
bug!("encountered type error in lit_to_const")
}
@ -137,35 +137,31 @@ fn recurse_build<'tcx>(
}
&ExprKind::NamedConst { def_id, args, user_ty: _ } => {
let uneval = ty::UnevaluatedConst::new(def_id, args);
ty::Const::new_unevaluated(tcx, uneval, node.ty)
ty::Const::new_unevaluated(tcx, uneval)
}
ExprKind::ConstParam { param, .. } => ty::Const::new_param(tcx, *param, node.ty),
ExprKind::ConstParam { param, .. } => ty::Const::new_param(tcx, *param),
ExprKind::Call { fun, args, .. } => {
let fun_ty = body.exprs[*fun].ty;
let fun = recurse_build(tcx, body, *fun, root_span)?;
let mut new_args = Vec::<ty::Const<'tcx>>::with_capacity(args.len());
for &id in args.iter() {
new_args.push(recurse_build(tcx, body, id, root_span)?);
}
ty::Const::new_expr(
tcx,
Expr::new_call(tcx, fun.ty(), fun, new_args.into_iter()),
node.ty,
)
ty::Const::new_expr(tcx, Expr::new_call(tcx, fun_ty, fun, new_args))
}
&ExprKind::Binary { op, lhs, rhs } if check_binop(op) => {
let lhs_ty = body.exprs[lhs].ty;
let lhs = recurse_build(tcx, body, lhs, root_span)?;
let rhs_ty = body.exprs[rhs].ty;
let rhs = recurse_build(tcx, body, rhs, root_span)?;
ty::Const::new_expr(
tcx,
Expr::new_binop(tcx, op, lhs.ty(), rhs.ty(), lhs, rhs),
node.ty,
)
ty::Const::new_expr(tcx, Expr::new_binop(tcx, op, lhs_ty, rhs_ty, lhs, rhs))
}
&ExprKind::Unary { op, arg } if check_unop(op) => {
let arg_ty = body.exprs[arg].ty;
let arg = recurse_build(tcx, body, arg, root_span)?;
ty::Const::new_expr(tcx, Expr::new_unop(tcx, op, arg.ty(), arg), node.ty)
ty::Const::new_expr(tcx, Expr::new_unop(tcx, op, arg_ty, arg))
}
// This is necessary so that the following compiles:
//
@ -187,20 +183,12 @@ fn recurse_build<'tcx>(
&ExprKind::Use { source } => {
let value_ty = body.exprs[source].ty;
let value = recurse_build(tcx, body, source, root_span)?;
ty::Const::new_expr(
tcx,
Expr::new_cast(tcx, CastKind::Use, value_ty, value, node.ty),
node.ty,
)
ty::Const::new_expr(tcx, Expr::new_cast(tcx, CastKind::Use, value_ty, value, node.ty))
}
&ExprKind::Cast { source } => {
let value_ty = body.exprs[source].ty;
let value = recurse_build(tcx, body, source, root_span)?;
ty::Const::new_expr(
tcx,
Expr::new_cast(tcx, CastKind::As, value_ty, value, node.ty),
node.ty,
)
ty::Const::new_expr(tcx, Expr::new_cast(tcx, CastKind::As, value_ty, value, node.ty))
}
ExprKind::Borrow { arg, .. } => {
let arg_node = &body.exprs[*arg];

View File

@ -115,8 +115,8 @@ impl<I: Interner> CanonicalVarInfo<I> {
CanonicalVarKind::PlaceholderTy(_) => false,
CanonicalVarKind::Region(_) => true,
CanonicalVarKind::PlaceholderRegion(..) => false,
CanonicalVarKind::Const(..) => true,
CanonicalVarKind::PlaceholderConst(_, _) => false,
CanonicalVarKind::Const(_) => true,
CanonicalVarKind::PlaceholderConst(_) => false,
CanonicalVarKind::Effect => true,
}
}
@ -126,8 +126,8 @@ impl<I: Interner> CanonicalVarInfo<I> {
CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => true,
CanonicalVarKind::Ty(_)
| CanonicalVarKind::PlaceholderTy(_)
| CanonicalVarKind::Const(_, _)
| CanonicalVarKind::PlaceholderConst(_, _)
| CanonicalVarKind::Const(_)
| CanonicalVarKind::PlaceholderConst(_)
| CanonicalVarKind::Effect => false,
}
}
@ -136,12 +136,12 @@ impl<I: Interner> CanonicalVarInfo<I> {
match self.kind {
CanonicalVarKind::Ty(_)
| CanonicalVarKind::Region(_)
| CanonicalVarKind::Const(_, _)
| CanonicalVarKind::Const(_)
| CanonicalVarKind::Effect => panic!("expected placeholder: {self:?}"),
CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.var().as_usize(),
CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.var().as_usize(),
CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.var().as_usize(),
CanonicalVarKind::PlaceholderConst(placeholder) => placeholder.var().as_usize(),
}
}
}
@ -169,13 +169,13 @@ pub enum CanonicalVarKind<I: Interner> {
PlaceholderRegion(I::PlaceholderRegion),
/// Some kind of const inference variable.
Const(UniverseIndex, I::Ty),
Const(UniverseIndex),
/// Effect variable `'?E`.
Effect,
/// A "placeholder" that represents "any const".
PlaceholderConst(I::PlaceholderConst, I::Ty),
PlaceholderConst(I::PlaceholderConst),
}
impl<I: Interner> PartialEq for CanonicalVarKind<I> {
@ -185,10 +185,8 @@ impl<I: Interner> PartialEq for CanonicalVarKind<I> {
(Self::PlaceholderTy(l0), Self::PlaceholderTy(r0)) => l0 == r0,
(Self::Region(l0), Self::Region(r0)) => l0 == r0,
(Self::PlaceholderRegion(l0), Self::PlaceholderRegion(r0)) => l0 == r0,
(Self::Const(l0, l1), Self::Const(r0, r1)) => l0 == r0 && l1 == r1,
(Self::PlaceholderConst(l0, l1), Self::PlaceholderConst(r0, r1)) => {
l0 == r0 && l1 == r1
}
(Self::Const(l0), Self::Const(r0)) => l0 == r0,
(Self::PlaceholderConst(l0), Self::PlaceholderConst(r0)) => l0 == r0,
_ => std::mem::discriminant(self) == std::mem::discriminant(other),
}
}
@ -199,10 +197,10 @@ impl<I: Interner> CanonicalVarKind<I> {
match self {
CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) => ui,
CanonicalVarKind::Region(ui) => ui,
CanonicalVarKind::Const(ui, _) => ui,
CanonicalVarKind::Const(ui) => ui,
CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe(),
CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe(),
CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.universe(),
CanonicalVarKind::PlaceholderConst(placeholder) => placeholder.universe(),
CanonicalVarKind::Ty(CanonicalTyVarKind::Float | CanonicalTyVarKind::Int) => {
UniverseIndex::ROOT
}
@ -220,7 +218,7 @@ impl<I: Interner> CanonicalVarKind<I> {
CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
}
CanonicalVarKind::Region(_) => CanonicalVarKind::Region(ui),
CanonicalVarKind::Const(_, ty) => CanonicalVarKind::Const(ui, ty),
CanonicalVarKind::Const(_) => CanonicalVarKind::Const(ui),
CanonicalVarKind::PlaceholderTy(placeholder) => {
CanonicalVarKind::PlaceholderTy(placeholder.with_updated_universe(ui))
@ -228,8 +226,8 @@ impl<I: Interner> CanonicalVarKind<I> {
CanonicalVarKind::PlaceholderRegion(placeholder) => {
CanonicalVarKind::PlaceholderRegion(placeholder.with_updated_universe(ui))
}
CanonicalVarKind::PlaceholderConst(placeholder, ty) => {
CanonicalVarKind::PlaceholderConst(placeholder.with_updated_universe(ui), ty)
CanonicalVarKind::PlaceholderConst(placeholder) => {
CanonicalVarKind::PlaceholderConst(placeholder.with_updated_universe(ui))
}
CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float)
| CanonicalVarKind::Effect => {
@ -345,21 +343,14 @@ impl<I: Interner> CanonicalVarValues<I> {
Region::new_anon_bound(tcx, ty::INNERMOST, ty::BoundVar::from_usize(i))
.into()
}
CanonicalVarKind::Effect => Const::new_anon_bound(
tcx,
ty::INNERMOST,
ty::BoundVar::from_usize(i),
Ty::new_bool(tcx),
)
.into(),
CanonicalVarKind::Const(_, ty)
| CanonicalVarKind::PlaceholderConst(_, ty) => Const::new_anon_bound(
tcx,
ty::INNERMOST,
ty::BoundVar::from_usize(i),
ty,
)
.into(),
CanonicalVarKind::Effect => {
Const::new_anon_bound(tcx, ty::INNERMOST, ty::BoundVar::from_usize(i))
.into()
}
CanonicalVarKind::Const(_) | CanonicalVarKind::PlaceholderConst(_) => {
Const::new_anon_bound(tcx, ty::INNERMOST, ty::BoundVar::from_usize(i))
.into()
}
}
},
)),

View File

@ -32,7 +32,7 @@ pub enum ConstKind<I: Interner> {
Unevaluated(ty::UnevaluatedConst<I>),
/// Used to hold computed value.
Value(I::ValueConst),
Value(I::Ty, I::ValueConst),
/// A placeholder for a const which could not be computed; this is
/// propagated to avoid useless error messages.
@ -51,7 +51,7 @@ impl<I: Interner> PartialEq for ConstKind<I> {
(Bound(l0, l1), Bound(r0, r1)) => l0 == r0 && l1 == r1,
(Placeholder(l0), Placeholder(r0)) => l0 == r0,
(Unevaluated(l0), Unevaluated(r0)) => l0 == r0,
(Value(l0), Value(r0)) => l0 == r0,
(Value(l0, l1), Value(r0, r1)) => l0 == r0 && l1 == r1,
(Error(l0), Error(r0)) => l0 == r0,
(Expr(l0), Expr(r0)) => l0 == r0,
_ => false,
@ -80,7 +80,7 @@ impl<I: Interner> DebugWithInfcx<I> for ConstKind<I> {
Unevaluated(uv) => {
write!(f, "{:?}", &this.wrap(uv))
}
Value(valtree) => write!(f, "{valtree:?}"),
Value(ty, valtree) => write!(f, "({valtree:?}: {:?})", &this.wrap(ty)),
Error(_) => write!(f, "{{const error}}"),
Expr(expr) => write!(f, "{:?}", &this.wrap(expr)),
}

View File

@ -38,11 +38,11 @@ impl<I: Interner> InferCtxtLike for NoInfcx<I> {
panic!("cannot resolve {vid:?}")
}
fn opportunistic_resolve_ct_var(&self, vid: ConstVid, _: I::Ty) -> I::Const {
fn opportunistic_resolve_ct_var(&self, vid: ConstVid) -> I::Const {
panic!("cannot resolve {vid:?}")
}
fn opportunistic_resolve_effect_var(&self, vid: EffectVid, _: I::Ty) -> I::Const {
fn opportunistic_resolve_effect_var(&self, vid: EffectVid) -> I::Const {
panic!("cannot resolve {vid:?}")
}

View File

@ -387,7 +387,7 @@ impl<I: Interner> TypeFolder<I> for Shifter<I> {
match ct.kind() {
ty::ConstKind::Bound(debruijn, bound_ct) if debruijn >= self.current_index => {
let debruijn = debruijn.shifted_in(self.amount);
Const::new_bound(self.tcx, debruijn, bound_ct, ct.ty())
Const::new_bound(self.tcx, debruijn, bound_ct)
}
_ => ct.super_fold_with(self),
}

View File

@ -12,15 +12,10 @@ pub trait InferCtxtLike {
fn opportunistic_resolve_ty_var(&self, vid: TyVid) -> <Self::Interner as Interner>::Ty;
fn opportunistic_resolve_int_var(&self, vid: IntVid) -> <Self::Interner as Interner>::Ty;
fn opportunistic_resolve_float_var(&self, vid: FloatVid) -> <Self::Interner as Interner>::Ty;
fn opportunistic_resolve_ct_var(
&self,
vid: ConstVid,
ty: <Self::Interner as Interner>::Ty,
) -> <Self::Interner as Interner>::Const;
fn opportunistic_resolve_ct_var(&self, vid: ConstVid) -> <Self::Interner as Interner>::Const;
fn opportunistic_resolve_effect_var(
&self,
vid: EffectVid,
ty: <Self::Interner as Interner>::Ty,
) -> <Self::Interner as Interner>::Const;
fn opportunistic_resolve_lt_var(&self, vid: RegionVid) -> <Self::Interner as Interner>::Region;

View File

@ -104,22 +104,15 @@ pub trait Const<I: Interner<Const = Self>>:
+ TypeSuperFoldable<I>
+ Flags
{
fn new_infer(interner: I, var: ty::InferConst, ty: I::Ty) -> Self;
fn new_infer(interner: I, var: ty::InferConst) -> Self;
fn new_var(interner: I, var: ty::ConstVid, ty: I::Ty) -> Self;
fn new_var(interner: I, var: ty::ConstVid) -> Self;
fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundConst, ty: I::Ty) -> Self;
fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundConst) -> Self;
fn new_anon_bound(
interner: I,
debruijn: ty::DebruijnIndex,
var: ty::BoundVar,
ty: I::Ty,
) -> Self;
fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self;
fn new_unevaluated(interner: I, uv: ty::UnevaluatedConst<I>, ty: I::Ty) -> Self;
fn ty(self) -> I::Ty;
fn new_unevaluated(interner: I, uv: ty::UnevaluatedConst<I>) -> Self;
}
pub trait GenericsOf<I: Interner<GenericsOf = Self>> {

View File

@ -567,7 +567,6 @@ impl<I: Interner> AliasTerm<I> {
I::Const::new_unevaluated(
interner,
ty::UnevaluatedConst::new(self.def_id, self.args),
interner.type_of(self.def_id).instantiate(interner, &self.args),
)
.into()
}

View File

@ -130,7 +130,10 @@ pub(crate) fn try_inline(
}
Res::Def(DefKind::Const, did) => {
record_extern_fqn(cx, did, ItemType::Constant);
cx.with_param_env(did, |cx| clean::ConstantItem(build_const(cx, did)))
cx.with_param_env(did, |cx| {
let (generics, ty, ct) = build_const_item(cx, did);
clean::ConstantItem(generics, Box::new(ty), ct)
})
}
Res::Def(DefKind::Macro(kind), did) => {
let is_doc_hidden = cx.tcx.is_doc_hidden(did)
@ -717,21 +720,20 @@ pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String {
}
}
fn build_const(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant {
fn build_const_item(
cx: &mut DocContext<'_>,
def_id: DefId,
) -> (clean::Generics, clean::Type, clean::Constant) {
let mut generics =
clean_ty_generics(cx, cx.tcx.generics_of(def_id), cx.tcx.explicit_predicates_of(def_id));
clean::simplify::move_bounds_to_generic_parameters(&mut generics);
clean::Constant {
type_: Box::new(clean_middle_ty(
let ty = clean_middle_ty(
ty::Binder::dummy(cx.tcx.type_of(def_id).instantiate_identity()),
cx,
Some(def_id),
None,
)),
generics,
kind: clean::ConstantKind::Extern { def_id },
}
None,
);
(generics, ty, clean::Constant { kind: clean::ConstantKind::Extern { def_id } })
}
fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::Static {

View File

@ -283,31 +283,17 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) ->
pub(crate) fn clean_const<'tcx>(
constant: &hir::ConstArg<'_>,
cx: &mut DocContext<'tcx>,
_cx: &mut DocContext<'tcx>,
) -> Constant {
let def_id = cx.tcx.hir().body_owner_def_id(constant.value.body).to_def_id();
Constant {
type_: Box::new(clean_middle_ty(
ty::Binder::dummy(cx.tcx.type_of(def_id).instantiate_identity()),
cx,
Some(def_id),
None,
)),
generics: Generics::default(),
kind: ConstantKind::Anonymous { body: constant.value.body },
}
Constant { kind: ConstantKind::Anonymous { body: constant.value.body } }
}
pub(crate) fn clean_middle_const<'tcx>(
constant: ty::Binder<'tcx, ty::Const<'tcx>>,
cx: &mut DocContext<'tcx>,
_cx: &mut DocContext<'tcx>,
) -> Constant {
// FIXME: instead of storing the stringified expression, store `self` directly instead.
Constant {
type_: Box::new(clean_middle_ty(constant.map_bound(|c| c.ty()), cx, None, None)),
generics: Generics::default(),
kind: ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() },
}
Constant { kind: ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() } }
}
pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option<Lifetime> {
@ -2738,11 +2724,11 @@ fn clean_maybe_renamed_item<'tcx>(
ItemKind::Static(ty, mutability, body_id) => {
StaticItem(Static { type_: clean_ty(ty, cx), mutability, expr: Some(body_id) })
}
ItemKind::Const(ty, generics, body_id) => ConstantItem(Constant {
type_: Box::new(clean_ty(ty, cx)),
generics: clean_generics(generics, cx),
kind: ConstantKind::Local { body: body_id, def_id },
}),
ItemKind::Const(ty, generics, body_id) => ConstantItem(
clean_generics(generics, cx),
Box::new(clean_ty(ty, cx)),
Constant { kind: ConstantKind::Local { body: body_id, def_id } },
),
ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy {
bounds: ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
generics: clean_generics(ty.generics, cx),

View File

@ -830,7 +830,6 @@ pub(crate) enum ItemKind {
TypeAliasItem(Box<TypeAlias>),
OpaqueTyItem(OpaqueTy),
StaticItem(Static),
ConstantItem(Constant),
TraitItem(Box<Trait>),
TraitAliasItem(TraitAlias),
ImplItem(Box<Impl>),
@ -853,6 +852,7 @@ pub(crate) enum ItemKind {
PrimitiveItem(PrimitiveType),
/// A required associated constant in a trait declaration.
TyAssocConstItem(Generics, Box<Type>),
ConstantItem(Generics, Box<Type>, Constant),
/// An associated constant in a trait impl or a provided one in a trait declaration.
AssocConstItem(Generics, Box<Type>, ConstantKind),
/// A required associated type in a trait declaration.
@ -888,7 +888,7 @@ impl ItemKind {
| TypeAliasItem(_)
| OpaqueTyItem(_)
| StaticItem(_)
| ConstantItem(_)
| ConstantItem(_, _, _)
| TraitAliasItem(_)
| TyMethodItem(_)
| MethodItem(_, _)
@ -922,7 +922,7 @@ impl ItemKind {
| TypeAliasItem(_)
| OpaqueTyItem(_)
| StaticItem(_)
| ConstantItem(_)
| ConstantItem(_, _, _)
| TraitAliasItem(_)
| ForeignFunctionItem(_)
| ForeignStaticItem(_)
@ -2364,8 +2364,6 @@ pub(crate) struct Static {
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub(crate) struct Constant {
pub(crate) type_: Box<Type>,
pub(crate) generics: Generics,
pub(crate) kind: ConstantKind,
}

View File

@ -353,8 +353,8 @@ pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
s
}
// array lengths are obviously usize
ty::ConstKind::Value(ty::ValTree::Leaf(scalar))
if *n.ty().kind() == ty::Uint(ty::UintTy::Usize) =>
ty::ConstKind::Value(ty, ty::ValTree::Leaf(scalar))
if *ty.kind() == ty::Uint(ty::UintTy::Usize) =>
{
scalar.to_string()
}

View File

@ -79,7 +79,7 @@ pub(crate) trait DocFolder: Sized {
| FunctionItem(_)
| OpaqueTyItem(_)
| StaticItem(_)
| ConstantItem(_)
| ConstantItem(_, _, _)
| TraitAliasItem(_)
| TyMethodItem(_)
| MethodItem(_, _)

Some files were not shown because too many files have changed in this diff Show More