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
149 changed files with 1159 additions and 1228 deletions
|
@ -346,7 +346,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
||||||
} else {
|
} else {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let maybe_uneval = match constant.const_ {
|
let maybe_uneval = match constant.const_ {
|
||||||
Const::Ty(ct) => match ct.kind() {
|
Const::Ty(_, ct) => match ct.kind() {
|
||||||
ty::ConstKind::Unevaluated(_) => {
|
ty::ConstKind::Unevaluated(_) => {
|
||||||
bug!("should not encounter unevaluated Const::Ty here, got {:?}", ct)
|
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 {
|
if let Operand::Constant(constant) = op {
|
||||||
let maybe_uneval = match constant.const_ {
|
let maybe_uneval = match constant.const_ {
|
||||||
Const::Val(..) | Const::Ty(_) => None,
|
Const::Val(..) | Const::Ty(_, _) => None,
|
||||||
Const::Unevaluated(uv, _) => Some(uv),
|
Const::Unevaluated(uv, _) => Some(uv),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -193,7 +193,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
|
||||||
types: &mut |_bound_ty: ty::BoundTy| {
|
types: &mut |_bound_ty: ty::BoundTy| {
|
||||||
unreachable!("we only replace regions in nll_relate, not types")
|
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")
|
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| {
|
types: &mut |_bound_ty: ty::BoundTy| {
|
||||||
unreachable!("we only replace regions in nll_relate, not types")
|
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")
|
unreachable!("we only replace regions in nll_relate, not consts")
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -133,6 +133,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
||||||
.expect_const()
|
.expect_const()
|
||||||
.eval(fx.tcx, ty::ParamEnv::reveal_all(), span)
|
.eval(fx.tcx, ty::ParamEnv::reveal_all(), span)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
.1
|
||||||
.unwrap_branch();
|
.unwrap_branch();
|
||||||
|
|
||||||
assert_eq!(x.layout(), y.layout());
|
assert_eq!(x.layout(), y.layout());
|
||||||
|
|
|
@ -1201,6 +1201,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
||||||
.expect_const()
|
.expect_const()
|
||||||
.eval(tcx, ty::ParamEnv::reveal_all(), span)
|
.eval(tcx, ty::ParamEnv::reveal_all(), span)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
.1
|
||||||
.unwrap_branch();
|
.unwrap_branch();
|
||||||
let n = idx.len() as u64;
|
let n = idx.len() as u64;
|
||||||
|
|
||||||
|
|
|
@ -693,41 +693,46 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
|
||||||
ty::ConstKind::Param(param) => {
|
ty::ConstKind::Param(param) => {
|
||||||
write!(output, "{}", param.name)
|
write!(output, "{}", param.name)
|
||||||
}
|
}
|
||||||
_ => match ct.ty().kind() {
|
ty::ConstKind::Value(ty, _) => {
|
||||||
ty::Int(ity) => {
|
match ty.kind() {
|
||||||
let bits = ct.eval_bits(tcx, ty::ParamEnv::reveal_all());
|
ty::Int(ity) => {
|
||||||
let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
|
// FIXME: directly extract the bits from a valtree instead of evaluating an
|
||||||
write!(output, "{val}")
|
// alreay evaluated `Const` in order to get the bits.
|
||||||
}
|
let bits = ct.eval_bits(tcx, ty::ParamEnv::reveal_all());
|
||||||
ty::Uint(_) => {
|
let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
|
||||||
let val = ct.eval_bits(tcx, ty::ParamEnv::reveal_all());
|
write!(output, "{val}")
|
||||||
write!(output, "{val}")
|
}
|
||||||
}
|
ty::Uint(_) => {
|
||||||
ty::Bool => {
|
let val = ct.eval_bits(tcx, ty::ParamEnv::reveal_all());
|
||||||
let val = ct.try_eval_bool(tcx, ty::ParamEnv::reveal_all()).unwrap();
|
write!(output, "{val}")
|
||||||
write!(output, "{val}")
|
}
|
||||||
}
|
ty::Bool => {
|
||||||
_ => {
|
let val = ct.try_eval_bool(tcx, ty::ParamEnv::reveal_all()).unwrap();
|
||||||
// If we cannot evaluate the constant to a known type, we fall back
|
write!(output, "{val}")
|
||||||
// to emitting a stable hash value of the constant. This isn't very pretty
|
}
|
||||||
// but we get a deterministic, virtually unique value for the constant.
|
_ => {
|
||||||
//
|
// If we cannot evaluate the constant to a known type, we fall back
|
||||||
// Let's only emit 64 bits of the hash value. That should be plenty for
|
// to emitting a stable hash value of the constant. This isn't very pretty
|
||||||
// avoiding collisions and will make the emitted type names shorter.
|
// but we get a deterministic, virtually unique value for the constant.
|
||||||
let hash_short = tcx.with_stable_hashing_context(|mut hcx| {
|
//
|
||||||
let mut hasher = StableHasher::new();
|
// Let's only emit 64 bits of the hash value. That should be plenty for
|
||||||
let ct = ct.eval(tcx, ty::ParamEnv::reveal_all(), DUMMY_SP).unwrap();
|
// avoiding collisions and will make the emitted type names shorter.
|
||||||
hcx.while_hashing_spans(false, |hcx| ct.hash_stable(hcx, &mut hasher));
|
let hash_short = tcx.with_stable_hashing_context(|mut hcx| {
|
||||||
hasher.finish::<Hash64>()
|
let mut hasher = StableHasher::new();
|
||||||
});
|
let ct = ct.eval(tcx, ty::ParamEnv::reveal_all(), DUMMY_SP).unwrap();
|
||||||
|
hcx.while_hashing_spans(false, |hcx| ct.hash_stable(hcx, &mut hasher));
|
||||||
|
hasher.finish::<Hash64>()
|
||||||
|
});
|
||||||
|
|
||||||
if cpp_like_debuginfo(tcx) {
|
if cpp_like_debuginfo(tcx) {
|
||||||
write!(output, "CONST${hash_short:x}")
|
write!(output, "CONST${hash_short:x}")
|
||||||
} else {
|
} else {
|
||||||
write!(output, "{{CONST#{hash_short:x}}}")
|
write!(output, "{{CONST#{hash_short:x}}}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
_ => bug!("Invalid `Const` during codegen: {:?}", ct),
|
||||||
}
|
}
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,10 +40,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
) -> Result<Option<ty::ValTree<'tcx>>, ErrorHandled> {
|
) -> Result<Option<ty::ValTree<'tcx>>, ErrorHandled> {
|
||||||
let uv = match self.monomorphize(constant.const_) {
|
let uv = match self.monomorphize(constant.const_) {
|
||||||
mir::Const::Unevaluated(uv, _) => uv.shrink(),
|
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
|
// 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).
|
// 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:#?}"),
|
other => span_bug!(constant.span, "{other:#?}"),
|
||||||
},
|
},
|
||||||
// We should never encounter `Const::Val` unless MIR opts (like const prop) evaluate
|
// 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.
|
// Check the qualifs of the value of `const` items.
|
||||||
let uneval = match constant.const_ {
|
let uneval = match constant.const_ {
|
||||||
Const::Ty(ct)
|
Const::Ty(_, ct)
|
||||||
if matches!(
|
if matches!(
|
||||||
ct.kind(),
|
ct.kind(),
|
||||||
ty::ConstKind::Param(_) | ty::ConstKind::Error(_) | ty::ConstKind::Value(_)
|
ty::ConstKind::Param(_) | ty::ConstKind::Error(_) | ty::ConstKind::Value(_, _)
|
||||||
) =>
|
) =>
|
||||||
{
|
{
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
Const::Ty(c) => {
|
Const::Ty(_, c) => {
|
||||||
bug!("expected ConstKind::Param or ConstKind::Value here, found {:?}", c)
|
bug!("expected ConstKind::Param or ConstKind::Value here, found {:?}", c)
|
||||||
}
|
}
|
||||||
Const::Unevaluated(uv, _) => Some(uv),
|
Const::Unevaluated(uv, _) => Some(uv),
|
||||||
|
|
|
@ -2198,9 +2198,6 @@ fn param_env_with_gat_bounds<'tcx>(
|
||||||
tcx,
|
tcx,
|
||||||
ty::INNERMOST,
|
ty::INNERMOST,
|
||||||
ty::BoundVar::from_usize(bound_vars.len() - 1),
|
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()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
|
@ -396,16 +396,8 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
|
||||||
Ty::new_error_with_message(self.tcx(), span, "bad placeholder type")
|
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> {
|
fn ct_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> {
|
||||||
let ty = self.tcx.fold_regions(ty, |r, _| match *r {
|
ty::Const::new_error_with_message(self.tcx(), span, "bad placeholder constant")
|
||||||
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 probe_ty_param_bounds(
|
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())
|
.type_of(param.def_id.to_def_id())
|
||||||
.no_bound_vars()
|
.no_bound_vars()
|
||||||
.expect("const parameters cannot be generic");
|
.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
|
predicates
|
||||||
.insert((ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx), param.span));
|
.insert((ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx), param.span));
|
||||||
}
|
}
|
||||||
|
|
|
@ -368,11 +368,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
let ty = tcx
|
ty::Const::new_error(tcx, guar).into()
|
||||||
.type_of(param.def_id)
|
|
||||||
.no_bound_vars()
|
|
||||||
.expect("ct params cannot have early bound vars");
|
|
||||||
ty::Const::new_error(tcx, guar, ty).into()
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
num_bound_vars += 1;
|
num_bound_vars += 1;
|
||||||
|
|
|
@ -111,12 +111,7 @@ pub trait HirTyLowerer<'tcx> {
|
||||||
fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx>;
|
fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx>;
|
||||||
|
|
||||||
/// Returns the const to use when a const is omitted.
|
/// Returns the const to use when a const is omitted.
|
||||||
fn ct_infer(
|
fn ct_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx>;
|
||||||
&self,
|
|
||||||
ty: Ty<'tcx>,
|
|
||||||
param: Option<&ty::GenericParamDef>,
|
|
||||||
span: Span,
|
|
||||||
) -> Const<'tcx>;
|
|
||||||
|
|
||||||
/// Probe bounds in scope where the bounded type coincides with the given type parameter.
|
/// 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(
|
fn provided_kind(
|
||||||
&mut self,
|
&mut self,
|
||||||
preceding_args: &[ty::GenericArg<'tcx>],
|
_preceding_args: &[ty::GenericArg<'tcx>],
|
||||||
param: &ty::GenericParamDef,
|
param: &ty::GenericParamDef,
|
||||||
arg: &GenericArg<'tcx>,
|
arg: &GenericArg<'tcx>,
|
||||||
) -> ty::GenericArg<'tcx> {
|
) -> ty::GenericArg<'tcx> {
|
||||||
|
@ -447,7 +442,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
|
|
||||||
if let Err(incorrect) = self.incorrect_args {
|
if let Err(incorrect) = self.incorrect_args {
|
||||||
if incorrect.invalid_args.contains(&(param.index as usize)) {
|
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()
|
ty::Const::from_anon_const(tcx, did).into()
|
||||||
}
|
}
|
||||||
(&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => {
|
(&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => {
|
||||||
let ty = tcx
|
self.lowerer.ct_infer(Some(param), inf.span).into()
|
||||||
.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()
|
|
||||||
}
|
}
|
||||||
(kind, arg) => span_bug!(
|
(kind, arg) => span_bug!(
|
||||||
self.span,
|
self.span,
|
||||||
|
@ -511,7 +501,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
|
|
||||||
if let Err(incorrect) = self.incorrect_args {
|
if let Err(incorrect) = self.incorrect_args {
|
||||||
if incorrect.invalid_args.contains(&(param.index as usize)) {
|
if incorrect.invalid_args.contains(&(param.index as usize)) {
|
||||||
return param.to_error(tcx, preceding_args);
|
return param.to_error(tcx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match param.kind {
|
match param.kind {
|
||||||
|
@ -548,7 +538,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
.no_bound_vars()
|
.no_bound_vars()
|
||||||
.expect("const parameter types cannot be generic");
|
.expect("const parameter types cannot be generic");
|
||||||
if let Err(guar) = ty.error_reported() {
|
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
|
// FIXME(effects) see if we should special case effect params here
|
||||||
if !infer_args && has_default {
|
if !infer_args && has_default {
|
||||||
|
@ -557,10 +547,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
.into()
|
.into()
|
||||||
} else {
|
} else {
|
||||||
if infer_args {
|
if infer_args {
|
||||||
self.lowerer.ct_infer(ty, Some(param), self.span).into()
|
self.lowerer.ct_infer(Some(param), self.span).into()
|
||||||
} else {
|
} else {
|
||||||
// We've already errored above about the mismatch.
|
// 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`]
|
/// Early-bound const parameters get lowered to [`ty::ConstKind::Param`]
|
||||||
/// and late-bound ones to [`ty::ConstKind::Bound`].
|
/// 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();
|
let tcx = self.tcx();
|
||||||
match tcx.named_bound_var(hir_id) {
|
match tcx.named_bound_var(hir_id) {
|
||||||
Some(rbv::ResolvedArg::EarlyBound(def_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 generics = tcx.generics_of(item_def_id);
|
||||||
let index = generics.param_def_id_to_index[&def_id];
|
let index = generics.param_def_id_to_index[&def_id];
|
||||||
let name = tcx.item_name(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, _)) => {
|
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),
|
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", hir_id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2139,7 +2129,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
}
|
}
|
||||||
hir::TyKind::Array(ty, length) => {
|
hir::TyKind::Array(ty, length) => {
|
||||||
let length = match 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) => {
|
hir::ArrayLen::Body(constant) => {
|
||||||
ty::Const::from_anon_const(tcx, constant.def_id)
|
ty::Const::from_anon_const(tcx, constant.def_id)
|
||||||
}
|
}
|
||||||
|
@ -2170,17 +2160,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
}
|
}
|
||||||
_ => (expr, None),
|
_ => (expr, None),
|
||||||
};
|
};
|
||||||
let c = match &expr.kind {
|
let (c, c_ty) = match &expr.kind {
|
||||||
hir::ExprKind::Lit(lit) => {
|
hir::ExprKind::Lit(lit) => {
|
||||||
let lit_input =
|
let lit_input =
|
||||||
LitToConstInput { lit: &lit.node, ty, neg: neg.is_some() };
|
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,
|
Ok(c) => c,
|
||||||
Err(LitToConstError::Reported(err)) => {
|
Err(LitToConstError::Reported(err)) => {
|
||||||
ty::Const::new_error(tcx, err, ty)
|
ty::Const::new_error(tcx, err)
|
||||||
}
|
}
|
||||||
Err(LitToConstError::TypeError) => todo!(),
|
Err(LitToConstError::TypeError) => todo!(),
|
||||||
}
|
};
|
||||||
|
(ct, ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
hir::ExprKind::Path(hir::QPath::Resolved(
|
hir::ExprKind::Path(hir::QPath::Resolved(
|
||||||
|
@ -2198,19 +2189,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
.type_of(def_id)
|
.type_of(def_id)
|
||||||
.no_bound_vars()
|
.no_bound_vars()
|
||||||
.expect("const parameter types cannot be generic");
|
.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
|
let err = tcx
|
||||||
.dcx()
|
.dcx()
|
||||||
.emit_err(crate::errors::NonConstRange { span: expr.span });
|
.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 {
|
if let Some((id, span)) = neg {
|
||||||
self.record_ty(id, c.ty(), span);
|
self.record_ty(id, c_ty, span);
|
||||||
}
|
}
|
||||||
c
|
c
|
||||||
};
|
};
|
||||||
|
|
|
@ -143,9 +143,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
// `trait_object_dummy_self`, so check for that.
|
// `trait_object_dummy_self`, so check for that.
|
||||||
let references_self = match pred.skip_binder().term.unpack() {
|
let references_self = match pred.skip_binder().term.unpack() {
|
||||||
ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()),
|
ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()),
|
||||||
ty::TermKind::Const(c) => {
|
// FIXME(associated_const_equality): We should walk the const instead of not doing anything
|
||||||
c.ty().walk().any(|arg| arg == dummy_self.into())
|
ty::TermKind::Const(_) => false,
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// If the projection output contains `Self`, force the user to
|
// 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,
|
lt_op: |_| self.tcx.lifetimes.re_erased,
|
||||||
ct_op: |ct| {
|
ct_op: |ct| {
|
||||||
if let ty::ConstKind::Infer(_) = ct.kind() {
|
if let ty::ConstKind::Infer(_) = ct.kind() {
|
||||||
self.next_const_var(ct.ty(), DUMMY_SP)
|
self.next_const_var(DUMMY_SP)
|
||||||
} else {
|
} else {
|
||||||
ct
|
ct
|
||||||
}
|
}
|
||||||
|
|
|
@ -436,7 +436,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
pub fn lower_array_length(&self, length: &hir::ArrayLen<'tcx>) -> ty::Const<'tcx> {
|
pub fn lower_array_length(&self, length: &hir::ArrayLen<'tcx>) -> ty::Const<'tcx> {
|
||||||
match length {
|
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) => {
|
hir::ArrayLen::Body(anon_const) => {
|
||||||
let span = self.tcx.def_span(anon_const.def_id);
|
let span = self.tcx.def_span(anon_const.def_id);
|
||||||
let c = ty::Const::from_anon_const(self.tcx, 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 },
|
&GenericParamDefKind::Const { has_default, is_host_effect },
|
||||||
GenericArg::Infer(inf),
|
GenericArg::Infer(inf),
|
||||||
) => {
|
) => {
|
||||||
let tcx = self.fcx.tcx();
|
|
||||||
|
|
||||||
if has_default && is_host_effect {
|
if has_default && is_host_effect {
|
||||||
self.fcx.var_for_effect(param)
|
self.fcx.var_for_effect(param)
|
||||||
} else {
|
} else {
|
||||||
self.fcx
|
self.fcx.ct_infer(Some(param), inf.span).into()
|
||||||
.ct_infer(
|
|
||||||
tcx.type_of(param.def_id)
|
|
||||||
.no_bound_vars()
|
|
||||||
.expect("const parameter types cannot be generic"),
|
|
||||||
Some(param),
|
|
||||||
inf.span,
|
|
||||||
)
|
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
|
|
@ -237,12 +237,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ct_infer(
|
fn ct_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> {
|
||||||
&self,
|
|
||||||
ty: Ty<'tcx>,
|
|
||||||
param: Option<&ty::GenericParamDef>,
|
|
||||||
span: Span,
|
|
||||||
) -> Const<'tcx> {
|
|
||||||
// FIXME ideally this shouldn't use unwrap
|
// FIXME ideally this shouldn't use unwrap
|
||||||
match param {
|
match param {
|
||||||
Some(
|
Some(
|
||||||
|
@ -252,7 +247,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
|
||||||
},
|
},
|
||||||
) => self.var_for_effect(param).as_const().unwrap(),
|
) => self.var_for_effect(param).as_const().unwrap(),
|
||||||
Some(param) => self.var_for_def(span, 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()
|
self.cfcx.ty_infer(Some(param), inf.span).into()
|
||||||
}
|
}
|
||||||
(GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
|
(GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
|
||||||
let tcx = self.cfcx.tcx();
|
self.cfcx.ct_infer(Some(param), inf.span).into()
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
(kind, arg) => {
|
(kind, arg) => {
|
||||||
bug!("mismatched method arg kind {kind:?} in turbofish: {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))
|
.next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP))
|
||||||
.into(),
|
.into(),
|
||||||
GenericArgKind::Type(_) => self.next_ty_var(DUMMY_SP).into(),
|
GenericArgKind::Type(_) => self.next_ty_var(DUMMY_SP).into(),
|
||||||
GenericArgKind::Const(arg) => {
|
GenericArgKind::Const(_) => self.next_const_var(DUMMY_SP).into(),
|
||||||
self.next_const_var(arg.ty(), DUMMY_SP).into()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
arg
|
arg
|
||||||
|
|
|
@ -2409,7 +2409,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
min_len: u64,
|
min_len: u64,
|
||||||
) -> (Option<Ty<'tcx>>, Ty<'tcx>) {
|
) -> (Option<Ty<'tcx>>, Ty<'tcx>) {
|
||||||
let len = match len.eval(self.tcx, self.param_env, span) {
|
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()
|
.try_to_scalar()
|
||||||
.and_then(|scalar| scalar.try_to_int().ok())
|
.and_then(|scalar| scalar.try_to_int().ok())
|
||||||
.and_then(|int| int.try_to_target_usize(self.tcx).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> {
|
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
||||||
self.handle_term(ct, ty::Const::outer_exclusive_binder, |tcx, guar| {
|
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)
|
.super_fold_with(self)
|
||||||
}
|
}
|
||||||
|
|
|
@ -462,7 +462,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
|
||||||
// any equated inference vars correctly!
|
// any equated inference vars correctly!
|
||||||
let root_vid = self.infcx.unwrap().root_const_var(vid);
|
let root_vid = self.infcx.unwrap().root_const_var(vid);
|
||||||
if root_vid != 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;
|
vid = root_vid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -481,7 +481,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
|
||||||
ui = ty::UniverseIndex::ROOT;
|
ui = ty::UniverseIndex::ROOT;
|
||||||
}
|
}
|
||||||
return self.canonicalize_const_var(
|
return self.canonicalize_const_var(
|
||||||
CanonicalVarInfo { kind: CanonicalVarKind::Const(ui, ct.ty()) },
|
CanonicalVarInfo { kind: CanonicalVarKind::Const(ui) },
|
||||||
ct,
|
ct,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -510,9 +510,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
ty::ConstKind::Placeholder(placeholder) => {
|
ty::ConstKind::Placeholder(placeholder) => {
|
||||||
return self.canonicalize_const_var(
|
return self.canonicalize_const_var(
|
||||||
CanonicalVarInfo {
|
CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderConst(placeholder) },
|
||||||
kind: CanonicalVarKind::PlaceholderConst(placeholder, ct.ty()),
|
|
||||||
},
|
|
||||||
ct,
|
ct,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -719,9 +717,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
|
||||||
CanonicalVarKind::Region(u) => {
|
CanonicalVarKind::Region(u) => {
|
||||||
CanonicalVarKind::Region(reverse_universe_map[&u])
|
CanonicalVarKind::Region(reverse_universe_map[&u])
|
||||||
}
|
}
|
||||||
CanonicalVarKind::Const(u, t) => {
|
CanonicalVarKind::Const(u) => CanonicalVarKind::Const(reverse_universe_map[&u]),
|
||||||
CanonicalVarKind::Const(reverse_universe_map[&u], t)
|
|
||||||
}
|
|
||||||
CanonicalVarKind::PlaceholderTy(placeholder) => {
|
CanonicalVarKind::PlaceholderTy(placeholder) => {
|
||||||
CanonicalVarKind::PlaceholderTy(ty::Placeholder {
|
CanonicalVarKind::PlaceholderTy(ty::Placeholder {
|
||||||
universe: reverse_universe_map[&placeholder.universe],
|
universe: reverse_universe_map[&placeholder.universe],
|
||||||
|
@ -734,14 +730,11 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
|
||||||
..placeholder
|
..placeholder
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
CanonicalVarKind::PlaceholderConst(placeholder, t) => {
|
CanonicalVarKind::PlaceholderConst(placeholder) => {
|
||||||
CanonicalVarKind::PlaceholderConst(
|
CanonicalVarKind::PlaceholderConst(ty::Placeholder {
|
||||||
ty::Placeholder {
|
universe: reverse_universe_map[&placeholder.universe],
|
||||||
universe: reverse_universe_map[&placeholder.universe],
|
..placeholder
|
||||||
..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))
|
!self.infcx.is_some_and(|infcx| const_var != infcx.shallow_resolve_const(const_var))
|
||||||
);
|
);
|
||||||
let var = self.canonical_var(info, const_var.into());
|
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,
|
GenericArgKind::Type(ty) => ty,
|
||||||
r => bug!("{:?} is a type but value is {:?}", bound_ty, r),
|
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,
|
GenericArgKind::Const(ct) => ct,
|
||||||
c => bug!("{:?} is a const but value is {:?}", bound_ct, c),
|
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()
|
ty::Region::new_placeholder(self.tcx, placeholder_mapped).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
CanonicalVarKind::Const(ui, ty) => {
|
CanonicalVarKind::Const(ui) => {
|
||||||
self.next_const_var_in_universe(ty, span, universe_map(ui)).into()
|
self.next_const_var_in_universe(span, universe_map(ui)).into()
|
||||||
}
|
}
|
||||||
CanonicalVarKind::Effect => {
|
CanonicalVarKind::Effect => {
|
||||||
let vid = self
|
let vid = self
|
||||||
|
@ -153,13 +153,12 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
.effect_unification_table()
|
.effect_unification_table()
|
||||||
.new_key(EffectVarValue::Unknown)
|
.new_key(EffectVarValue::Unknown)
|
||||||
.vid;
|
.vid;
|
||||||
ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(vid), self.tcx.types.bool)
|
ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(vid)).into()
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
CanonicalVarKind::PlaceholderConst(ty::PlaceholderConst { universe, bound }, ty) => {
|
CanonicalVarKind::PlaceholderConst(ty::PlaceholderConst { universe, bound }) => {
|
||||||
let universe_mapped = universe_map(universe);
|
let universe_mapped = universe_map(universe);
|
||||||
let placeholder_mapped = ty::PlaceholderConst { universe: universe_mapped, bound };
|
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() {
|
match arg.unpack() {
|
||||||
GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
|
GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
|
||||||
GenericArgKind::Type(_) => self.next_ty_var(DUMMY_SP).into(),
|
GenericArgKind::Type(_) => self.next_ty_var(DUMMY_SP).into(),
|
||||||
GenericArgKind::Const(arg) => {
|
GenericArgKind::Const(_) => self.next_const_var(DUMMY_SP).into(),
|
||||||
self.next_const_var(arg.ty(), DUMMY_SP).into()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
@ -79,7 +79,6 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
|
||||||
&mut self,
|
&mut self,
|
||||||
input: Result<ty::Const<'tcx>, ty::InferConst>,
|
input: Result<ty::Const<'tcx>, ty::InferConst>,
|
||||||
freshener: F,
|
freshener: F,
|
||||||
ty: Ty<'tcx>,
|
|
||||||
) -> ty::Const<'tcx>
|
) -> ty::Const<'tcx>
|
||||||
where
|
where
|
||||||
F: FnOnce(u32) -> ty::InferConst,
|
F: FnOnce(u32) -> ty::InferConst,
|
||||||
|
@ -91,7 +90,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
|
||||||
Entry::Vacant(entry) => {
|
Entry::Vacant(entry) => {
|
||||||
let index = self.const_freshen_count;
|
let index = self.const_freshen_count;
|
||||||
self.const_freshen_count += 1;
|
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);
|
entry.insert(ct);
|
||||||
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)
|
ty::InferConst::Var(inner.const_unification_table().find(v).vid)
|
||||||
});
|
});
|
||||||
drop(inner);
|
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)) => {
|
ty::ConstKind::Infer(ty::InferConst::EffectVar(v)) => {
|
||||||
let mut inner = self.infcx.inner.borrow_mut();
|
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)
|
ty::InferConst::EffectVar(inner.effect_unification_table().find(v).vid)
|
||||||
});
|
});
|
||||||
drop(inner);
|
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)) => {
|
ty::ConstKind::Infer(ty::InferConst::Fresh(i)) => {
|
||||||
if i >= self.const_freshen_count {
|
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::Param(_)
|
||||||
| ty::ConstKind::Value(_)
|
| ty::ConstKind::Value(_, _)
|
||||||
| ty::ConstKind::Unevaluated(..)
|
| ty::ConstKind::Unevaluated(..)
|
||||||
| ty::ConstKind::Expr(..)
|
| ty::ConstKind::Expr(..)
|
||||||
| ty::ConstKind::Error(_) => ct.super_fold_with(self),
|
| 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)
|
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) {
|
match self.probe_const_var(vid) {
|
||||||
Ok(ct) => ct,
|
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) {
|
match self.probe_effect_var(vid) {
|
||||||
Some(ct) => ct,
|
Some(ct) => ct,
|
||||||
None => {
|
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())
|
(0..table.len())
|
||||||
.map(|i| ty::EffectVid::from_usize(i))
|
.map(|i| ty::EffectVid::from_usize(i))
|
||||||
.filter(|&vid| table.probe_value(vid).is_unknown())
|
.filter(|&vid| table.probe_value(vid).is_unknown())
|
||||||
.map(|v| {
|
.map(|v| ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(v)))
|
||||||
ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(v), self.tcx.types.bool)
|
|
||||||
})
|
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -993,27 +991,22 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
Ty::new_var(self.tcx, vid)
|
Ty::new_var(self.tcx, vid)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_const_var(&self, ty: Ty<'tcx>, span: Span) -> ty::Const<'tcx> {
|
pub fn next_const_var(&self, span: Span) -> ty::Const<'tcx> {
|
||||||
self.next_const_var_with_origin(ty, ConstVariableOrigin { span, param_def_id: None })
|
self.next_const_var_with_origin(ConstVariableOrigin { span, param_def_id: None })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_const_var_with_origin(
|
pub fn next_const_var_with_origin(&self, origin: ConstVariableOrigin) -> ty::Const<'tcx> {
|
||||||
&self,
|
|
||||||
ty: Ty<'tcx>,
|
|
||||||
origin: ConstVariableOrigin,
|
|
||||||
) -> ty::Const<'tcx> {
|
|
||||||
let vid = self
|
let vid = self
|
||||||
.inner
|
.inner
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.const_unification_table()
|
.const_unification_table()
|
||||||
.new_key(ConstVariableValue::Unknown { origin, universe: self.universe() })
|
.new_key(ConstVariableValue::Unknown { origin, universe: self.universe() })
|
||||||
.vid;
|
.vid;
|
||||||
ty::Const::new_var(self.tcx, vid, ty)
|
ty::Const::new_var(self.tcx, vid)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_const_var_in_universe(
|
pub fn next_const_var_in_universe(
|
||||||
&self,
|
&self,
|
||||||
ty: Ty<'tcx>,
|
|
||||||
span: Span,
|
span: Span,
|
||||||
universe: ty::UniverseIndex,
|
universe: ty::UniverseIndex,
|
||||||
) -> ty::Const<'tcx> {
|
) -> ty::Const<'tcx> {
|
||||||
|
@ -1024,7 +1017,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
.const_unification_table()
|
.const_unification_table()
|
||||||
.new_key(ConstVariableValue::Unknown { origin, universe })
|
.new_key(ConstVariableValue::Unknown { origin, universe })
|
||||||
.vid;
|
.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 {
|
pub fn next_const_var_id(&self, origin: ConstVariableOrigin) -> ConstVid {
|
||||||
|
@ -1135,15 +1128,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
.const_unification_table()
|
.const_unification_table()
|
||||||
.new_key(ConstVariableValue::Unknown { origin, universe: self.universe() })
|
.new_key(ConstVariableValue::Unknown { origin, universe: self.universe() })
|
||||||
.vid;
|
.vid;
|
||||||
ty::Const::new_var(
|
ty::Const::new_var(self.tcx, const_var_id).into()
|
||||||
self.tcx,
|
|
||||||
const_var_id,
|
|
||||||
self.tcx
|
|
||||||
.type_of(param.def_id)
|
|
||||||
.no_bound_vars()
|
|
||||||
.expect("const parameter types cannot be generic"),
|
|
||||||
)
|
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1157,7 +1142,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
.no_bound_vars()
|
.no_bound_vars()
|
||||||
.expect("const parameter types cannot be generic");
|
.expect("const parameter types cannot be generic");
|
||||||
debug_assert_eq!(self.tcx.types.bool, ty);
|
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
|
/// 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::Bound(_, _)
|
||||||
| ty::ConstKind::Placeholder(_)
|
| ty::ConstKind::Placeholder(_)
|
||||||
| ty::ConstKind::Unevaluated(_)
|
| ty::ConstKind::Unevaluated(_)
|
||||||
| ty::ConstKind::Value(_)
|
| ty::ConstKind::Value(_, _)
|
||||||
| ty::ConstKind::Error(_)
|
| ty::ConstKind::Error(_)
|
||||||
| ty::ConstKind::Expr(_) => ct,
|
| ty::ConstKind::Expr(_) => ct,
|
||||||
}
|
}
|
||||||
|
@ -1469,10 +1454,10 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
.or_insert_with(|| self.infcx.next_ty_var(self.span).into())
|
.or_insert_with(|| self.infcx.next_ty_var(self.span).into())
|
||||||
.expect_ty()
|
.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
|
self.map
|
||||||
.entry(bv)
|
.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()
|
.expect_const()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1526,11 +1511,14 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
&self,
|
&self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
unevaluated: ty::UnevaluatedConst<'tcx>,
|
unevaluated: ty::UnevaluatedConst<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<ty::Const<'tcx>, ErrorHandled> {
|
) -> Result<ty::Const<'tcx>, ErrorHandled> {
|
||||||
match self.const_eval_resolve(param_env, unevaluated, span) {
|
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) => {
|
Ok(None) => {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let def_id = unevaluated.def;
|
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> {
|
fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
||||||
if let ty::ConstKind::Infer(_) = c.kind() {
|
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(
|
ty::Const::new_placeholder(
|
||||||
self.tcx,
|
self.tcx,
|
||||||
ty::PlaceholderConst {
|
ty::PlaceholderConst {
|
||||||
|
@ -1979,7 +1962,6 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>(
|
||||||
idx
|
idx
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
ty,
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
c.super_fold_with(self)
|
c.super_fold_with(self)
|
||||||
|
|
|
@ -653,7 +653,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
||||||
{
|
{
|
||||||
variable_table.union(vid, new_var_id);
|
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,
|
||||||
args,
|
args,
|
||||||
)?;
|
)?;
|
||||||
Ok(ty::Const::new_unevaluated(
|
Ok(ty::Const::new_unevaluated(self.tcx(), ty::UnevaluatedConst { def, args }))
|
||||||
self.tcx(),
|
|
||||||
ty::UnevaluatedConst { def, args },
|
|
||||||
c.ty(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
ty::ConstKind::Placeholder(placeholder) => {
|
ty::ConstKind::Placeholder(placeholder) => {
|
||||||
if self.for_universe.can_name(placeholder.universe) {
|
if self.for_universe.can_name(placeholder.universe) {
|
||||||
|
|
|
@ -43,11 +43,10 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
ty::PlaceholderType { universe: next_universe, bound: bound_ty },
|
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(
|
ty::Const::new_placeholder(
|
||||||
self.tcx,
|
self.tcx,
|
||||||
ty::PlaceholderConst { universe: next_universe, bound: bound_var },
|
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.
|
// Recreate it with a fresh variable here.
|
||||||
let idx = vid.index() - self.const_vars.0.start.index();
|
let idx = vid.index() - self.const_vars.0.start.index();
|
||||||
let origin = self.const_vars.1[idx];
|
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 {
|
} else {
|
||||||
ct
|
ct
|
||||||
}
|
}
|
||||||
|
|
|
@ -204,7 +204,9 @@ pub enum Const<'tcx> {
|
||||||
/// Any way of turning `ty::Const` into `ConstValue` should go through `valtree_to_const_val`;
|
/// 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
|
/// this ensures that we consistently produce "clean" values without data in the padding or
|
||||||
/// anything like that.
|
/// 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.
|
/// An unevaluated mir constant which is not part of the type system.
|
||||||
///
|
///
|
||||||
|
@ -237,7 +239,15 @@ impl<'tcx> Const<'tcx> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn ty(&self) -> Ty<'tcx> {
|
pub fn ty(&self) -> Ty<'tcx> {
|
||||||
match self {
|
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,
|
Const::Val(_, ty) | Const::Unevaluated(_, ty) => *ty,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -247,8 +257,8 @@ impl<'tcx> Const<'tcx> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_required_const(&self) -> bool {
|
pub fn is_required_const(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Const::Ty(c) => match c.kind() {
|
Const::Ty(_, c) => match c.kind() {
|
||||||
ty::ConstKind::Value(_) => false, // already a value, cannot error
|
ty::ConstKind::Value(_, _) => false, // already a value, cannot error
|
||||||
_ => true,
|
_ => true,
|
||||||
},
|
},
|
||||||
Const::Val(..) => false, // already a value, cannot error
|
Const::Val(..) => false, // already a value, cannot error
|
||||||
|
@ -259,8 +269,8 @@ impl<'tcx> Const<'tcx> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn try_to_scalar(self) -> Option<Scalar> {
|
pub fn try_to_scalar(self) -> Option<Scalar> {
|
||||||
match self {
|
match self {
|
||||||
Const::Ty(c) => match c.kind() {
|
Const::Ty(_, c) => match c.kind() {
|
||||||
ty::ConstKind::Value(valtree) if c.ty().is_primitive() => {
|
ty::ConstKind::Value(ty, valtree) if ty.is_primitive() => {
|
||||||
// A valtree of a type where leaves directly represent the scalar const value.
|
// 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
|
// 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!
|
// 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.
|
// This is equivalent to `self.try_to_scalar()?.try_to_int().ok()`, but measurably faster.
|
||||||
match self {
|
match self {
|
||||||
Const::Val(ConstValue::Scalar(Scalar::Int(x)), _) => Some(x),
|
Const::Val(ConstValue::Scalar(Scalar::Int(x)), _) => Some(x),
|
||||||
Const::Ty(c) => match c.kind() {
|
Const::Ty(_, c) => match c.kind() {
|
||||||
ty::ConstKind::Value(valtree) if c.ty().is_primitive() => {
|
ty::ConstKind::Value(ty, valtree) if ty.is_primitive() => {
|
||||||
Some(valtree.unwrap_leaf())
|
Some(valtree.unwrap_leaf())
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -306,11 +316,11 @@ impl<'tcx> Const<'tcx> {
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<ConstValue<'tcx>, ErrorHandled> {
|
) -> Result<ConstValue<'tcx>, ErrorHandled> {
|
||||||
match self {
|
match self {
|
||||||
Const::Ty(c) => {
|
Const::Ty(_, c) => {
|
||||||
// We want to consistently have a "clean" value for type system constants (i.e., no
|
// 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.
|
// data hidden in the padding), so we always go through a valtree here.
|
||||||
let val = c.eval(tcx, param_env, span)?;
|
let (ty, val) = c.eval(tcx, param_env, span)?;
|
||||||
Ok(tcx.valtree_to_const_val((self.ty(), val)))
|
Ok(tcx.valtree_to_const_val((ty, val)))
|
||||||
}
|
}
|
||||||
Const::Unevaluated(uneval, _) => {
|
Const::Unevaluated(uneval, _) => {
|
||||||
// FIXME: We might want to have a `try_eval`-like function on `Unevaluated`
|
// 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) {
|
match self.eval(tcx, param_env, DUMMY_SP) {
|
||||||
Ok(val) => Self::Val(val, self.ty()),
|
Ok(val) => Self::Val(val, self.ty()),
|
||||||
Err(ErrorHandled::Reported(guar, _span)) => {
|
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,
|
Err(ErrorHandled::TooGeneric(_span)) => self,
|
||||||
}
|
}
|
||||||
|
@ -338,15 +348,16 @@ impl<'tcx> Const<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
) -> Option<Scalar> {
|
) -> Option<Scalar> {
|
||||||
match self {
|
if let Const::Ty(_, c) = self
|
||||||
Const::Ty(c) if c.ty().is_primitive() => {
|
&& let ty::ConstKind::Value(ty, val) = c.kind()
|
||||||
// Avoid the `valtree_to_const_val` query. Can only be done on primitive types that
|
&& ty.is_primitive()
|
||||||
// are valtree leaves, and *not* on references. (References should return the
|
{
|
||||||
// pointer here, which valtrees don't represent.)
|
// Avoid the `valtree_to_const_val` query. Can only be done on primitive types that
|
||||||
let val = c.eval(tcx, param_env, DUMMY_SP).ok()?;
|
// are valtree leaves, and *not* on references. (References should return the
|
||||||
Some(val.unwrap_leaf().into())
|
// pointer here, which valtrees don't represent.)
|
||||||
}
|
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)
|
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() {
|
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.
|
// Make sure that if `c` is normalized, then the return value is normalized.
|
||||||
let const_val = tcx.valtree_to_const_val((c.ty(), valtree));
|
let const_val = tcx.valtree_to_const_val((ty, valtree));
|
||||||
Self::Val(const_val, c.ty())
|
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
|
// - valtrees purposefully generate new allocations
|
||||||
// - ConstValue::Slice also generate new allocations
|
// - ConstValue::Slice also generate new allocations
|
||||||
match self {
|
match self {
|
||||||
Const::Ty(c) => match c.kind() {
|
Const::Ty(_, c) => match c.kind() {
|
||||||
ty::ConstKind::Param(..) => true,
|
ty::ConstKind::Param(..) => true,
|
||||||
// A valtree may be a reference. Valtree references correspond to a
|
// A valtree may be a reference. Valtree references correspond to a
|
||||||
// different allocation each time they are evaluated. Valtrees for primitive
|
// different allocation each time they are evaluated. Valtrees for primitive
|
||||||
// types are fine though.
|
// 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,
|
ty::ConstKind::Unevaluated(..) | ty::ConstKind::Expr(..) => false,
|
||||||
// This can happen if evaluation of a constant failed. The result does not matter
|
// This can happen if evaluation of a constant failed. The result does not matter
|
||||||
// much since compilation is doomed.
|
// much since compilation is doomed.
|
||||||
|
@ -517,7 +528,7 @@ impl<'tcx> UnevaluatedConst<'tcx> {
|
||||||
impl<'tcx> Display for Const<'tcx> {
|
impl<'tcx> Display for Const<'tcx> {
|
||||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
||||||
match *self {
|
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),
|
Const::Val(val, ty) => pretty_print_const_value(val, ty, fmt),
|
||||||
// FIXME(valtrees): Correctly print mir constants.
|
// FIXME(valtrees): Correctly print mir constants.
|
||||||
Const::Unevaluated(c, _ty) => {
|
Const::Unevaluated(c, _ty) => {
|
||||||
|
|
|
@ -1313,12 +1313,12 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let val = match const_ {
|
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::Param(p) => format!("ty::Param({p})"),
|
||||||
ty::ConstKind::Unevaluated(uv) => {
|
ty::ConstKind::Unevaluated(uv) => {
|
||||||
format!("ty::Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.args,)
|
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`.
|
// No `ty::` prefix since we also use this to represent errors from `mir::Unevaluated`.
|
||||||
ty::ConstKind::Error(_) => "Error".to_string(),
|
ty::ConstKind::Error(_) => "Error".to_string(),
|
||||||
// These variants shouldn't exist in the MIR.
|
// These variants shouldn't exist in the MIR.
|
||||||
|
@ -1417,7 +1417,7 @@ pub fn write_allocations<'tcx>(
|
||||||
impl<'tcx> Visitor<'tcx> for CollectAllocIds {
|
impl<'tcx> Visitor<'tcx> for CollectAllocIds {
|
||||||
fn visit_constant(&mut self, c: &ConstOperand<'tcx>, _: Location) {
|
fn visit_constant(&mut self, c: &ConstOperand<'tcx>, _: Location) {
|
||||||
match c.const_ {
|
match c.const_ {
|
||||||
Const::Ty(_) | Const::Unevaluated(..) => {}
|
Const::Ty(_, _) | Const::Unevaluated(..) => {}
|
||||||
Const::Val(val, _) => {
|
Const::Val(val, _) => {
|
||||||
self.0.extend(alloc_ids_from_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);
|
self.visit_span($(& $mutability)? *span);
|
||||||
match const_ {
|
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::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
|
||||||
Const::Unevaluated(_, 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 can thus not know whether the hidden type implements an auto trait, so
|
||||||
/// we should not presume anything about it.
|
/// we should not presume anything about it.
|
||||||
OpaqueTypeAutoTraitLeakageUnknown(DefId),
|
OpaqueTypeAutoTraitLeakageUnknown(DefId),
|
||||||
|
/// Error for a `ConstArgHasType` goal
|
||||||
|
ConstArgHasWrongType { ct: ty::Const<'tcx>, ct_ty: Ty<'tcx>, expected_ty: Ty<'tcx> },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, TypeVisitable)]
|
#[derive(Clone, Debug, TypeVisitable)]
|
||||||
|
|
|
@ -53,7 +53,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
fn fold_const(&mut self, c: Const<'tcx>) -> Const<'tcx> {
|
fn fold_const(&mut self, c: Const<'tcx>) -> Const<'tcx> {
|
||||||
let ct = match c.kind() {
|
let ct = match c.kind() {
|
||||||
ty::ConstKind::Unevaluated(uv) => match self.tcx.thir_abstract_const(uv.def) {
|
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)) => {
|
Ok(Some(bac)) => {
|
||||||
let args = self.tcx.erase_regions(uv.args);
|
let args = self.tcx.erase_regions(uv.args);
|
||||||
let bac = bac.instantiate(self.tcx, 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> {
|
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Const<'tcx> {
|
||||||
fn decode(decoder: &mut D) -> Self {
|
fn decode(decoder: &mut D) -> Self {
|
||||||
let consts: ty::ConstData<'tcx> = Decodable::decode(decoder);
|
let kind: ty::ConstKind<'tcx> = Decodable::decode(decoder);
|
||||||
decoder.interner().mk_ct_from_kind(consts.kind, consts.ty)
|
decoder.interner().mk_ct_from_kind(kind)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ use rustc_error_messages::MultiSpan;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::def_id::LocalDefId;
|
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 rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
|
||||||
use tracing::{debug, instrument};
|
use tracing::{debug, instrument};
|
||||||
|
|
||||||
|
@ -24,12 +24,11 @@ pub type ConstKind<'tcx> = ir::ConstKind<TyCtxt<'tcx>>;
|
||||||
pub type UnevaluatedConst<'tcx> = ir::UnevaluatedConst<TyCtxt<'tcx>>;
|
pub type UnevaluatedConst<'tcx> = ir::UnevaluatedConst<TyCtxt<'tcx>>;
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[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)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)]
|
||||||
#[rustc_pass_by_value]
|
#[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> {
|
impl<'tcx> rustc_type_ir::inherent::IntoKind for Const<'tcx> {
|
||||||
type Kind = ConstKind<'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> {
|
impl<'tcx> Const<'tcx> {
|
||||||
#[inline]
|
|
||||||
pub fn ty(self) -> Ty<'tcx> {
|
|
||||||
self.0.ty
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn kind(self) -> ConstKind<'tcx> {
|
pub fn kind(self) -> ConstKind<'tcx> {
|
||||||
self.0.kind
|
let a: &ConstKind<'tcx> = self.0.0;
|
||||||
|
*a
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(compiler-errors): Think about removing this.
|
// FIXME(compiler-errors): Think about removing this.
|
||||||
|
@ -84,28 +68,28 @@ impl<'tcx> Const<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(tcx: TyCtxt<'tcx>, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
|
pub fn new(tcx: TyCtxt<'tcx>, kind: ty::ConstKind<'tcx>) -> Const<'tcx> {
|
||||||
tcx.mk_ct_from_kind(kind, ty)
|
tcx.mk_ct_from_kind(kind)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_param(tcx: TyCtxt<'tcx>, param: ty::ParamConst, ty: Ty<'tcx>) -> Const<'tcx> {
|
pub fn new_param(tcx: TyCtxt<'tcx>, param: ty::ParamConst) -> Const<'tcx> {
|
||||||
Const::new(tcx, ty::ConstKind::Param(param), ty)
|
Const::new(tcx, ty::ConstKind::Param(param))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_var(tcx: TyCtxt<'tcx>, infer: ty::ConstVid, ty: Ty<'tcx>) -> Const<'tcx> {
|
pub fn new_var(tcx: TyCtxt<'tcx>, infer: ty::ConstVid) -> Const<'tcx> {
|
||||||
Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Var(infer)), ty)
|
Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Var(infer)))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_fresh(tcx: TyCtxt<'tcx>, fresh: u32, ty: Ty<'tcx>) -> Const<'tcx> {
|
pub fn new_fresh(tcx: TyCtxt<'tcx>, fresh: u32) -> Const<'tcx> {
|
||||||
Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Fresh(fresh)), ty)
|
Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Fresh(fresh)))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst, ty: Ty<'tcx>) -> Const<'tcx> {
|
pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst) -> Const<'tcx> {
|
||||||
Const::new(tcx, ty::ConstKind::Infer(infer), ty)
|
Const::new(tcx, ty::ConstKind::Infer(infer))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -113,50 +97,40 @@ impl<'tcx> Const<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
debruijn: ty::DebruijnIndex,
|
debruijn: ty::DebruijnIndex,
|
||||||
var: ty::BoundVar,
|
var: ty::BoundVar,
|
||||||
ty: Ty<'tcx>,
|
|
||||||
) -> Const<'tcx> {
|
) -> Const<'tcx> {
|
||||||
Const::new(tcx, ty::ConstKind::Bound(debruijn, var), ty)
|
Const::new(tcx, ty::ConstKind::Bound(debruijn, var))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_placeholder(
|
pub fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderConst) -> Const<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
Const::new(tcx, ty::ConstKind::Placeholder(placeholder))
|
||||||
placeholder: ty::PlaceholderConst,
|
|
||||||
ty: Ty<'tcx>,
|
|
||||||
) -> Const<'tcx> {
|
|
||||||
Const::new(tcx, ty::ConstKind::Placeholder(placeholder), ty)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_unevaluated(
|
pub fn new_unevaluated(tcx: TyCtxt<'tcx>, uv: ty::UnevaluatedConst<'tcx>) -> Const<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
Const::new(tcx, ty::ConstKind::Unevaluated(uv))
|
||||||
uv: ty::UnevaluatedConst<'tcx>,
|
|
||||||
ty: Ty<'tcx>,
|
|
||||||
) -> Const<'tcx> {
|
|
||||||
Const::new(tcx, ty::ConstKind::Unevaluated(uv), ty)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_value(tcx: TyCtxt<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
|
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]
|
#[inline]
|
||||||
pub fn new_expr(tcx: TyCtxt<'tcx>, expr: ty::Expr<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
|
pub fn new_expr(tcx: TyCtxt<'tcx>, expr: ty::Expr<'tcx>) -> Const<'tcx> {
|
||||||
Const::new(tcx, ty::ConstKind::Expr(expr), ty)
|
Const::new(tcx, ty::ConstKind::Expr(expr))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_error(tcx: TyCtxt<'tcx>, e: ty::ErrorGuaranteed, ty: Ty<'tcx>) -> Const<'tcx> {
|
pub fn new_error(tcx: TyCtxt<'tcx>, e: ty::ErrorGuaranteed) -> Const<'tcx> {
|
||||||
Const::new(tcx, ty::ConstKind::Error(e), ty)
|
Const::new(tcx, ty::ConstKind::Error(e))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Like [Ty::new_error] but for constants.
|
/// Like [Ty::new_error] but for constants.
|
||||||
#[track_caller]
|
#[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(
|
Const::new_error_with_message(
|
||||||
tcx,
|
tcx,
|
||||||
ty,
|
|
||||||
DUMMY_SP,
|
DUMMY_SP,
|
||||||
"ty::ConstKind::Error constructed but no error reported",
|
"ty::ConstKind::Error constructed but no error reported",
|
||||||
)
|
)
|
||||||
|
@ -166,52 +140,33 @@ impl<'tcx> Const<'tcx> {
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn new_error_with_message<S: Into<MultiSpan>>(
|
pub fn new_error_with_message<S: Into<MultiSpan>>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
|
||||||
span: S,
|
span: S,
|
||||||
msg: &'static str,
|
msg: &'static str,
|
||||||
) -> Const<'tcx> {
|
) -> Const<'tcx> {
|
||||||
let reported = tcx.dcx().span_delayed_bug(span, msg);
|
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> {
|
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 {
|
fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst) -> Self {
|
||||||
Const::new_infer(tcx, infer, ty)
|
Const::new_infer(tcx, infer)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_var(tcx: TyCtxt<'tcx>, vid: ty::ConstVid, ty: Ty<'tcx>) -> Self {
|
fn new_var(tcx: TyCtxt<'tcx>, vid: ty::ConstVid) -> Self {
|
||||||
Const::new_var(tcx, vid, ty)
|
Const::new_var(tcx, vid)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_bound(
|
fn new_bound(interner: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
|
||||||
interner: TyCtxt<'tcx>,
|
Const::new_bound(interner, debruijn, var)
|
||||||
debruijn: ty::DebruijnIndex,
|
|
||||||
var: ty::BoundVar,
|
|
||||||
ty: Ty<'tcx>,
|
|
||||||
) -> Self {
|
|
||||||
Const::new_bound(interner, debruijn, var, ty)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_anon_bound(
|
fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
|
||||||
tcx: TyCtxt<'tcx>,
|
Const::new_bound(tcx, debruijn, var)
|
||||||
debruijn: ty::DebruijnIndex,
|
|
||||||
var: ty::BoundVar,
|
|
||||||
ty: Ty<'tcx>,
|
|
||||||
) -> Self {
|
|
||||||
Const::new_bound(tcx, debruijn, var, ty)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_unevaluated(
|
fn new_unevaluated(interner: TyCtxt<'tcx>, uv: ty::UnevaluatedConst<'tcx>) -> Self {
|
||||||
interner: TyCtxt<'tcx>,
|
Const::new_unevaluated(interner, uv)
|
||||||
uv: ty::UnevaluatedConst<'tcx>,
|
|
||||||
ty: Ty<'tcx>,
|
|
||||||
) -> Self {
|
|
||||||
Const::new_unevaluated(interner, uv, ty)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ty(self) -> Ty<'tcx> {
|
|
||||||
self.ty()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,7 +196,6 @@ impl<'tcx> Const<'tcx> {
|
||||||
def: def.to_def_id(),
|
def: def.to_def_id(),
|
||||||
args: GenericArgs::identity_for_item(tcx, 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), .. },
|
&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) {
|
match tcx.named_bound_var(expr.hir_id) {
|
||||||
Some(rbv::ResolvedArg::EarlyBound(_)) => {
|
Some(rbv::ResolvedArg::EarlyBound(_)) => {
|
||||||
// Find the name and index of the const parameter by indexing the generics of
|
// 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 generics = tcx.generics_of(item_def_id);
|
||||||
let index = generics.param_def_id_to_index[&def_id];
|
let index = generics.param_def_id_to_index[&def_id];
|
||||||
let name = tcx.item_name(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(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
|
||||||
Some(ty::Const::new_bound(
|
Some(ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index)))
|
||||||
tcx,
|
|
||||||
debruijn,
|
|
||||||
ty::BoundVar::from_u32(index),
|
|
||||||
param_ty,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
Some(rbv::ResolvedArg::Error(guar)) => {
|
|
||||||
Some(ty::Const::new_error(tcx, guar, param_ty))
|
|
||||||
}
|
}
|
||||||
|
Some(rbv::ResolvedArg::Error(guar)) => Some(ty::Const::new_error(tcx, guar)),
|
||||||
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
|
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -363,7 +307,7 @@ impl<'tcx> Const<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param_env: ParamEnv<'tcx>,
|
param_env: ParamEnv<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<ValTree<'tcx>, ErrorHandled> {
|
) -> Result<(Ty<'tcx>, ValTree<'tcx>), ErrorHandled> {
|
||||||
assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}");
|
assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}");
|
||||||
match self.kind() {
|
match self.kind() {
|
||||||
ConstKind::Unevaluated(unevaluated) => {
|
ConstKind::Unevaluated(unevaluated) => {
|
||||||
|
@ -381,9 +325,9 @@ impl<'tcx> Const<'tcx> {
|
||||||
);
|
);
|
||||||
return Err(e.into());
|
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::Error(g) => Err(g.into()),
|
||||||
ConstKind::Param(_)
|
ConstKind::Param(_)
|
||||||
| ConstKind::Infer(_)
|
| ConstKind::Infer(_)
|
||||||
|
@ -397,8 +341,8 @@ impl<'tcx> Const<'tcx> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn normalize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self {
|
pub fn normalize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self {
|
||||||
match self.eval(tcx, param_env, DUMMY_SP) {
|
match self.eval(tcx, param_env, DUMMY_SP) {
|
||||||
Ok(val) => Self::new_value(tcx, val, self.ty()),
|
Ok((ty, val)) => Self::new_value(tcx, val, ty),
|
||||||
Err(ErrorHandled::Reported(r, _span)) => Self::new_error(tcx, r.into(), self.ty()),
|
Err(ErrorHandled::Reported(r, _span)) => Self::new_error(tcx, r.into()),
|
||||||
Err(ErrorHandled::TooGeneric(_span)) => self,
|
Err(ErrorHandled::TooGeneric(_span)) => self,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -408,8 +352,10 @@ impl<'tcx> Const<'tcx> {
|
||||||
self,
|
self,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
) -> Option<Scalar> {
|
) -> Option<(Ty<'tcx>, Scalar)> {
|
||||||
self.eval(tcx, param_env, DUMMY_SP).ok()?.try_to_scalar()
|
let (ty, val) = self.eval(tcx, param_env, DUMMY_SP).ok()?;
|
||||||
|
let val = val.try_to_scalar()?;
|
||||||
|
Some((ty, val))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -420,8 +366,10 @@ impl<'tcx> Const<'tcx> {
|
||||||
self,
|
self,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param_env: ParamEnv<'tcx>,
|
param_env: ParamEnv<'tcx>,
|
||||||
) -> Option<ScalarInt> {
|
) -> Option<(Ty<'tcx>, ScalarInt)> {
|
||||||
self.try_eval_scalar(tcx, param_env)?.try_to_int().ok()
|
let (ty, scalar) = self.try_eval_scalar(tcx, param_env)?;
|
||||||
|
let val = scalar.try_to_int().ok()?;
|
||||||
|
Some((ty, val))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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
|
/// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it
|
||||||
/// contains const generic parameters or pointers).
|
/// contains const generic parameters or pointers).
|
||||||
pub fn try_eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<u128> {
|
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 (ty, scalar) = self.try_eval_scalar_int(tcx, param_env)?;
|
||||||
let size =
|
let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
|
||||||
tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(self.ty())).ok()?.size;
|
|
||||||
// if `ty` does not depend on generic parameters, use an empty param_env
|
// 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]
|
#[inline]
|
||||||
/// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
|
/// 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 {
|
pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u128 {
|
||||||
self.try_eval_bits(tcx, param_env)
|
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]
|
#[inline]
|
||||||
|
@ -449,12 +396,14 @@ impl<'tcx> Const<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param_env: ParamEnv<'tcx>,
|
param_env: ParamEnv<'tcx>,
|
||||||
) -> Option<u64> {
|
) -> 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]
|
#[inline]
|
||||||
pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> {
|
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]
|
#[inline]
|
||||||
|
@ -467,7 +416,7 @@ impl<'tcx> Const<'tcx> {
|
||||||
/// Panics if self.kind != ty::ConstKind::Value
|
/// Panics if self.kind != ty::ConstKind::Value
|
||||||
pub fn to_valtree(self) -> ty::ValTree<'tcx> {
|
pub fn to_valtree(self) -> ty::ValTree<'tcx> {
|
||||||
match self.kind() {
|
match self.kind() {
|
||||||
ty::ConstKind::Value(valtree) => valtree,
|
ty::ConstKind::Value(_, valtree) => valtree,
|
||||||
_ => bug!("expected ConstKind::Value, got {:?}", self.kind()),
|
_ => bug!("expected ConstKind::Value, got {:?}", self.kind()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -475,7 +424,7 @@ impl<'tcx> Const<'tcx> {
|
||||||
/// Attempts to convert to a `ValTree`
|
/// Attempts to convert to a `ValTree`
|
||||||
pub fn try_to_valtree(self) -> Option<ty::ValTree<'tcx>> {
|
pub fn try_to_valtree(self) -> Option<ty::ValTree<'tcx>> {
|
||||||
match self.kind() {
|
match self.kind() {
|
||||||
ty::ConstKind::Value(valtree) => Some(valtree),
|
ty::ConstKind::Value(_, valtree) => Some(valtree),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,10 +104,12 @@ impl<'tcx> Expr<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
func_ty: Ty<'tcx>,
|
func_ty: Ty<'tcx>,
|
||||||
func_expr: Const<'tcx>,
|
func_expr: Const<'tcx>,
|
||||||
arguments: impl Iterator<Item = Const<'tcx>>,
|
arguments: impl IntoIterator<Item = Const<'tcx>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let args = tcx.mk_args_from_iter::<_, ty::GenericArg<'tcx>>(
|
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 }
|
Self { kind: ExprKind::FunctionCall, args }
|
||||||
|
@ -155,7 +157,7 @@ impl<'tcx> Expr<'tcx> {
|
||||||
Self { kind, args }
|
Self { kind, args }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn args(&self) -> ty::GenericArgsRef<'tcx> {
|
pub fn args(self) -> ty::GenericArgsRef<'tcx> {
|
||||||
self.args
|
self.args
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,10 +28,10 @@ use crate::traits::solve::{
|
||||||
};
|
};
|
||||||
use crate::ty::predicate::ExistentialPredicateStableCmpExt as _;
|
use crate::ty::predicate::ExistentialPredicateStableCmpExt as _;
|
||||||
use crate::ty::{
|
use crate::ty::{
|
||||||
self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, ConstData,
|
self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, GenericParamDefKind,
|
||||||
GenericParamDefKind, ImplPolarity, List, ListWithCachedTypeInfo, ParamConst, ParamTy, Pattern,
|
ImplPolarity, List, ListWithCachedTypeInfo, ParamConst, ParamTy, Pattern, PatternKind,
|
||||||
PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicatePolarity,
|
PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicatePolarity, Region,
|
||||||
Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, Visibility,
|
RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, Visibility,
|
||||||
};
|
};
|
||||||
use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
|
use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
|
||||||
use rustc_ast::{self as ast, attr};
|
use rustc_ast::{self as ast, attr};
|
||||||
|
@ -268,7 +268,7 @@ pub struct CtxtInterners<'tcx> {
|
||||||
clauses: InternedSet<'tcx, ListWithCachedTypeInfo<Clause<'tcx>>>,
|
clauses: InternedSet<'tcx, ListWithCachedTypeInfo<Clause<'tcx>>>,
|
||||||
projs: InternedSet<'tcx, List<ProjectionKind>>,
|
projs: InternedSet<'tcx, List<ProjectionKind>>,
|
||||||
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
|
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>>,
|
pat: InternedSet<'tcx, PatternKind<'tcx>>,
|
||||||
const_allocation: InternedSet<'tcx, Allocation>,
|
const_allocation: InternedSet<'tcx, Allocation>,
|
||||||
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
|
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
|
||||||
|
@ -338,18 +338,18 @@ impl<'tcx> CtxtInterners<'tcx> {
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn intern_const(
|
fn intern_const(
|
||||||
&self,
|
&self,
|
||||||
data: ty::ConstData<'tcx>,
|
kind: ty::ConstKind<'tcx>,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
untracked: &Untracked,
|
untracked: &Untracked,
|
||||||
) -> Const<'tcx> {
|
) -> Const<'tcx> {
|
||||||
Const(Interned::new_unchecked(
|
Const(Interned::new_unchecked(
|
||||||
self.const_
|
self.const_
|
||||||
.intern(data, |data: ConstData<'_>| {
|
.intern(kind, |kind: ty::ConstKind<'_>| {
|
||||||
let flags = super::flags::FlagComputation::for_const(&data.kind, data.ty);
|
let flags = super::flags::FlagComputation::for_const_kind(&kind);
|
||||||
let stable_hash = self.stable_hash(&flags, sess, untracked, &data);
|
let stable_hash = self.stable_hash(&flags, sess, untracked, &kind);
|
||||||
|
|
||||||
InternedInSet(self.arena.alloc(WithCachedTypeInfo {
|
InternedInSet(self.arena.alloc(WithCachedTypeInfo {
|
||||||
internee: data,
|
internee: kind,
|
||||||
stable_hash,
|
stable_hash,
|
||||||
flags: flags.flags,
|
flags: flags.flags,
|
||||||
outer_exclusive_binder: flags.outer_exclusive_binder,
|
outer_exclusive_binder: flags.outer_exclusive_binder,
|
||||||
|
@ -601,18 +601,15 @@ impl<'tcx> CommonConsts<'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
CommonConsts {
|
CommonConsts {
|
||||||
unit: mk_const(ty::ConstData {
|
unit: mk_const(ty::ConstKind::Value(types.unit, ty::ValTree::zst())),
|
||||||
kind: ty::ConstKind::Value(ty::ValTree::zst()),
|
true_: mk_const(ty::ConstKind::Value(
|
||||||
ty: types.unit,
|
types.bool,
|
||||||
}),
|
ty::ValTree::Leaf(ty::ScalarInt::TRUE),
|
||||||
true_: mk_const(ty::ConstData {
|
)),
|
||||||
kind: ty::ConstKind::Value(ty::ValTree::Leaf(ty::ScalarInt::TRUE)),
|
false_: mk_const(ty::ConstKind::Value(
|
||||||
ty: types.bool,
|
types.bool,
|
||||||
}),
|
ty::ValTree::Leaf(ty::ScalarInt::FALSE),
|
||||||
false_: mk_const(ty::ConstData {
|
)),
|
||||||
kind: ty::ConstKind::Value(ty::ValTree::Leaf(ty::ScalarInt::FALSE)),
|
|
||||||
ty: types.bool,
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2225,9 +2222,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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(
|
self.interners.intern_const(
|
||||||
ty::ConstData { kind, ty },
|
kind,
|
||||||
self.sess,
|
self.sess,
|
||||||
// This is only used to create a stable hashing context.
|
// This is only used to create a stable hashing context.
|
||||||
&self.untracked,
|
&self.untracked,
|
||||||
|
@ -2252,14 +2249,10 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
ty::Region::new_early_param(self, param.to_early_bound_region_data()).into()
|
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::Type { .. } => Ty::new_param(self, param.index, param.name).into(),
|
||||||
GenericParamDefKind::Const { .. } => ty::Const::new_param(
|
GenericParamDefKind::Const { .. } => {
|
||||||
self,
|
ty::Const::new_param(self, ParamConst { index: param.index, name: param.name })
|
||||||
ParamConst { index: param.index, name: param.name },
|
.into()
|
||||||
self.type_of(param.def_id)
|
}
|
||||||
.no_bound_vars()
|
|
||||||
.expect("const parameter types cannot be generic"),
|
|
||||||
)
|
|
||||||
.into(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -337,7 +337,7 @@ impl DeepRejectCtxt {
|
||||||
| ty::ConstKind::Error(_) => {
|
| ty::ConstKind::Error(_) => {
|
||||||
return true;
|
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(_) => {
|
ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => {
|
||||||
bug!("unexpected impl arg: {:?}", impl_ct)
|
bug!("unexpected impl arg: {:?}", impl_ct)
|
||||||
}
|
}
|
||||||
|
@ -357,7 +357,7 @@ impl DeepRejectCtxt {
|
||||||
ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => {
|
ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
ty::ConstKind::Value(obl_val) => obl_val == impl_val,
|
ty::ConstKind::Value(_, obl_val) => obl_val == impl_val,
|
||||||
|
|
||||||
ty::ConstKind::Infer(_) => true,
|
ty::ConstKind::Infer(_) => true,
|
||||||
|
|
||||||
|
|
|
@ -28,10 +28,9 @@ impl FlagComputation {
|
||||||
result
|
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();
|
let mut result = FlagComputation::new();
|
||||||
result.add_const_kind(c);
|
result.add_const_kind(kind);
|
||||||
result.add_ty(t);
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,7 +372,7 @@ impl FlagComputation {
|
||||||
self.add_flags(TypeFlags::HAS_CT_PLACEHOLDER);
|
self.add_flags(TypeFlags::HAS_CT_PLACEHOLDER);
|
||||||
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
|
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::Expr(e) => self.add_args(e.args()),
|
||||||
ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_ERROR),
|
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> {
|
pub trait BoundVarReplacerDelegate<'tcx> {
|
||||||
fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx>;
|
fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx>;
|
||||||
fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'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 struct FnMutDelegate<'a, 'tcx> {
|
||||||
pub regions: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a),
|
pub regions: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a),
|
||||||
pub types: &'a mut (dyn FnMut(ty::BoundTy) -> Ty<'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> {
|
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> {
|
fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> {
|
||||||
(self.types)(bt)
|
(self.types)(bt)
|
||||||
}
|
}
|
||||||
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.consts)(bv, ty)
|
(self.consts)(bv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,7 +224,7 @@ where
|
||||||
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
||||||
match ct.kind() {
|
match ct.kind() {
|
||||||
ty::ConstKind::Bound(debruijn, bound_const) if debruijn == self.current_index => {
|
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));
|
debug_assert!(!ct.has_vars_bound_above(ty::INNERMOST));
|
||||||
ty::fold::shift_vars(self.tcx, ct, self.current_index.as_u32())
|
ty::fold::shift_vars(self.tcx, ct, self.current_index.as_u32())
|
||||||
}
|
}
|
||||||
|
@ -282,7 +282,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
let delegate = FnMutDelegate {
|
let delegate = FnMutDelegate {
|
||||||
regions: &mut replace_regions,
|
regions: &mut replace_regions,
|
||||||
types: &mut |b| bug!("unexpected bound ty in binder: {b:?}"),
|
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);
|
let mut replacer = BoundVarReplacer::new(self, delegate);
|
||||||
value.fold_with(&mut replacer)
|
value.fold_with(&mut replacer)
|
||||||
|
@ -353,9 +353,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
ty::BoundTy { var: shift_bv(t.var), kind: t.kind },
|
ty::BoundTy { var: shift_bv(t.var), kind: t.kind },
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
consts: &mut |c, ty: Ty<'tcx>| {
|
consts: &mut |c| ty::Const::new_bound(self, ty::INNERMOST, shift_bv(c)),
|
||||||
ty::Const::new_bound(self, ty::INNERMOST, shift_bv(c), ty)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -398,12 +396,12 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
.expect_ty();
|
.expect_ty();
|
||||||
Ty::new_bound(self.tcx, ty::INNERMOST, BoundTy { var, kind })
|
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 entry = self.map.entry(bv);
|
||||||
let index = entry.index();
|
let index = entry.index();
|
||||||
let var = ty::BoundVar::from_usize(index);
|
let var = ty::BoundVar::from_usize(index);
|
||||||
let () = entry.or_insert_with(|| ty::BoundVariableKind::Const).expect_const();
|
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(),
|
ptr.cast::<WithCachedTypeInfo<ty::TyKind<'tcx>>>().as_ref(),
|
||||||
))),
|
))),
|
||||||
CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked(
|
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(),
|
_ => intrinsics::unreachable(),
|
||||||
}
|
}
|
||||||
|
@ -454,11 +454,11 @@ impl<'tcx> GenericArgs<'tcx> {
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
original_args: &[GenericArg<'tcx>],
|
original_args: &[GenericArg<'tcx>],
|
||||||
) -> GenericArgsRef<'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) {
|
if let Some(arg) = original_args.get(def.index as usize) {
|
||||||
*arg
|
*arg
|
||||||
} else {
|
} else {
|
||||||
def.to_error(tcx, args)
|
def.to_error(tcx)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,19 +100,11 @@ impl GenericParamDef {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_error<'tcx>(
|
pub fn to_error<'tcx>(&self, tcx: TyCtxt<'tcx>) -> ty::GenericArg<'tcx> {
|
||||||
&self,
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
preceding_args: &[ty::GenericArg<'tcx>],
|
|
||||||
) -> ty::GenericArg<'tcx> {
|
|
||||||
match &self.kind {
|
match &self.kind {
|
||||||
ty::GenericParamDefKind::Lifetime => ty::Region::new_error_misc(tcx).into(),
|
ty::GenericParamDefKind::Lifetime => ty::Region::new_error_misc(tcx).into(),
|
||||||
ty::GenericParamDefKind::Type { .. } => Ty::new_misc_error(tcx).into(),
|
ty::GenericParamDefKind::Type { .. } => Ty::new_misc_error(tcx).into(),
|
||||||
ty::GenericParamDefKind::Const { .. } => ty::Const::new_misc_error(
|
ty::GenericParamDefKind::Const { .. } => ty::Const::new_misc_error(tcx).into(),
|
||||||
tcx,
|
|
||||||
tcx.type_of(self.def_id).instantiate(tcx, preceding_args),
|
|
||||||
)
|
|
||||||
.into(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -385,9 +385,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::Array(inner, len)
|
ty::Array(inner, len) if tcx.features().transmute_generic_consts => {
|
||||||
if len.ty() == tcx.types.usize && tcx.features().transmute_generic_consts =>
|
|
||||||
{
|
|
||||||
let len_eval = len.try_eval_target_usize(tcx, param_env);
|
let len_eval = len.try_eval_target_usize(tcx, param_env);
|
||||||
if len_eval == Some(0) {
|
if len_eval == Some(0) {
|
||||||
return Ok(SizeSkeleton::Known(Size::from_bytes(0)));
|
return Ok(SizeSkeleton::Known(Size::from_bytes(0)));
|
||||||
|
|
|
@ -87,7 +87,7 @@ pub use self::closure::{
|
||||||
CAPTURE_STRUCT_LOCAL,
|
CAPTURE_STRUCT_LOCAL,
|
||||||
};
|
};
|
||||||
pub use self::consts::{
|
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::{
|
pub use self::context::{
|
||||||
tls, CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift,
|
tls, CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift,
|
||||||
|
@ -617,7 +617,7 @@ impl<'tcx> Term<'tcx> {
|
||||||
ptr.cast::<WithCachedTypeInfo<ty::TyKind<'tcx>>>().as_ref(),
|
ptr.cast::<WithCachedTypeInfo<ty::TyKind<'tcx>>>().as_ref(),
|
||||||
))),
|
))),
|
||||||
CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked(
|
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(),
|
_ => core::intrinsics::unreachable(),
|
||||||
}
|
}
|
||||||
|
@ -934,6 +934,30 @@ pub struct Placeholder<T> {
|
||||||
pub universe: UniverseIndex,
|
pub universe: UniverseIndex,
|
||||||
pub bound: T,
|
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>;
|
pub type PlaceholderRegion = Placeholder<BoundRegion>;
|
||||||
|
|
||||||
|
|
|
@ -216,7 +216,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
|
||||||
})
|
})
|
||||||
.emit_unless(self.ignore_errors);
|
.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(());
|
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() {
|
match ct.kind() {
|
||||||
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) => {
|
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) => {
|
||||||
match self.tcx().def_kind(def) {
|
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) => {
|
ty::InferConst::Var(ct_vid) if let Some(name) = self.const_infer_name(ct_vid) => {
|
||||||
p!(write("{}", name))
|
p!(write("{}", name))
|
||||||
}
|
}
|
||||||
_ => print_underscore!(),
|
_ => write!(self, "_")?,
|
||||||
},
|
},
|
||||||
ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)),
|
ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)),
|
||||||
ty::ConstKind::Value(value) => {
|
ty::ConstKind::Value(ty, value) => {
|
||||||
return self.pretty_print_const_valtree(value, ct.ty(), print_ty);
|
return self.pretty_print_const_valtree(value, ty, print_ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::ConstKind::Bound(debruijn, bound_var) => {
|
ty::ConstKind::Bound(debruijn, bound_var) => {
|
||||||
|
@ -1666,7 +1649,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||||
ty::Ref(_, inner, _) => {
|
ty::Ref(_, inner, _) => {
|
||||||
if let ty::Array(elem, len) = inner.kind() {
|
if let ty::Array(elem, len) = inner.kind() {
|
||||||
if let ty::Uint(ty::UintTy::U8) = elem.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()) {
|
match self.tcx().try_get_global_alloc(prov.alloc_id()) {
|
||||||
Some(GlobalAlloc::Memory(alloc)) => {
|
Some(GlobalAlloc::Memory(alloc)) => {
|
||||||
let len = int.assert_bits(self.tcx().data_layout.pointer_size);
|
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
|
true
|
||||||
}
|
}
|
||||||
(ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2,
|
(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`
|
// 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
|
// and is the better alternative to waiting until `generic_const_exprs` can
|
||||||
// be stabilized.
|
// be stabilized.
|
||||||
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.def == bu.def => {
|
(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(
|
let args = relation.relate_with_variance(
|
||||||
ty::Variance::Invariant,
|
ty::Variance::Invariant,
|
||||||
ty::VarianceDiagInfo::default(),
|
ty::VarianceDiagInfo::default(),
|
||||||
au.args,
|
au.args,
|
||||||
bu.args,
|
bu.args,
|
||||||
)?;
|
)?;
|
||||||
return Ok(ty::Const::new_unevaluated(
|
return Ok(ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst { def: au.def, args }));
|
||||||
tcx,
|
|
||||||
ty::UnevaluatedConst { def: au.def, args },
|
|
||||||
a.ty(),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
(ty::ConstKind::Expr(ae), ty::ConstKind::Expr(be)) => {
|
(ty::ConstKind::Expr(ae), ty::ConstKind::Expr(be)) => {
|
||||||
match (ae.kind, be.kind) {
|
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())?;
|
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,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
|
@ -201,26 +201,21 @@ impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::Const<'tcx> {
|
||||||
f: &mut core::fmt::Formatter<'_>,
|
f: &mut core::fmt::Formatter<'_>,
|
||||||
) -> core::fmt::Result {
|
) -> core::fmt::Result {
|
||||||
// If this is a value, we spend some effort to make it look nice.
|
// 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| {
|
return ty::tls::with(move |tcx| {
|
||||||
// Somehow trying to lift the valtree results in lifetime errors, so we lift the
|
// Somehow trying to lift the valtree results in lifetime errors, so we lift the
|
||||||
// entire constant.
|
// entire constant.
|
||||||
let lifted = tcx.lift(*this.data).unwrap();
|
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")
|
bug!("we checked that this is a valtree")
|
||||||
};
|
};
|
||||||
let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
|
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())
|
f.write_str(&cx.into_buffer())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Fall back to something verbose.
|
// Fall back to something verbose.
|
||||||
write!(
|
write!(f, "{kind:?}", kind = &this.map(|data| data.kind()))
|
||||||
f,
|
|
||||||
"{kind:?}: {ty:?}",
|
|
||||||
ty = &this.map(|data| data.ty()),
|
|
||||||
kind = &this.map(|data| data.kind())
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -647,7 +642,6 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> {
|
||||||
self,
|
self,
|
||||||
folder: &mut F,
|
folder: &mut F,
|
||||||
) -> Result<Self, F::Error> {
|
) -> Result<Self, F::Error> {
|
||||||
let ty = self.ty().try_fold_with(folder)?;
|
|
||||||
let kind = match self.kind() {
|
let kind = match self.kind() {
|
||||||
ConstKind::Param(p) => ConstKind::Param(p.try_fold_with(folder)?),
|
ConstKind::Param(p) => ConstKind::Param(p.try_fold_with(folder)?),
|
||||||
ConstKind::Infer(i) => ConstKind::Infer(i.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::Placeholder(p) => ConstKind::Placeholder(p.try_fold_with(folder)?),
|
||||||
ConstKind::Unevaluated(uv) => ConstKind::Unevaluated(uv.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::Error(e) => ConstKind::Error(e.try_fold_with(folder)?),
|
||||||
ConstKind::Expr(e) => ConstKind::Expr(e.try_fold_with(folder)?),
|
ConstKind::Expr(e) => ConstKind::Expr(e.try_fold_with(folder)?),
|
||||||
};
|
};
|
||||||
if ty != self.ty() || kind != self.kind() {
|
if kind != self.kind() { Ok(folder.interner().mk_ct_from_kind(kind)) } else { Ok(self) }
|
||||||
Ok(folder.interner().mk_ct_from_kind(kind, ty))
|
|
||||||
} else {
|
|
||||||
Ok(self)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> {
|
impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> {
|
||||||
fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
|
fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
|
||||||
try_visit!(self.ty().visit_with(visitor));
|
|
||||||
match self.kind() {
|
match self.kind() {
|
||||||
ConstKind::Param(p) => p.visit_with(visitor),
|
ConstKind::Param(p) => p.visit_with(visitor),
|
||||||
ConstKind::Infer(i) => i.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::Placeholder(p) => p.visit_with(visitor),
|
||||||
ConstKind::Unevaluated(uv) => uv.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::Error(e) => e.visit_with(visitor),
|
||||||
ConstKind::Expr(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_span::{Span, DUMMY_SP};
|
||||||
use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
|
use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
|
||||||
use rustc_target::spec::abi;
|
use rustc_target::spec::abi;
|
||||||
|
use rustc_type_ir::visit::TypeVisitableExt;
|
||||||
use std::assert_matches::debug_assert_matches;
|
use std::assert_matches::debug_assert_matches;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
@ -339,6 +340,27 @@ impl ParamConst {
|
||||||
pub fn for_def(def: &ty::GenericParamDef) -> ParamConst {
|
pub fn for_def(def: &ty::GenericParamDef) -> ParamConst {
|
||||||
ParamConst::new(def.index, def.name)
|
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)]
|
#[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::Lifetime(_) => {}
|
||||||
GenericArgKind::Const(parent_ct) => {
|
GenericArgKind::Const(parent_ct) => match parent_ct.kind() {
|
||||||
stack.push(parent_ct.ty().into());
|
ty::ConstKind::Infer(_)
|
||||||
match parent_ct.kind() {
|
| ty::ConstKind::Param(_)
|
||||||
ty::ConstKind::Infer(_)
|
| ty::ConstKind::Placeholder(_)
|
||||||
| ty::ConstKind::Param(_)
|
| ty::ConstKind::Bound(..)
|
||||||
| ty::ConstKind::Placeholder(_)
|
| ty::ConstKind::Error(_) => {}
|
||||||
| ty::ConstKind::Bound(..)
|
|
||||||
| ty::ConstKind::Value(_)
|
|
||||||
| ty::ConstKind::Error(_) => {}
|
|
||||||
|
|
||||||
ty::ConstKind::Expr(expr) => stack.extend(expr.args().iter().rev()),
|
ty::ConstKind::Value(ty, _) => stack.push(ty.into()),
|
||||||
ty::ConstKind::Unevaluated(ct) => {
|
|
||||||
stack.extend(ct.args.iter().rev());
|
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::mir::*;
|
||||||
use rustc_middle::thir::*;
|
use rustc_middle::thir::*;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, CanonicalUserType, CanonicalUserTypeAnnotation, TyCtxt, UserTypeAnnotationIndex,
|
self, CanonicalUserType, CanonicalUserTypeAnnotation, Ty, TyCtxt, UserTypeAnnotationIndex,
|
||||||
};
|
};
|
||||||
use rustc_middle::{bug, span_bug};
|
use rustc_middle::{bug, span_bug};
|
||||||
use rustc_target::abi::Size;
|
use rustc_target::abi::Size;
|
||||||
|
@ -51,7 +51,7 @@ pub(crate) fn as_constant_inner<'tcx>(
|
||||||
{
|
{
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(LitToConstError::Reported(guar)) => {
|
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) => {
|
Err(LitToConstError::TypeError) => {
|
||||||
bug!("encountered type error in `lit_to_mir_constant`")
|
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_ }
|
ConstOperand { user_ty, span, const_ }
|
||||||
}
|
}
|
||||||
ExprKind::ConstParam { param, def_id: _ } => {
|
ExprKind::ConstParam { param, def_id: _ } => {
|
||||||
let const_param = ty::Const::new_param(tcx, param, expr.ty);
|
let const_param = ty::Const::new_param(tcx, param);
|
||||||
let const_ = Const::Ty(const_param);
|
let const_ = Const::Ty(expr.ty, const_param);
|
||||||
|
|
||||||
ConstOperand { user_ty: None, span, const_ }
|
ConstOperand { user_ty: None, span, const_ }
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,9 +101,9 @@ impl<'tcx> ConstToPat<'tcx> {
|
||||||
// level of indirection can be eliminated
|
// level of indirection can be eliminated
|
||||||
|
|
||||||
let have_valtree =
|
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 {
|
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::Param(_)
|
||||||
| ty::ConstKind::Infer(_)
|
| ty::ConstKind::Infer(_)
|
||||||
| ty::ConstKind::Bound(_, _)
|
| ty::ConstKind::Bound(_, _)
|
||||||
|
@ -113,8 +113,8 @@ impl<'tcx> ConstToPat<'tcx> {
|
||||||
| ty::ConstKind::Expr(_) => {
|
| ty::ConstKind::Expr(_) => {
|
||||||
span_bug!(self.span, "unexpected const in `to_pat`: {:?}", c.kind())
|
span_bug!(self.span, "unexpected const in `to_pat`: {:?}", c.kind())
|
||||||
}
|
}
|
||||||
ty::ConstKind::Value(valtree) => {
|
ty::ConstKind::Value(ty, valtree) => {
|
||||||
self.recur(valtree, cv.ty()).unwrap_or_else(|_: FallbackToOpaqueConst| {
|
self.recur(valtree, ty).unwrap_or_else(|_: FallbackToOpaqueConst| {
|
||||||
Box::new(Pat {
|
Box::new(Pat {
|
||||||
span: self.span,
|
span: self.span,
|
||||||
ty: cv.ty(),
|
ty: cv.ty(),
|
||||||
|
@ -336,9 +336,9 @@ impl<'tcx> ConstToPat<'tcx> {
|
||||||
ty::Ref(_, pointee_ty, ..) => match *pointee_ty.kind() {
|
ty::Ref(_, pointee_ty, ..) => match *pointee_ty.kind() {
|
||||||
// `&str` is represented as a valtree, let's keep using this
|
// `&str` is represented as a valtree, let's keep using this
|
||||||
// optimization for now.
|
// optimization for now.
|
||||||
ty::Str => {
|
ty::Str => PatKind::Constant {
|
||||||
PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) }
|
value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)),
|
||||||
}
|
},
|
||||||
// All other references are converted into deref patterns and then recursively
|
// 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
|
// convert the dereferenced constant to a pattern that is the sub-pattern of the
|
||||||
// deref pattern.
|
// deref pattern.
|
||||||
|
@ -382,13 +382,15 @@ impl<'tcx> ConstToPat<'tcx> {
|
||||||
self.saw_const_match_error.set(Some(e));
|
self.saw_const_match_error.set(Some(e));
|
||||||
return Err(FallbackToOpaqueConst);
|
return Err(FallbackToOpaqueConst);
|
||||||
} else {
|
} 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(..) => {
|
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
|
// The raw pointers we see here have been "vetted" by valtree construction to be
|
||||||
// just integers, so we simply allow them.
|
// 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(..) => {
|
ty::FnPtr(..) => {
|
||||||
unreachable!(
|
unreachable!(
|
||||||
|
|
|
@ -580,7 +580,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||||
.tcx
|
.tcx
|
||||||
.const_eval_global_id_for_typeck(param_env_reveal_all, cid, span)
|
.const_eval_global_id_for_typeck(param_env_reveal_all, cid, span)
|
||||||
.map(|val| match val {
|
.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(
|
None => mir::Const::Val(
|
||||||
self.tcx
|
self.tcx
|
||||||
.const_eval_global_id(param_env_reveal_all, cid, span)
|
.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 {
|
if let Some(lit_input) = lit_input {
|
||||||
match tcx.at(expr.span).lit_to_const(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
|
// If an error occurred, ignore that it's a literal
|
||||||
// and leave reporting the error up to const eval of
|
// and leave reporting the error up to const eval of
|
||||||
// the unevaluated constant below.
|
// 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.
|
// 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)
|
if let Ok(Some(valtree)) = self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, span)
|
||||||
{
|
{
|
||||||
let subpattern =
|
let subpattern = self.const_to_pat(
|
||||||
self.const_to_pat(Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)), id, span);
|
Const::Ty(ty, ty::Const::new_value(self.tcx, valtree, ty)),
|
||||||
|
id,
|
||||||
|
span,
|
||||||
|
);
|
||||||
PatKind::InlineConstant { subpattern, def: def_id }
|
PatKind::InlineConstant { subpattern, def: def_id }
|
||||||
} else {
|
} else {
|
||||||
// If that fails, convert it to an opaque constant pattern.
|
// 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),
|
_ => span_bug!(expr.span, "not a literal: {:?}", expr),
|
||||||
};
|
};
|
||||||
|
|
||||||
let lit_input =
|
let ct_ty = self.typeck_results.expr_ty(expr);
|
||||||
LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg };
|
let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg };
|
||||||
match self.tcx.at(expr.span).lit_to_const(lit_input) {
|
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::Reported(e)) => PatKind::Error(e),
|
||||||
Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"),
|
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 operand_ty = operand.ty(self.local_decls, self.tcx)
|
||||||
&& let Some(operand_ty) = operand_ty.builtin_deref(true)
|
&& let Some(operand_ty) = operand_ty.builtin_deref(true)
|
||||||
&& let ty::Array(_, len) = operand_ty.kind()
|
&& 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());
|
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) => {
|
Rvalue::Len(place) => {
|
||||||
let place_ty = place.ty(self.local_decls, self.tcx);
|
let place_ty = place.ty(self.local_decls, self.tcx);
|
||||||
if let ty::Array(_, len) = place_ty.ty.kind() {
|
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)
|
.try_eval_scalar(self.tcx, self.param_env)
|
||||||
.map_or(FlatSet::Top, FlatSet::Elem)
|
.map_or(FlatSet::Top, FlatSet::Elem)
|
||||||
} else if let [ProjectionElem::Deref] = place.projection[..] {
|
} 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.
|
// Trivial case: we are fetching a statically known length.
|
||||||
let place_ty = place.ty(self.local_decls, self.tcx).ty;
|
let place_ty = place.ty(self.local_decls, self.tcx).ty;
|
||||||
if let ty::Array(_, len) = place_ty.kind() {
|
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)?;
|
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 Some(to) = to.builtin_deref(true)
|
||||||
&& let ty::Slice(..) = to.kind()
|
&& 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`.
|
// Fallback: a symbolic `Len`.
|
||||||
|
|
|
@ -150,7 +150,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
|
||||||
return;
|
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 };
|
let constant = ConstOperand { span: source_info.span, const_, user_ty: None };
|
||||||
*rvalue = Rvalue::Use(Operand::Constant(Box::new(constant)));
|
*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 {
|
*rvalue = Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
|
||||||
span: rustc_span::DUMMY_SP,
|
span: rustc_span::DUMMY_SP,
|
||||||
user_ty: None,
|
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);
|
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) {
|
fn visit_constant(&mut self, ct: &mir::ConstOperand<'tcx>, location: Location) {
|
||||||
match ct.const_ {
|
match ct.const_ {
|
||||||
mir::Const::Ty(c) => {
|
mir::Const::Ty(_, c) => {
|
||||||
c.visit_with(self);
|
c.visit_with(self);
|
||||||
}
|
}
|
||||||
mir::Const::Unevaluated(mir::UnevaluatedConst { def, args: _, promoted }, ty) => {
|
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 {
|
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() {
|
let kind = match c.kind() {
|
||||||
ty::ConstKind::Infer(i) => match i {
|
ty::ConstKind::Infer(i) => match i {
|
||||||
ty::InferConst::Var(vid) => {
|
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!(
|
assert_eq!(
|
||||||
self.infcx.opportunistic_resolve_ct_var(vid, ty).kind(),
|
self.infcx.opportunistic_resolve_ct_var(vid),
|
||||||
c.kind(),
|
c,
|
||||||
"region vid should have been resolved fully before canonicalization"
|
"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::EffectVar(_) => CanonicalVarKind::Effect,
|
||||||
ty::InferConst::Fresh(_) => todo!(),
|
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 {
|
ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode {
|
||||||
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
|
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
|
||||||
PlaceholderLike::new(placeholder.universe(), self.variables.len().into()),
|
PlaceholderLike::new(placeholder.universe(), self.variables.len().into()),
|
||||||
ty,
|
|
||||||
),
|
),
|
||||||
CanonicalizeMode::Response { .. } => {
|
CanonicalizeMode::Response { .. } => {
|
||||||
CanonicalVarKind::PlaceholderConst(placeholder, ty)
|
CanonicalVarKind::PlaceholderConst(placeholder)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ty::ConstKind::Param(_) => match self.canonicalize_mode {
|
ty::ConstKind::Param(_) => match self.canonicalize_mode {
|
||||||
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
|
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
|
||||||
PlaceholderLike::new(ty::UniverseIndex::ROOT, self.variables.len().into()),
|
PlaceholderLike::new(ty::UniverseIndex::ROOT, self.variables.len().into()),
|
||||||
ty,
|
|
||||||
),
|
),
|
||||||
CanonicalizeMode::Response { .. } => panic!("param ty in response: {c:?}"),
|
CanonicalizeMode::Response { .. } => panic!("param ty in response: {c:?}"),
|
||||||
},
|
},
|
||||||
// FIXME: See comment above -- we could fold the region separately or something.
|
// FIXME: See comment above -- we could fold the region separately or something.
|
||||||
ty::ConstKind::Bound(_, _)
|
ty::ConstKind::Bound(_, _)
|
||||||
| ty::ConstKind::Unevaluated(_)
|
| ty::ConstKind::Unevaluated(_)
|
||||||
| ty::ConstKind::Value(_)
|
| ty::ConstKind::Value(_, _)
|
||||||
| ty::ConstKind::Error(_)
|
| ty::ConstKind::Error(_)
|
||||||
| ty::ConstKind::Expr(_) => return c.super_fold_with(self),
|
| 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)
|
Const::new_anon_bound(self.interner(), self.binder_index, var)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
fn fold_const(&mut self, c: I::Const) -> I::Const {
|
||||||
match c.kind() {
|
match c.kind() {
|
||||||
ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
|
ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
|
||||||
let ty = c.ty().fold_with(self);
|
let resolved = self.infcx.opportunistic_resolve_ct_var(vid);
|
||||||
let resolved = self.infcx.opportunistic_resolve_ct_var(vid, ty);
|
|
||||||
if c != resolved && resolved.has_infer() {
|
if c != resolved && resolved.has_infer() {
|
||||||
resolved.fold_with(self)
|
resolved.fold_with(self)
|
||||||
} else {
|
} else {
|
||||||
|
@ -67,9 +66,7 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I> for EagerRes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)) => {
|
ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)) => {
|
||||||
let bool = Ty::new_bool(self.infcx.interner());
|
self.infcx.opportunistic_resolve_effect_var(vid)
|
||||||
debug_assert_eq!(c.ty(), bool);
|
|
||||||
self.infcx.opportunistic_resolve_effect_var(vid, bool)
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if c.has_infer() {
|
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
|
// this). We show this to the user as `usize::MAX..` which is slightly incorrect but
|
||||||
// probably clear enough.
|
// probably clear enough.
|
||||||
let c = ty.numeric_max_val(cx.tcx).unwrap();
|
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);
|
lo = PatRangeBoundary::Finite(value);
|
||||||
}
|
}
|
||||||
let hi = if let Some(hi) = range.hi.minus_one() {
|
let hi = if let Some(hi) = range.hi.minus_one() {
|
||||||
|
|
|
@ -68,6 +68,8 @@ fn compress<'tcx>(
|
||||||
fn encode_args<'tcx>(
|
fn encode_args<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
args: GenericArgsRef<'tcx>,
|
args: GenericArgsRef<'tcx>,
|
||||||
|
for_def: DefId,
|
||||||
|
has_erased_self: bool,
|
||||||
dict: &mut FxHashMap<DictKey<'tcx>, usize>,
|
dict: &mut FxHashMap<DictKey<'tcx>, usize>,
|
||||||
options: EncodeTyOptions,
|
options: EncodeTyOptions,
|
||||||
) -> String {
|
) -> String {
|
||||||
|
@ -76,7 +78,8 @@ fn encode_args<'tcx>(
|
||||||
let args: Vec<GenericArg<'_>> = args.iter().collect();
|
let args: Vec<GenericArg<'_>> = args.iter().collect();
|
||||||
if !args.is_empty() {
|
if !args.is_empty() {
|
||||||
s.push('I');
|
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() {
|
match arg.unpack() {
|
||||||
GenericArgKind::Lifetime(region) => {
|
GenericArgKind::Lifetime(region) => {
|
||||||
s.push_str(&encode_region(region, dict));
|
s.push_str(&encode_region(region, dict));
|
||||||
|
@ -85,7 +88,10 @@ fn encode_args<'tcx>(
|
||||||
s.push_str(&encode_ty(tcx, ty, dict, options));
|
s.push_str(&encode_ty(tcx, ty, dict, options));
|
||||||
}
|
}
|
||||||
GenericArgKind::Const(c) => {
|
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>(
|
fn encode_const<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
c: Const<'tcx>,
|
c: Const<'tcx>,
|
||||||
|
ct_ty: Ty<'tcx>,
|
||||||
dict: &mut FxHashMap<DictKey<'tcx>, usize>,
|
dict: &mut FxHashMap<DictKey<'tcx>, usize>,
|
||||||
options: EncodeTyOptions,
|
options: EncodeTyOptions,
|
||||||
) -> String {
|
) -> String {
|
||||||
|
@ -111,20 +118,20 @@ fn encode_const<'tcx>(
|
||||||
// L<element-type>E as literal argument
|
// L<element-type>E as literal argument
|
||||||
|
|
||||||
// Element type
|
// Element type
|
||||||
s.push_str(&encode_ty(tcx, c.ty(), dict, options));
|
s.push_str(&encode_ty(tcx, ct_ty, dict, options));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Literal arguments
|
// Literal arguments
|
||||||
ty::ConstKind::Value(..) => {
|
ty::ConstKind::Value(ct_ty, ..) => {
|
||||||
// L<element-type>[n]<element-value>E as literal argument
|
// L<element-type>[n]<element-value>E as literal argument
|
||||||
|
|
||||||
// Element type
|
// 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,
|
// The only allowed types of const values are bool, u8, u16, u32,
|
||||||
// u64, u128, usize i8, i16, i32, i64, i128, isize, and char. The
|
// u64, u128, usize i8, i16, i32, i64, i128, isize, and char. The
|
||||||
// bool value false is encoded as 0 and true as 1.
|
// bool value false is encoded as 0 and true as 1.
|
||||||
match c.ty().kind() {
|
match ct_ty.kind() {
|
||||||
ty::Int(ity) => {
|
ty::Int(ity) => {
|
||||||
let bits = c.eval_bits(tcx, ty::ParamEnv::reveal_all());
|
let bits = c.eval_bits(tcx, ty::ParamEnv::reveal_all());
|
||||||
let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
|
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}");
|
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) => {
|
ty::ExistentialPredicate::Trait(trait_ref) => {
|
||||||
let name = encode_ty_name(tcx, trait_ref.def_id);
|
let name = encode_ty_name(tcx, trait_ref.def_id);
|
||||||
let _ = write!(s, "u{}{}", name.len(), &name);
|
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) => {
|
ty::ExistentialPredicate::Projection(projection) => {
|
||||||
let name = encode_ty_name(tcx, projection.def_id);
|
let name = encode_ty_name(tcx, projection.def_id);
|
||||||
let _ = write!(s, "u{}{}", name.len(), &name);
|
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() {
|
match projection.term.unpack() {
|
||||||
TermKind::Ty(ty) => s.push_str(&encode_ty(tcx, ty, dict, options)),
|
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) => {
|
ty::ExistentialPredicate::AutoTrait(def_id) => {
|
||||||
|
@ -485,7 +498,7 @@ pub fn encode_ty<'tcx>(
|
||||||
// <subst>, as vendor extended type.
|
// <subst>, as vendor extended type.
|
||||||
let name = encode_ty_name(tcx, def_id);
|
let name = encode_ty_name(tcx, def_id);
|
||||||
let _ = write!(s, "u{}{}", name.len(), &name);
|
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);
|
compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
|
||||||
}
|
}
|
||||||
typeid.push_str(&s);
|
typeid.push_str(&s);
|
||||||
|
@ -529,7 +542,7 @@ pub fn encode_ty<'tcx>(
|
||||||
let mut s = String::new();
|
let mut s = String::new();
|
||||||
let name = encode_ty_name(tcx, *def_id);
|
let name = encode_ty_name(tcx, *def_id);
|
||||||
let _ = write!(s, "u{}{}", name.len(), &name);
|
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);
|
compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
|
||||||
typeid.push_str(&s);
|
typeid.push_str(&s);
|
||||||
}
|
}
|
||||||
|
@ -541,7 +554,7 @@ pub fn encode_ty<'tcx>(
|
||||||
let name = encode_ty_name(tcx, *def_id);
|
let name = encode_ty_name(tcx, *def_id);
|
||||||
let _ = write!(s, "u{}{}", name.len(), &name);
|
let _ = write!(s, "u{}{}", name.len(), &name);
|
||||||
let parent_args = tcx.mk_args(args.as_coroutine_closure().parent_args());
|
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);
|
compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
|
||||||
typeid.push_str(&s);
|
typeid.push_str(&s);
|
||||||
}
|
}
|
||||||
|
@ -556,6 +569,8 @@ pub fn encode_ty<'tcx>(
|
||||||
s.push_str(&encode_args(
|
s.push_str(&encode_args(
|
||||||
tcx,
|
tcx,
|
||||||
tcx.mk_args(args.as_coroutine().parent_args()),
|
tcx.mk_args(args.as_coroutine().parent_args()),
|
||||||
|
*def_id,
|
||||||
|
false,
|
||||||
dict,
|
dict,
|
||||||
options,
|
options,
|
||||||
));
|
));
|
||||||
|
|
|
@ -251,7 +251,9 @@ impl RustcInternal for MirConst {
|
||||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||||
let constant = tables.mir_consts[self.id];
|
let constant = tables.mir_consts[self.id];
|
||||||
match constant {
|
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(uneval, ty) => {
|
||||||
rustc_middle::mir::Const::Unevaluated(
|
rustc_middle::mir::Const::Unevaluated(
|
||||||
tcx.lift(uneval).unwrap(),
|
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 {
|
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 {
|
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||||
let id = tables.intern_mir_const(tables.tcx.lift(*self).unwrap());
|
let id = tables.intern_mir_const(tables.tcx.lift(*self).unwrap());
|
||||||
match *self {
|
match *self {
|
||||||
mir::Const::Ty(c) => MirConst::new(
|
mir::Const::Ty(ty, c) => MirConst::new(
|
||||||
stable_mir::ty::ConstantKind::Ty(c.stable(tables)),
|
stable_mir::ty::ConstantKind::Ty(c.stable(tables)),
|
||||||
c.ty().stable(tables),
|
ty.stable(tables),
|
||||||
id,
|
id,
|
||||||
),
|
),
|
||||||
mir::Const::Unevaluated(unev_const, ty) => {
|
mir::Const::Unevaluated(unev_const, ty) => {
|
||||||
|
|
|
@ -415,7 +415,7 @@ pub fn mir_const_from_ty_const<'tcx>(
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
) -> stable_mir::ty::MirConst {
|
) -> stable_mir::ty::MirConst {
|
||||||
let kind = match ty_const.kind() {
|
let kind = match ty_const.kind() {
|
||||||
ty::Value(val) => {
|
ty::Value(ty, val) => {
|
||||||
let val = match val {
|
let val = match val {
|
||||||
ty::ValTree::Leaf(scalar) => ty::ValTree::Leaf(scalar),
|
ty::ValTree::Leaf(scalar) => ty::ValTree::Leaf(scalar),
|
||||||
ty::ValTree::Branch(branch) => {
|
ty::ValTree::Branch(branch) => {
|
||||||
|
@ -447,7 +447,7 @@ pub fn mir_const_from_ty_const<'tcx>(
|
||||||
ty::ExprCt(_) => unimplemented!(),
|
ty::ExprCt(_) => unimplemented!(),
|
||||||
};
|
};
|
||||||
let stable_ty = tables.intern_ty(ty);
|
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)
|
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 {
|
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||||
let kind = match self.kind() {
|
let kind = match self.kind() {
|
||||||
ty::Value(val) => {
|
ty::Value(ty, val) => {
|
||||||
let val = match val {
|
let val = match val {
|
||||||
ty::ValTree::Leaf(scalar) => ty::ValTree::Leaf(scalar),
|
ty::ValTree::Leaf(scalar) => ty::ValTree::Leaf(scalar),
|
||||||
ty::ValTree::Branch(branch) => {
|
ty::ValTree::Branch(branch) => {
|
||||||
ty::ValTree::Branch(tables.tcx.lift(branch).unwrap())
|
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));
|
let const_val = tables.tcx.valtree_to_const_val((ty, val));
|
||||||
if matches!(const_val, mir::ConstValue::ZeroSized) {
|
if matches!(const_val, mir::ConstValue::ZeroSized) {
|
||||||
stable_mir::ty::TyConstKind::ZSTValue(ty.stable(tables))
|
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> {
|
fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError> {
|
||||||
// only print integers
|
// only print integers
|
||||||
match (ct.kind(), ct.ty().kind()) {
|
match ct.kind() {
|
||||||
(ty::ConstKind::Value(ty::ValTree::Leaf(scalar)), ty::Int(_) | ty::Uint(_)) => {
|
ty::ConstKind::Value(ty, ty::ValTree::Leaf(scalar)) if ty.is_integral() => {
|
||||||
// The `pretty_print_const` formatting depends on -Zverbose-internals
|
// The `pretty_print_const` formatting depends on -Zverbose-internals
|
||||||
// flag, so we cannot reuse it here.
|
// flag, so we cannot reuse it here.
|
||||||
let signed = matches!(ct.ty().kind(), ty::Int(_));
|
let signed = matches!(ty.kind(), ty::Int(_));
|
||||||
write!(
|
write!(
|
||||||
self,
|
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("_")?,
|
_ => 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> {
|
fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError> {
|
||||||
// We only mangle a typed value if the const can be evaluated.
|
// We only mangle a typed value if the const can be evaluated.
|
||||||
let ct = ct.normalize(self.tcx, ty::ParamEnv::reveal_all());
|
let ct = ct.normalize(self.tcx, ty::ParamEnv::reveal_all());
|
||||||
match ct.kind() {
|
let (ct_ty, valtree) = match ct.kind() {
|
||||||
ty::ConstKind::Value(_) => {}
|
ty::ConstKind::Value(ty, val) => (ty, val),
|
||||||
|
|
||||||
// Placeholders (should be demangled as `_`).
|
// Placeholders (should be demangled as `_`).
|
||||||
// NOTE(eddyb) despite `Unevaluated` having a `DefId` (and therefore
|
// NOTE(eddyb) despite `Unevaluated` having a `DefId` (and therefore
|
||||||
|
@ -559,7 +559,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
|
||||||
self.push("p");
|
self.push("p");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
if let Some(&i) = self.consts.get(&ct) {
|
if let Some(&i) = self.consts.get(&ct) {
|
||||||
self.print_backref(i)?;
|
self.print_backref(i)?;
|
||||||
|
@ -567,16 +567,15 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let start = self.out.len();
|
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::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());
|
let mut bits = ct.eval_bits(self.tcx, ty::ParamEnv::reveal_all());
|
||||||
|
|
||||||
// Negative integer values are mangled using `n` as a "sign prefix".
|
// 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 =
|
let val =
|
||||||
Integer::from_int_ty(&self.tcx, *ity).size().sign_extend(bits) as i128;
|
Integer::from_int_ty(&self.tcx, *ity).size().sign_extend(bits) as i128;
|
||||||
if val < 0 {
|
if val < 0 {
|
||||||
|
@ -598,40 +597,32 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
|
||||||
|
|
||||||
match inner_ty.kind() {
|
match inner_ty.kind() {
|
||||||
ty::Str if mutbl.is_not() => {
|
ty::Str if mutbl.is_not() => {
|
||||||
match ct.kind() {
|
let slice =
|
||||||
ty::ConstKind::Value(valtree) => {
|
valtree.try_to_raw_bytes(self.tcx(), ct_ty).unwrap_or_else(|| {
|
||||||
let slice =
|
bug!(
|
||||||
valtree.try_to_raw_bytes(self.tcx(), ty).unwrap_or_else(|| {
|
"expected to get raw bytes from valtree {:?} for type {:}",
|
||||||
bug!(
|
valtree,
|
||||||
"expected to get raw bytes from valtree {:?} for type {:}",
|
ct_ty
|
||||||
valtree, ty
|
)
|
||||||
)
|
});
|
||||||
});
|
let s =
|
||||||
let s = std::str::from_utf8(slice)
|
std::str::from_utf8(slice).expect("non utf8 str from MIR interpreter");
|
||||||
.expect("non utf8 str from MIR interpreter");
|
|
||||||
|
|
||||||
self.push("e");
|
self.push("e");
|
||||||
|
|
||||||
// FIXME(eddyb) use a specialized hex-encoding loop.
|
// FIXME(eddyb) use a specialized hex-encoding loop.
|
||||||
for byte in s.bytes() {
|
for byte in s.bytes() {
|
||||||
let _ = write!(self.out, "{byte:02x}");
|
let _ = write!(self.out, "{byte:02x}");
|
||||||
}
|
|
||||||
|
|
||||||
self.push("_");
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => {
|
|
||||||
bug!("symbol_names: unsupported `&str` constant: {:?}", ct);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.push("_");
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let pointee_ty = ct
|
let pointee_ty = ct_ty
|
||||||
.ty()
|
|
||||||
.builtin_deref(true)
|
.builtin_deref(true)
|
||||||
.expect("tried to dereference on non-ptr type");
|
.expect("tried to dereference on non-ptr type");
|
||||||
// FIXME(const_generics): add an assert that we only do this for valtrees.
|
let dereferenced_const =
|
||||||
let dereferenced_const = self.tcx.mk_ct_from_kind(ct.kind(), pointee_ty);
|
ty::Const::new_value(self.tcx, valtree, pointee_ty);
|
||||||
dereferenced_const.print(self)?;
|
dereferenced_const.print(self)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -649,7 +640,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
|
||||||
Ok(())
|
Ok(())
|
||||||
};
|
};
|
||||||
|
|
||||||
match *ct.ty().kind() {
|
match *ct_ty.kind() {
|
||||||
ty::Array(..) | ty::Slice(_) => {
|
ty::Array(..) | ty::Slice(_) => {
|
||||||
self.push("A");
|
self.push("A");
|
||||||
print_field_list(self)?;
|
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()
|
infcx.next_region_var(RegionVariableOrigin::MiscVariable(span)).into()
|
||||||
}
|
}
|
||||||
ty::GenericArgKind::Type(_) => infcx.next_ty_var(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);
|
orig_values.push(unconstrained);
|
||||||
|
|
|
@ -609,8 +609,8 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||||
ty
|
ty
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn next_const_infer(&mut self, ty: Ty<'tcx>) -> ty::Const<'tcx> {
|
pub(super) fn next_const_infer(&mut self) -> ty::Const<'tcx> {
|
||||||
let ct = self.infcx.next_const_var(ty, DUMMY_SP);
|
let ct = self.infcx.next_const_var(DUMMY_SP);
|
||||||
self.inspect.add_var_value(ct);
|
self.inspect.add_var_value(ct);
|
||||||
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> {
|
pub(super) fn next_term_infer_of_kind(&mut self, kind: ty::Term<'tcx>) -> ty::Term<'tcx> {
|
||||||
match kind.unpack() {
|
match kind.unpack() {
|
||||||
ty::TermKind::Ty(_) => self.next_ty_infer().into(),
|
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,
|
&self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
unevaluated: ty::UnevaluatedConst<'tcx>,
|
unevaluated: ty::UnevaluatedConst<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
|
||||||
) -> Option<ty::Const<'tcx>> {
|
) -> Option<ty::Const<'tcx>> {
|
||||||
use rustc_middle::mir::interpret::ErrorHandled;
|
use rustc_middle::mir::interpret::ErrorHandled;
|
||||||
match self.infcx.const_eval_resolve(param_env, unevaluated, DUMMY_SP) {
|
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,
|
Ok(None) | Err(ErrorHandled::TooGeneric(_)) => None,
|
||||||
Err(ErrorHandled::Reported(e, _)) => {
|
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> {
|
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
||||||
match ct.kind() {
|
match ct.kind() {
|
||||||
ty::ConstKind::Unevaluated(..) if !ct.has_escaping_bound_vars() => {
|
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(
|
let normalizes_to = ty::PredicateKind::AliasRelate(
|
||||||
ct.into(),
|
ct.into(),
|
||||||
infer_ct.into(),
|
infer_ct.into(),
|
||||||
|
|
|
@ -208,7 +208,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
|
||||||
Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => {
|
Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => {
|
||||||
let unconstrained_term = match term.unpack() {
|
let unconstrained_term = match term.unpack() {
|
||||||
ty::TermKind::Ty(_) => infcx.next_ty_var(span).into(),
|
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 =
|
let goal =
|
||||||
goal.with(infcx.tcx, ty::NormalizesTo { alias, term: unconstrained_term });
|
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
|
// FIXME(generic_const_exprs): Implement handling for generic
|
||||||
// const expressions here.
|
// 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)
|
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||||
} else {
|
} else {
|
||||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
|
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
|
||||||
|
@ -178,7 +178,9 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
|
||||||
ty::ConstKind::Infer(_) => {
|
ty::ConstKind::Infer(_) => {
|
||||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
|
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)
|
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||||
}
|
}
|
||||||
// We can freely ICE here as:
|
// We can freely ICE here as:
|
||||||
|
@ -198,29 +200,37 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
let (ct, ty) = goal.predicate;
|
let (ct, ty) = goal.predicate;
|
||||||
|
|
||||||
// FIXME(BoxyUwU): Really we should not be calling `ct.ty()` for any variant
|
let ct_ty = match ct.kind() {
|
||||||
// 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() {
|
|
||||||
// FIXME: Ignore effect vars because canonicalization doesn't handle them correctly
|
// 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
|
// 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.
|
// for this goal which contains an effect var. Which then ends up ICEing.
|
||||||
ty::ConstKind::Infer(ty::InferConst::Var(_)) => {
|
ty::ConstKind::Infer(ty::InferConst::EffectVar(_)) => {
|
||||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
|
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(_) => {
|
ty::ConstKind::Error(_) => {
|
||||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
|
||||||
}
|
}
|
||||||
_ => {
|
ty::ConstKind::Unevaluated(uv) => {
|
||||||
self.eq(goal.param_env, ct.ty(), ty)?;
|
self.interner().type_of(uv.def).instantiate(self.interner(), uv.args)
|
||||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
|
||||||
}
|
}
|
||||||
}
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,6 @@ where
|
||||||
|
|
||||||
fn normalize_unevaluated_const(
|
fn normalize_unevaluated_const(
|
||||||
&mut self,
|
&mut self,
|
||||||
ty: Ty<'tcx>,
|
|
||||||
uv: ty::UnevaluatedConst<'tcx>,
|
uv: ty::UnevaluatedConst<'tcx>,
|
||||||
) -> Result<ty::Const<'tcx>, Vec<E>> {
|
) -> Result<ty::Const<'tcx>, Vec<E>> {
|
||||||
let infcx = self.at.infcx;
|
let infcx = self.at.infcx;
|
||||||
|
@ -126,7 +125,7 @@ where
|
||||||
|
|
||||||
self.depth += 1;
|
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(
|
let obligation = Obligation::new(
|
||||||
tcx,
|
tcx,
|
||||||
self.at.cause.clone(),
|
self.at.cause.clone(),
|
||||||
|
@ -143,7 +142,7 @@ where
|
||||||
let ct = infcx.resolve_vars_if_possible(new_infer_ct);
|
let ct = infcx.resolve_vars_if_possible(new_infer_ct);
|
||||||
ct.try_fold_with(self)?
|
ct.try_fold_with(self)?
|
||||||
} else {
|
} 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;
|
self.depth -= 1;
|
||||||
|
@ -214,7 +213,7 @@ where
|
||||||
if uv.has_escaping_bound_vars() {
|
if uv.has_escaping_bound_vars() {
|
||||||
let (uv, mapped_regions, mapped_types, mapped_consts) =
|
let (uv, mapped_regions, mapped_types, mapped_consts) =
|
||||||
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, uv);
|
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(
|
Ok(PlaceholderReplacer::replace_placeholders(
|
||||||
infcx,
|
infcx,
|
||||||
mapped_regions,
|
mapped_regions,
|
||||||
|
@ -224,7 +223,7 @@ where
|
||||||
result,
|
result,
|
||||||
))
|
))
|
||||||
} else {
|
} 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(
|
if let Some(normalized_const) = self.try_const_eval_resolve(
|
||||||
goal.param_env,
|
goal.param_env,
|
||||||
ty::UnevaluatedConst::new(goal.predicate.alias.def_id, goal.predicate.alias.args),
|
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.instantiate_normalizes_to_term(goal, normalized_const.into());
|
||||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
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 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 guar = tcx.dcx().span_delayed_bug(tcx.def_span(assoc_def.item.def_id), reason);
|
||||||
let error_term = match assoc_def.item.kind {
|
let error_term = match assoc_def.item.kind {
|
||||||
ty::AssocKind::Const => ty::Const::new_error(
|
ty::AssocKind::Const => ty::Const::new_error(tcx, guar).into(),
|
||||||
tcx,
|
|
||||||
guar,
|
|
||||||
tcx.type_of(goal.predicate.def_id())
|
|
||||||
.instantiate(tcx, goal.predicate.alias.args),
|
|
||||||
)
|
|
||||||
.into(),
|
|
||||||
ty::AssocKind::Type => Ty::new_error(tcx, guar).into(),
|
ty::AssocKind::Type => Ty::new_error(tcx, guar).into(),
|
||||||
// This makes no sense...
|
// This makes no sense...
|
||||||
ty::AssocKind::Fn => span_bug!(
|
ty::AssocKind::Fn => span_bug!(
|
||||||
|
@ -253,7 +247,6 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
|
||||||
ty::EarlyBinder::bind(
|
ty::EarlyBinder::bind(
|
||||||
ty::Const::new_error_with_message(
|
ty::Const::new_error_with_message(
|
||||||
tcx,
|
tcx,
|
||||||
tcx.type_of(assoc_def.item.def_id).instantiate_identity(),
|
|
||||||
DUMMY_SP,
|
DUMMY_SP,
|
||||||
"associated const projection is not supported yet",
|
"associated const projection is not supported yet",
|
||||||
)
|
)
|
||||||
|
|
|
@ -765,7 +765,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
||||||
unevaluated,
|
unevaluated,
|
||||||
obligation.cause.span,
|
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) => {
|
Ok(None) => {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let reported =
|
let reported =
|
||||||
|
|
|
@ -529,7 +529,6 @@ fn plug_infer_with_placeholders<'tcx>(
|
||||||
ty::Const::new_placeholder(
|
ty::Const::new_placeholder(
|
||||||
self.infcx.tcx,
|
self.infcx.tcx,
|
||||||
ty::Placeholder { universe: self.universe, bound: self.next_var() },
|
ty::Placeholder { universe: self.universe, bound: self.next_var() },
|
||||||
ct.ty(),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -34,7 +34,7 @@ pub fn is_const_evaluatable<'tcx>(
|
||||||
ty::ConstKind::Param(_)
|
ty::ConstKind::Param(_)
|
||||||
| ty::ConstKind::Bound(_, _)
|
| ty::ConstKind::Bound(_, _)
|
||||||
| ty::ConstKind::Placeholder(_)
|
| ty::ConstKind::Placeholder(_)
|
||||||
| ty::ConstKind::Value(_)
|
| ty::ConstKind::Value(_, _)
|
||||||
| ty::ConstKind::Error(_) => return Ok(()),
|
| ty::ConstKind::Error(_) => return Ok(()),
|
||||||
ty::ConstKind::Infer(_) => return Err(NotConstEvaluatable::MentionsInfer),
|
ty::ConstKind::Infer(_) => return Err(NotConstEvaluatable::MentionsInfer),
|
||||||
};
|
};
|
||||||
|
@ -173,8 +173,7 @@ fn satisfied_from_param_env<'tcx>(
|
||||||
debug!("is_const_evaluatable: candidate={:?}", c);
|
debug!("is_const_evaluatable: candidate={:?}", c);
|
||||||
if self.infcx.probe(|_| {
|
if self.infcx.probe(|_| {
|
||||||
let ocx = ObligationCtxt::new(self.infcx);
|
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()
|
&& ocx.select_all_or_error().is_empty()
|
||||||
}) {
|
}) {
|
||||||
self.single_match = match self.single_match {
|
self.single_match = match self.single_match {
|
||||||
|
@ -215,7 +214,6 @@ fn satisfied_from_param_env<'tcx>(
|
||||||
|
|
||||||
if let Some(Ok(c)) = single_match {
|
if let Some(Ok(c)) = single_match {
|
||||||
let ocx = ObligationCtxt::new(infcx);
|
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.eq(&ObligationCause::dummy(), param_env, c, ct).is_ok());
|
||||||
assert!(ocx.select_all_or_error().is_empty());
|
assert!(ocx.select_all_or_error().is_empty());
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -876,56 +876,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) => {
|
// Errors for `ConstEvaluatable` predicates show up as
|
||||||
// Errors for `ConstEvaluatable` predicates show up as
|
// `SelectionError::ConstEvalFailure`,
|
||||||
// `SelectionError::ConstEvalFailure`,
|
// not `Unimplemented`.
|
||||||
// not `Unimplemented`.
|
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_bug!(
|
||||||
span,
|
span,
|
||||||
"const-evaluatable requirement gave wrong error: `{:?}`",
|
"Unexpected `Predicate` for `SelectionError`: `{:?}`",
|
||||||
obligation
|
obligation
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::PredicateKind::ConstEquate(..) => {
|
|
||||||
// Errors for `ConstEquate` predicates show up as
|
|
||||||
// `SelectionError::ConstEvalFailure`,
|
|
||||||
// not `Unimplemented`.
|
|
||||||
span_bug!(
|
|
||||||
span,
|
|
||||||
"const-equate requirement gave wrong error: `{:?}`",
|
|
||||||
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(_) => {
|
Overflow(_) => {
|
||||||
bug!("overflow should be handled before the `report_selection_error` path");
|
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);
|
self.note_obligation_cause(&mut err, &obligation);
|
||||||
|
|
|
@ -439,37 +439,50 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
||||||
// This is because this is not ever a useful obligation to report
|
// This is because this is not ever a useful obligation to report
|
||||||
// as the cause of an overflow.
|
// as the cause of an overflow.
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
|
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
|
||||||
// FIXME(BoxyUwU): Really we should not be calling `ct.ty()` for any variant
|
let ct = infcx.shallow_resolve_const(ct);
|
||||||
// other than `ConstKind::Value`. Unfortunately this would require looking in the
|
let ct_ty = match ct.kind() {
|
||||||
// env for any `ConstArgHasType` assumptions for parameters and placeholders. I
|
ty::ConstKind::Infer(var) => {
|
||||||
// don't really want to implement this in the old solver so I haven't.
|
let var = match var {
|
||||||
//
|
ty::InferConst::Var(vid) => TyOrConstInferVar::Const(vid),
|
||||||
// We do still stall on infer vars though as otherwise a goal like:
|
ty::InferConst::EffectVar(vid) => TyOrConstInferVar::Effect(vid),
|
||||||
// `ConstArgHasType(?x: usize, usize)` can succeed even though it might later
|
ty::InferConst::Fresh(_) => {
|
||||||
// get unified with some const that is not of type `usize`.
|
bug!("encountered fresh const in fulfill")
|
||||||
let ct = self.selcx.infcx.shallow_resolve_const(ct);
|
}
|
||||||
match ct.kind() {
|
};
|
||||||
ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
|
|
||||||
pending_obligation.stalled_on.clear();
|
pending_obligation.stalled_on.clear();
|
||||||
pending_obligation.stalled_on.extend([TyOrConstInferVar::Const(vid)]);
|
pending_obligation.stalled_on.extend([var]);
|
||||||
ProcessResult::Unchanged
|
return ProcessResult::Unchanged;
|
||||||
}
|
}
|
||||||
ty::ConstKind::Error(_) => return ProcessResult::Changed(vec![]),
|
ty::ConstKind::Error(_) => return ProcessResult::Changed(vec![]),
|
||||||
_ => {
|
ty::ConstKind::Value(ty, _) => ty,
|
||||||
match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq(
|
ty::ConstKind::Unevaluated(uv) => {
|
||||||
// Only really excercised by generic_const_exprs
|
infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args)
|
||||||
DefineOpaqueTypes::Yes,
|
|
||||||
ct.ty(),
|
|
||||||
ty,
|
|
||||||
) {
|
|
||||||
Ok(inf_ok) => {
|
|
||||||
ProcessResult::Changed(mk_pending(inf_ok.into_obligations()))
|
|
||||||
}
|
|
||||||
Err(_) => ProcessResult::Error(FulfillmentErrorCode::Select(
|
|
||||||
SelectionError::Unimplemented,
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// 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,
|
||||||
|
ty,
|
||||||
|
) {
|
||||||
|
Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())),
|
||||||
|
Err(_) => ProcessResult::Error(FulfillmentErrorCode::Select(
|
||||||
|
SelectionError::ConstArgHasWrongType { ct, ct_ty, expected_ty: ty },
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -633,7 +646,6 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
||||||
match self.selcx.infcx.try_const_eval_resolve(
|
match self.selcx.infcx.try_const_eval_resolve(
|
||||||
obligation.param_env,
|
obligation.param_env,
|
||||||
unevaluated,
|
unevaluated,
|
||||||
c.ty(),
|
|
||||||
obligation.cause.span,
|
obligation.cause.span,
|
||||||
) {
|
) {
|
||||||
Ok(val) => Ok(val),
|
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.
|
// `ty::Const::normalize` can only work with properly preserved binders.
|
||||||
|
|
||||||
if c.has_escaping_bound_vars() {
|
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
|
// 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
|
// 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::InherentTy
|
||||||
| ty::AliasTermKind::OpaqueTy
|
| ty::AliasTermKind::OpaqueTy
|
||||||
| ty::AliasTermKind::WeakTy => selcx.infcx.next_ty_var(cause.span).into(),
|
| ty::AliasTermKind::WeakTy => selcx.infcx.next_ty_var(cause.span).into(),
|
||||||
ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => selcx
|
ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => {
|
||||||
.infcx
|
selcx.infcx.next_const_var(cause.span).into()
|
||||||
.next_const_var(
|
}
|
||||||
selcx
|
|
||||||
.tcx()
|
|
||||||
.type_of(projection_term.def_id)
|
|
||||||
.instantiate(selcx.tcx(), projection_term.args),
|
|
||||||
cause.span,
|
|
||||||
)
|
|
||||||
.into(),
|
|
||||||
};
|
};
|
||||||
let trait_obligation = Obligation {
|
let trait_obligation = Obligation {
|
||||||
cause,
|
cause,
|
||||||
|
@ -744,8 +737,6 @@ fn project<'cx, 'tcx>(
|
||||||
obligation.predicate.def_id,
|
obligation.predicate.def_id,
|
||||||
obligation.predicate.args,
|
obligation.predicate.args,
|
||||||
),
|
),
|
||||||
tcx.type_of(obligation.predicate.def_id)
|
|
||||||
.instantiate(tcx, obligation.predicate.args),
|
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
kind => {
|
kind => {
|
||||||
|
@ -2071,15 +2062,14 @@ fn confirm_impl_candidate<'cx, 'tcx>(
|
||||||
// * `args` ends up as `[u32, S]`
|
// * `args` ends up as `[u32, S]`
|
||||||
let args = obligation.predicate.args.rebase_onto(tcx, trait_def_id, args);
|
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 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 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 term: ty::EarlyBinder<'tcx, ty::Term<'tcx>> = if is_const {
|
||||||
let did = assoc_ty.item.def_id;
|
let did = assoc_ty.item.def_id;
|
||||||
let identity_args = crate::traits::GenericArgs::identity_for_item(tcx, did);
|
let identity_args = crate::traits::GenericArgs::identity_for_item(tcx, did);
|
||||||
let uv = ty::UnevaluatedConst::new(did, identity_args);
|
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 {
|
} 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) {
|
if !tcx.check_args_compatible(assoc_ty.item.def_id, args) {
|
||||||
let err = Ty::new_error_with_message(
|
let err = Ty::new_error_with_message(
|
||||||
|
|
|
@ -665,9 +665,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
tcx,
|
tcx,
|
||||||
ty::INNERMOST,
|
ty::INNERMOST,
|
||||||
ty::BoundVar::from_usize(bound_vars.len() - 1),
|
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()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
|
@ -947,7 +947,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
match self.infcx.try_const_eval_resolve(
|
match self.infcx.try_const_eval_resolve(
|
||||||
obligation.param_env,
|
obligation.param_env,
|
||||||
unevaluated,
|
unevaluated,
|
||||||
c.ty(),
|
|
||||||
obligation.cause.span,
|
obligation.cause.span,
|
||||||
) {
|
) {
|
||||||
Ok(val) => Ok(val),
|
Ok(val) => Ok(val),
|
||||||
|
@ -995,21 +994,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig),
|
ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig),
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
|
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 = self.infcx.shallow_resolve_const(ct);
|
||||||
let ct_ty = match ct.kind() {
|
let ct_ty = match ct.kind() {
|
||||||
ty::ConstKind::Infer(ty::InferConst::Var(_)) => {
|
ty::ConstKind::Infer(_) => {
|
||||||
return Ok(EvaluatedToAmbig);
|
return Ok(EvaluatedToAmbig);
|
||||||
}
|
}
|
||||||
ty::ConstKind::Error(_) => return Ok(EvaluatedToOk),
|
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(
|
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 universe = self.universe_for(debruijn);
|
||||||
let p = ty::PlaceholderConst { universe, bound: bound_const };
|
let p = ty::PlaceholderConst { universe, bound: bound_const };
|
||||||
self.mapped_consts.insert(p, 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),
|
_ => ct.super_fold_with(self),
|
||||||
}
|
}
|
||||||
|
@ -626,7 +626,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
|
||||||
let db = ty::DebruijnIndex::from_usize(
|
let db = ty::DebruijnIndex::from_usize(
|
||||||
self.universe_indices.len() - index + self.current_index.as_usize() - 1,
|
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 => {
|
None => {
|
||||||
if ct.has_infer() {
|
if ct.has_infer() {
|
||||||
|
|
|
@ -135,7 +135,7 @@ mod rustc {
|
||||||
use rustc_middle::ty::ScalarInt;
|
use rustc_middle::ty::ScalarInt;
|
||||||
use rustc_span::symbol::sym;
|
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 {
|
return Some(Self {
|
||||||
alignment: true,
|
alignment: true,
|
||||||
lifetimes: 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!(
|
assert_eq!(
|
||||||
tcx.require_lang_item(LangItem::TransmuteOpts, None),
|
tcx.require_lang_item(LangItem::TransmuteOpts, None),
|
||||||
|
|
|
@ -23,7 +23,7 @@ fn destructure_const<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
const_: ty::Const<'tcx>,
|
const_: ty::Const<'tcx>,
|
||||||
) -> ty::DestructuredConst<'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_)
|
bug!("cannot destructure constant {:?}", const_)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ fn destructure_const<'tcx>(
|
||||||
_ => bug!("cannot destructure constant {:?}", const_),
|
_ => 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) => {
|
ty::Array(inner_ty, _) | ty::Slice(inner_ty) => {
|
||||||
// construct the consts for the elements of the array/slice
|
// construct the consts for the elements of the array/slice
|
||||||
let field_consts = branches
|
let field_consts = branches
|
||||||
|
@ -121,7 +121,7 @@ fn recurse_build<'tcx>(
|
||||||
let sp = node.span;
|
let sp = node.span;
|
||||||
match tcx.at(sp).lit_to_const(LitToConstInput { lit: &lit.node, ty: node.ty, neg }) {
|
match tcx.at(sp).lit_to_const(LitToConstInput { lit: &lit.node, ty: node.ty, neg }) {
|
||||||
Ok(c) => c,
|
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) => {
|
Err(LitToConstError::TypeError) => {
|
||||||
bug!("encountered type error in lit_to_const")
|
bug!("encountered type error in lit_to_const")
|
||||||
}
|
}
|
||||||
|
@ -137,35 +137,31 @@ fn recurse_build<'tcx>(
|
||||||
}
|
}
|
||||||
&ExprKind::NamedConst { def_id, args, user_ty: _ } => {
|
&ExprKind::NamedConst { def_id, args, user_ty: _ } => {
|
||||||
let uneval = ty::UnevaluatedConst::new(def_id, args);
|
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, .. } => {
|
ExprKind::Call { fun, args, .. } => {
|
||||||
|
let fun_ty = body.exprs[*fun].ty;
|
||||||
let fun = recurse_build(tcx, body, *fun, root_span)?;
|
let fun = recurse_build(tcx, body, *fun, root_span)?;
|
||||||
|
|
||||||
let mut new_args = Vec::<ty::Const<'tcx>>::with_capacity(args.len());
|
let mut new_args = Vec::<ty::Const<'tcx>>::with_capacity(args.len());
|
||||||
for &id in args.iter() {
|
for &id in args.iter() {
|
||||||
new_args.push(recurse_build(tcx, body, id, root_span)?);
|
new_args.push(recurse_build(tcx, body, id, root_span)?);
|
||||||
}
|
}
|
||||||
ty::Const::new_expr(
|
ty::Const::new_expr(tcx, Expr::new_call(tcx, fun_ty, fun, new_args))
|
||||||
tcx,
|
|
||||||
Expr::new_call(tcx, fun.ty(), fun, new_args.into_iter()),
|
|
||||||
node.ty,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
&ExprKind::Binary { op, lhs, rhs } if check_binop(op) => {
|
&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 lhs = recurse_build(tcx, body, lhs, root_span)?;
|
||||||
|
let rhs_ty = body.exprs[rhs].ty;
|
||||||
let rhs = recurse_build(tcx, body, rhs, root_span)?;
|
let rhs = recurse_build(tcx, body, rhs, root_span)?;
|
||||||
ty::Const::new_expr(
|
ty::Const::new_expr(tcx, Expr::new_binop(tcx, op, lhs_ty, rhs_ty, lhs, rhs))
|
||||||
tcx,
|
|
||||||
Expr::new_binop(tcx, op, lhs.ty(), rhs.ty(), lhs, rhs),
|
|
||||||
node.ty,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
&ExprKind::Unary { op, arg } if check_unop(op) => {
|
&ExprKind::Unary { op, arg } if check_unop(op) => {
|
||||||
|
let arg_ty = body.exprs[arg].ty;
|
||||||
let arg = recurse_build(tcx, body, arg, root_span)?;
|
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:
|
// This is necessary so that the following compiles:
|
||||||
//
|
//
|
||||||
|
@ -187,20 +183,12 @@ fn recurse_build<'tcx>(
|
||||||
&ExprKind::Use { source } => {
|
&ExprKind::Use { source } => {
|
||||||
let value_ty = body.exprs[source].ty;
|
let value_ty = body.exprs[source].ty;
|
||||||
let value = recurse_build(tcx, body, source, root_span)?;
|
let value = recurse_build(tcx, body, source, root_span)?;
|
||||||
ty::Const::new_expr(
|
ty::Const::new_expr(tcx, Expr::new_cast(tcx, CastKind::Use, value_ty, value, node.ty))
|
||||||
tcx,
|
|
||||||
Expr::new_cast(tcx, CastKind::Use, value_ty, value, node.ty),
|
|
||||||
node.ty,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
&ExprKind::Cast { source } => {
|
&ExprKind::Cast { source } => {
|
||||||
let value_ty = body.exprs[source].ty;
|
let value_ty = body.exprs[source].ty;
|
||||||
let value = recurse_build(tcx, body, source, root_span)?;
|
let value = recurse_build(tcx, body, source, root_span)?;
|
||||||
ty::Const::new_expr(
|
ty::Const::new_expr(tcx, Expr::new_cast(tcx, CastKind::As, value_ty, value, node.ty))
|
||||||
tcx,
|
|
||||||
Expr::new_cast(tcx, CastKind::As, value_ty, value, node.ty),
|
|
||||||
node.ty,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
ExprKind::Borrow { arg, .. } => {
|
ExprKind::Borrow { arg, .. } => {
|
||||||
let arg_node = &body.exprs[*arg];
|
let arg_node = &body.exprs[*arg];
|
||||||
|
|
|
@ -115,8 +115,8 @@ impl<I: Interner> CanonicalVarInfo<I> {
|
||||||
CanonicalVarKind::PlaceholderTy(_) => false,
|
CanonicalVarKind::PlaceholderTy(_) => false,
|
||||||
CanonicalVarKind::Region(_) => true,
|
CanonicalVarKind::Region(_) => true,
|
||||||
CanonicalVarKind::PlaceholderRegion(..) => false,
|
CanonicalVarKind::PlaceholderRegion(..) => false,
|
||||||
CanonicalVarKind::Const(..) => true,
|
CanonicalVarKind::Const(_) => true,
|
||||||
CanonicalVarKind::PlaceholderConst(_, _) => false,
|
CanonicalVarKind::PlaceholderConst(_) => false,
|
||||||
CanonicalVarKind::Effect => true,
|
CanonicalVarKind::Effect => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,8 +126,8 @@ impl<I: Interner> CanonicalVarInfo<I> {
|
||||||
CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => true,
|
CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => true,
|
||||||
CanonicalVarKind::Ty(_)
|
CanonicalVarKind::Ty(_)
|
||||||
| CanonicalVarKind::PlaceholderTy(_)
|
| CanonicalVarKind::PlaceholderTy(_)
|
||||||
| CanonicalVarKind::Const(_, _)
|
| CanonicalVarKind::Const(_)
|
||||||
| CanonicalVarKind::PlaceholderConst(_, _)
|
| CanonicalVarKind::PlaceholderConst(_)
|
||||||
| CanonicalVarKind::Effect => false,
|
| CanonicalVarKind::Effect => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,12 +136,12 @@ impl<I: Interner> CanonicalVarInfo<I> {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
CanonicalVarKind::Ty(_)
|
CanonicalVarKind::Ty(_)
|
||||||
| CanonicalVarKind::Region(_)
|
| CanonicalVarKind::Region(_)
|
||||||
| CanonicalVarKind::Const(_, _)
|
| CanonicalVarKind::Const(_)
|
||||||
| CanonicalVarKind::Effect => panic!("expected placeholder: {self:?}"),
|
| CanonicalVarKind::Effect => panic!("expected placeholder: {self:?}"),
|
||||||
|
|
||||||
CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.var().as_usize(),
|
CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.var().as_usize(),
|
||||||
CanonicalVarKind::PlaceholderTy(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),
|
PlaceholderRegion(I::PlaceholderRegion),
|
||||||
|
|
||||||
/// Some kind of const inference variable.
|
/// Some kind of const inference variable.
|
||||||
Const(UniverseIndex, I::Ty),
|
Const(UniverseIndex),
|
||||||
|
|
||||||
/// Effect variable `'?E`.
|
/// Effect variable `'?E`.
|
||||||
Effect,
|
Effect,
|
||||||
|
|
||||||
/// A "placeholder" that represents "any const".
|
/// A "placeholder" that represents "any const".
|
||||||
PlaceholderConst(I::PlaceholderConst, I::Ty),
|
PlaceholderConst(I::PlaceholderConst),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I: Interner> PartialEq for CanonicalVarKind<I> {
|
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::PlaceholderTy(l0), Self::PlaceholderTy(r0)) => l0 == r0,
|
||||||
(Self::Region(l0), Self::Region(r0)) => l0 == r0,
|
(Self::Region(l0), Self::Region(r0)) => l0 == r0,
|
||||||
(Self::PlaceholderRegion(l0), Self::PlaceholderRegion(r0)) => l0 == r0,
|
(Self::PlaceholderRegion(l0), Self::PlaceholderRegion(r0)) => l0 == r0,
|
||||||
(Self::Const(l0, l1), Self::Const(r0, r1)) => l0 == r0 && l1 == r1,
|
(Self::Const(l0), Self::Const(r0)) => l0 == r0,
|
||||||
(Self::PlaceholderConst(l0, l1), Self::PlaceholderConst(r0, r1)) => {
|
(Self::PlaceholderConst(l0), Self::PlaceholderConst(r0)) => l0 == r0,
|
||||||
l0 == r0 && l1 == r1
|
|
||||||
}
|
|
||||||
_ => std::mem::discriminant(self) == std::mem::discriminant(other),
|
_ => std::mem::discriminant(self) == std::mem::discriminant(other),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -199,10 +197,10 @@ impl<I: Interner> CanonicalVarKind<I> {
|
||||||
match self {
|
match self {
|
||||||
CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) => ui,
|
CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) => ui,
|
||||||
CanonicalVarKind::Region(ui) => ui,
|
CanonicalVarKind::Region(ui) => ui,
|
||||||
CanonicalVarKind::Const(ui, _) => ui,
|
CanonicalVarKind::Const(ui) => ui,
|
||||||
CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe(),
|
CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe(),
|
||||||
CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe(),
|
CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe(),
|
||||||
CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.universe(),
|
CanonicalVarKind::PlaceholderConst(placeholder) => placeholder.universe(),
|
||||||
CanonicalVarKind::Ty(CanonicalTyVarKind::Float | CanonicalTyVarKind::Int) => {
|
CanonicalVarKind::Ty(CanonicalTyVarKind::Float | CanonicalTyVarKind::Int) => {
|
||||||
UniverseIndex::ROOT
|
UniverseIndex::ROOT
|
||||||
}
|
}
|
||||||
|
@ -220,7 +218,7 @@ impl<I: Interner> CanonicalVarKind<I> {
|
||||||
CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
|
CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
|
||||||
}
|
}
|
||||||
CanonicalVarKind::Region(_) => CanonicalVarKind::Region(ui),
|
CanonicalVarKind::Region(_) => CanonicalVarKind::Region(ui),
|
||||||
CanonicalVarKind::Const(_, ty) => CanonicalVarKind::Const(ui, ty),
|
CanonicalVarKind::Const(_) => CanonicalVarKind::Const(ui),
|
||||||
|
|
||||||
CanonicalVarKind::PlaceholderTy(placeholder) => {
|
CanonicalVarKind::PlaceholderTy(placeholder) => {
|
||||||
CanonicalVarKind::PlaceholderTy(placeholder.with_updated_universe(ui))
|
CanonicalVarKind::PlaceholderTy(placeholder.with_updated_universe(ui))
|
||||||
|
@ -228,8 +226,8 @@ impl<I: Interner> CanonicalVarKind<I> {
|
||||||
CanonicalVarKind::PlaceholderRegion(placeholder) => {
|
CanonicalVarKind::PlaceholderRegion(placeholder) => {
|
||||||
CanonicalVarKind::PlaceholderRegion(placeholder.with_updated_universe(ui))
|
CanonicalVarKind::PlaceholderRegion(placeholder.with_updated_universe(ui))
|
||||||
}
|
}
|
||||||
CanonicalVarKind::PlaceholderConst(placeholder, ty) => {
|
CanonicalVarKind::PlaceholderConst(placeholder) => {
|
||||||
CanonicalVarKind::PlaceholderConst(placeholder.with_updated_universe(ui), ty)
|
CanonicalVarKind::PlaceholderConst(placeholder.with_updated_universe(ui))
|
||||||
}
|
}
|
||||||
CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float)
|
CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float)
|
||||||
| CanonicalVarKind::Effect => {
|
| CanonicalVarKind::Effect => {
|
||||||
|
@ -345,21 +343,14 @@ impl<I: Interner> CanonicalVarValues<I> {
|
||||||
Region::new_anon_bound(tcx, ty::INNERMOST, ty::BoundVar::from_usize(i))
|
Region::new_anon_bound(tcx, ty::INNERMOST, ty::BoundVar::from_usize(i))
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
CanonicalVarKind::Effect => Const::new_anon_bound(
|
CanonicalVarKind::Effect => {
|
||||||
tcx,
|
Const::new_anon_bound(tcx, ty::INNERMOST, ty::BoundVar::from_usize(i))
|
||||||
ty::INNERMOST,
|
.into()
|
||||||
ty::BoundVar::from_usize(i),
|
}
|
||||||
Ty::new_bool(tcx),
|
CanonicalVarKind::Const(_) | CanonicalVarKind::PlaceholderConst(_) => {
|
||||||
)
|
Const::new_anon_bound(tcx, ty::INNERMOST, ty::BoundVar::from_usize(i))
|
||||||
.into(),
|
.into()
|
||||||
CanonicalVarKind::Const(_, ty)
|
}
|
||||||
| CanonicalVarKind::PlaceholderConst(_, ty) => Const::new_anon_bound(
|
|
||||||
tcx,
|
|
||||||
ty::INNERMOST,
|
|
||||||
ty::BoundVar::from_usize(i),
|
|
||||||
ty,
|
|
||||||
)
|
|
||||||
.into(),
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
|
|
|
@ -32,7 +32,7 @@ pub enum ConstKind<I: Interner> {
|
||||||
Unevaluated(ty::UnevaluatedConst<I>),
|
Unevaluated(ty::UnevaluatedConst<I>),
|
||||||
|
|
||||||
/// Used to hold computed value.
|
/// 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
|
/// A placeholder for a const which could not be computed; this is
|
||||||
/// propagated to avoid useless error messages.
|
/// 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,
|
(Bound(l0, l1), Bound(r0, r1)) => l0 == r0 && l1 == r1,
|
||||||
(Placeholder(l0), Placeholder(r0)) => l0 == r0,
|
(Placeholder(l0), Placeholder(r0)) => l0 == r0,
|
||||||
(Unevaluated(l0), Unevaluated(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,
|
(Error(l0), Error(r0)) => l0 == r0,
|
||||||
(Expr(l0), Expr(r0)) => l0 == r0,
|
(Expr(l0), Expr(r0)) => l0 == r0,
|
||||||
_ => false,
|
_ => false,
|
||||||
|
@ -80,7 +80,7 @@ impl<I: Interner> DebugWithInfcx<I> for ConstKind<I> {
|
||||||
Unevaluated(uv) => {
|
Unevaluated(uv) => {
|
||||||
write!(f, "{:?}", &this.wrap(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}}"),
|
Error(_) => write!(f, "{{const error}}"),
|
||||||
Expr(expr) => write!(f, "{:?}", &this.wrap(expr)),
|
Expr(expr) => write!(f, "{:?}", &this.wrap(expr)),
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,11 +38,11 @@ impl<I: Interner> InferCtxtLike for NoInfcx<I> {
|
||||||
panic!("cannot resolve {vid:?}")
|
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:?}")
|
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:?}")
|
panic!("cannot resolve {vid:?}")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -387,7 +387,7 @@ impl<I: Interner> TypeFolder<I> for Shifter<I> {
|
||||||
match ct.kind() {
|
match ct.kind() {
|
||||||
ty::ConstKind::Bound(debruijn, bound_ct) if debruijn >= self.current_index => {
|
ty::ConstKind::Bound(debruijn, bound_ct) if debruijn >= self.current_index => {
|
||||||
let debruijn = debruijn.shifted_in(self.amount);
|
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),
|
_ => 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_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_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_float_var(&self, vid: FloatVid) -> <Self::Interner as Interner>::Ty;
|
||||||
fn opportunistic_resolve_ct_var(
|
fn opportunistic_resolve_ct_var(&self, vid: ConstVid) -> <Self::Interner as Interner>::Const;
|
||||||
&self,
|
|
||||||
vid: ConstVid,
|
|
||||||
ty: <Self::Interner as Interner>::Ty,
|
|
||||||
) -> <Self::Interner as Interner>::Const;
|
|
||||||
fn opportunistic_resolve_effect_var(
|
fn opportunistic_resolve_effect_var(
|
||||||
&self,
|
&self,
|
||||||
vid: EffectVid,
|
vid: EffectVid,
|
||||||
ty: <Self::Interner as Interner>::Ty,
|
|
||||||
) -> <Self::Interner as Interner>::Const;
|
) -> <Self::Interner as Interner>::Const;
|
||||||
fn opportunistic_resolve_lt_var(&self, vid: RegionVid) -> <Self::Interner as Interner>::Region;
|
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>
|
+ TypeSuperFoldable<I>
|
||||||
+ Flags
|
+ 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(
|
fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self;
|
||||||
interner: I,
|
|
||||||
debruijn: ty::DebruijnIndex,
|
|
||||||
var: ty::BoundVar,
|
|
||||||
ty: I::Ty,
|
|
||||||
) -> Self;
|
|
||||||
|
|
||||||
fn new_unevaluated(interner: I, uv: ty::UnevaluatedConst<I>, ty: I::Ty) -> Self;
|
fn new_unevaluated(interner: I, uv: ty::UnevaluatedConst<I>) -> Self;
|
||||||
|
|
||||||
fn ty(self) -> I::Ty;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait GenericsOf<I: Interner<GenericsOf = Self>> {
|
pub trait GenericsOf<I: Interner<GenericsOf = Self>> {
|
||||||
|
|
|
@ -567,7 +567,6 @@ impl<I: Interner> AliasTerm<I> {
|
||||||
I::Const::new_unevaluated(
|
I::Const::new_unevaluated(
|
||||||
interner,
|
interner,
|
||||||
ty::UnevaluatedConst::new(self.def_id, self.args),
|
ty::UnevaluatedConst::new(self.def_id, self.args),
|
||||||
interner.type_of(self.def_id).instantiate(interner, &self.args),
|
|
||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,7 +130,10 @@ pub(crate) fn try_inline(
|
||||||
}
|
}
|
||||||
Res::Def(DefKind::Const, did) => {
|
Res::Def(DefKind::Const, did) => {
|
||||||
record_extern_fqn(cx, did, ItemType::Constant);
|
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) => {
|
Res::Def(DefKind::Macro(kind), did) => {
|
||||||
let is_doc_hidden = cx.tcx.is_doc_hidden(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 =
|
let mut generics =
|
||||||
clean_ty_generics(cx, cx.tcx.generics_of(def_id), cx.tcx.explicit_predicates_of(def_id));
|
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::simplify::move_bounds_to_generic_parameters(&mut generics);
|
||||||
|
let ty = clean_middle_ty(
|
||||||
clean::Constant {
|
ty::Binder::dummy(cx.tcx.type_of(def_id).instantiate_identity()),
|
||||||
type_: Box::new(clean_middle_ty(
|
cx,
|
||||||
ty::Binder::dummy(cx.tcx.type_of(def_id).instantiate_identity()),
|
None,
|
||||||
cx,
|
None,
|
||||||
Some(def_id),
|
);
|
||||||
None,
|
(generics, ty, clean::Constant { kind: clean::ConstantKind::Extern { def_id } })
|
||||||
)),
|
|
||||||
generics,
|
|
||||||
kind: clean::ConstantKind::Extern { def_id },
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::Static {
|
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>(
|
pub(crate) fn clean_const<'tcx>(
|
||||||
constant: &hir::ConstArg<'_>,
|
constant: &hir::ConstArg<'_>,
|
||||||
cx: &mut DocContext<'tcx>,
|
_cx: &mut DocContext<'tcx>,
|
||||||
) -> Constant {
|
) -> Constant {
|
||||||
let def_id = cx.tcx.hir().body_owner_def_id(constant.value.body).to_def_id();
|
Constant { kind: ConstantKind::Anonymous { body: constant.value.body } }
|
||||||
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 },
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn clean_middle_const<'tcx>(
|
pub(crate) fn clean_middle_const<'tcx>(
|
||||||
constant: ty::Binder<'tcx, ty::Const<'tcx>>,
|
constant: ty::Binder<'tcx, ty::Const<'tcx>>,
|
||||||
cx: &mut DocContext<'tcx>,
|
_cx: &mut DocContext<'tcx>,
|
||||||
) -> Constant {
|
) -> Constant {
|
||||||
// FIXME: instead of storing the stringified expression, store `self` directly instead.
|
// FIXME: instead of storing the stringified expression, store `self` directly instead.
|
||||||
Constant {
|
Constant { kind: ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() } }
|
||||||
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() },
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option<Lifetime> {
|
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) => {
|
ItemKind::Static(ty, mutability, body_id) => {
|
||||||
StaticItem(Static { type_: clean_ty(ty, cx), mutability, expr: Some(body_id) })
|
StaticItem(Static { type_: clean_ty(ty, cx), mutability, expr: Some(body_id) })
|
||||||
}
|
}
|
||||||
ItemKind::Const(ty, generics, body_id) => ConstantItem(Constant {
|
ItemKind::Const(ty, generics, body_id) => ConstantItem(
|
||||||
type_: Box::new(clean_ty(ty, cx)),
|
clean_generics(generics, cx),
|
||||||
generics: clean_generics(generics, cx),
|
Box::new(clean_ty(ty, cx)),
|
||||||
kind: ConstantKind::Local { body: body_id, def_id },
|
Constant { kind: ConstantKind::Local { body: body_id, def_id } },
|
||||||
}),
|
),
|
||||||
ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy {
|
ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy {
|
||||||
bounds: ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
|
bounds: ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
|
||||||
generics: clean_generics(ty.generics, cx),
|
generics: clean_generics(ty.generics, cx),
|
||||||
|
|
|
@ -830,7 +830,6 @@ pub(crate) enum ItemKind {
|
||||||
TypeAliasItem(Box<TypeAlias>),
|
TypeAliasItem(Box<TypeAlias>),
|
||||||
OpaqueTyItem(OpaqueTy),
|
OpaqueTyItem(OpaqueTy),
|
||||||
StaticItem(Static),
|
StaticItem(Static),
|
||||||
ConstantItem(Constant),
|
|
||||||
TraitItem(Box<Trait>),
|
TraitItem(Box<Trait>),
|
||||||
TraitAliasItem(TraitAlias),
|
TraitAliasItem(TraitAlias),
|
||||||
ImplItem(Box<Impl>),
|
ImplItem(Box<Impl>),
|
||||||
|
@ -853,6 +852,7 @@ pub(crate) enum ItemKind {
|
||||||
PrimitiveItem(PrimitiveType),
|
PrimitiveItem(PrimitiveType),
|
||||||
/// A required associated constant in a trait declaration.
|
/// A required associated constant in a trait declaration.
|
||||||
TyAssocConstItem(Generics, Box<Type>),
|
TyAssocConstItem(Generics, Box<Type>),
|
||||||
|
ConstantItem(Generics, Box<Type>, Constant),
|
||||||
/// An associated constant in a trait impl or a provided one in a trait declaration.
|
/// An associated constant in a trait impl or a provided one in a trait declaration.
|
||||||
AssocConstItem(Generics, Box<Type>, ConstantKind),
|
AssocConstItem(Generics, Box<Type>, ConstantKind),
|
||||||
/// A required associated type in a trait declaration.
|
/// A required associated type in a trait declaration.
|
||||||
|
@ -888,7 +888,7 @@ impl ItemKind {
|
||||||
| TypeAliasItem(_)
|
| TypeAliasItem(_)
|
||||||
| OpaqueTyItem(_)
|
| OpaqueTyItem(_)
|
||||||
| StaticItem(_)
|
| StaticItem(_)
|
||||||
| ConstantItem(_)
|
| ConstantItem(_, _, _)
|
||||||
| TraitAliasItem(_)
|
| TraitAliasItem(_)
|
||||||
| TyMethodItem(_)
|
| TyMethodItem(_)
|
||||||
| MethodItem(_, _)
|
| MethodItem(_, _)
|
||||||
|
@ -922,7 +922,7 @@ impl ItemKind {
|
||||||
| TypeAliasItem(_)
|
| TypeAliasItem(_)
|
||||||
| OpaqueTyItem(_)
|
| OpaqueTyItem(_)
|
||||||
| StaticItem(_)
|
| StaticItem(_)
|
||||||
| ConstantItem(_)
|
| ConstantItem(_, _, _)
|
||||||
| TraitAliasItem(_)
|
| TraitAliasItem(_)
|
||||||
| ForeignFunctionItem(_)
|
| ForeignFunctionItem(_)
|
||||||
| ForeignStaticItem(_)
|
| ForeignStaticItem(_)
|
||||||
|
@ -2364,8 +2364,6 @@ pub(crate) struct Static {
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
pub(crate) struct Constant {
|
pub(crate) struct Constant {
|
||||||
pub(crate) type_: Box<Type>,
|
|
||||||
pub(crate) generics: Generics,
|
|
||||||
pub(crate) kind: ConstantKind,
|
pub(crate) kind: ConstantKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -353,8 +353,8 @@ pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
// array lengths are obviously usize
|
// array lengths are obviously usize
|
||||||
ty::ConstKind::Value(ty::ValTree::Leaf(scalar))
|
ty::ConstKind::Value(ty, ty::ValTree::Leaf(scalar))
|
||||||
if *n.ty().kind() == ty::Uint(ty::UintTy::Usize) =>
|
if *ty.kind() == ty::Uint(ty::UintTy::Usize) =>
|
||||||
{
|
{
|
||||||
scalar.to_string()
|
scalar.to_string()
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ pub(crate) trait DocFolder: Sized {
|
||||||
| FunctionItem(_)
|
| FunctionItem(_)
|
||||||
| OpaqueTyItem(_)
|
| OpaqueTyItem(_)
|
||||||
| StaticItem(_)
|
| StaticItem(_)
|
||||||
| ConstantItem(_)
|
| ConstantItem(_, _, _)
|
||||||
| TraitAliasItem(_)
|
| TraitAliasItem(_)
|
||||||
| TyMethodItem(_)
|
| TyMethodItem(_)
|
||||||
| MethodItem(_, _)
|
| MethodItem(_, _)
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue