mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
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:
commit
003a902792
@ -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),
|
||||
};
|
||||
|
||||
|
@ -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")
|
||||
},
|
||||
};
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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!(),
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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:?}")
|
||||
|
@ -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
|
||||
|
@ -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()),
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
},
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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),
|
||||
|
@ -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)
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
)
|
||||
},
|
||||
};
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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) => {
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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)),
|
||||
}
|
||||
|
@ -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)]
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
||||
|
@ -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),
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)));
|
||||
|
@ -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>;
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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),
|
||||
}
|
||||
|
@ -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)]
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -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_ }
|
||||
}
|
||||
|
@ -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!(
|
||||
|
@ -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"),
|
||||
}
|
||||
|
@ -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[..] {
|
||||
|
@ -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`.
|
||||
|
@ -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)));
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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) => {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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() {
|
||||
|
@ -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,
|
||||
));
|
||||
|
@ -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(),
|
||||
|
@ -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 {
|
||||
|
@ -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) => {
|
||||
|
@ -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))
|
||||
|
@ -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("_")?,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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(),
|
||||
|
@ -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 });
|
||||
|
@ -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>> {
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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",
|
||||
)
|
||||
|
@ -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 =
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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() {
|
||||
|
@ -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),
|
||||
|
@ -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];
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
},
|
||||
)),
|
||||
|
@ -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)),
|
||||
}
|
||||
|
@ -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:?}")
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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>> {
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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),
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user