Setup ty::Const functions for ConstArg
This commit is contained in:
parent
7d7be2f0f6
commit
e7c85cb1e0
3 changed files with 86 additions and 44 deletions
|
@ -470,13 +470,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
(&GenericParamDefKind::Type { has_default, .. }, GenericArg::Infer(inf)) => {
|
(&GenericParamDefKind::Type { has_default, .. }, GenericArg::Infer(inf)) => {
|
||||||
handle_ty_args(has_default, &inf.to_ty())
|
handle_ty_args(has_default, &inf.to_ty())
|
||||||
}
|
}
|
||||||
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => match &ct.kind {
|
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
|
||||||
hir::ConstArgKind::Anon(anon) => {
|
ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::Param(param.def_id))
|
||||||
let did = anon.def_id;
|
.into()
|
||||||
tcx.feed_anon_const_type(did, tcx.type_of(param.def_id));
|
|
||||||
ty::Const::from_anon_const(tcx, did).into()
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
(&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => {
|
(&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => {
|
||||||
self.lowerer.ct_infer(Some(param), inf.span).into()
|
self.lowerer.ct_infer(Some(param), inf.span).into()
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,9 @@ use crate::mir::interpret::{ErrorHandled, LitToConstInput, Scalar};
|
||||||
use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
|
use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
|
||||||
use rustc_data_structures::intern::Interned;
|
use rustc_data_structures::intern::Interned;
|
||||||
use rustc_error_messages::MultiSpan;
|
use rustc_error_messages::MultiSpan;
|
||||||
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::{DefId, LocalDefId};
|
||||||
|
use rustc_hir::{self as hir, HirId};
|
||||||
use rustc_macros::HashStable;
|
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};
|
||||||
|
@ -182,16 +182,52 @@ impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// In some cases, [`hir::ConstArg`]s that are being used in the type system
|
||||||
|
/// through const generics need to have their type "fed" to them
|
||||||
|
/// using the query system.
|
||||||
|
///
|
||||||
|
/// Use this enum with [`Const::from_const_arg`] to instruct it with the
|
||||||
|
/// desired behavior.
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum FeedConstTy {
|
||||||
|
/// Feed the type.
|
||||||
|
///
|
||||||
|
/// The `DefId` belongs to the const param that we are supplying
|
||||||
|
/// this (anon) const arg to.
|
||||||
|
Param(DefId),
|
||||||
|
/// Don't feed the type.
|
||||||
|
No,
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> Const<'tcx> {
|
impl<'tcx> Const<'tcx> {
|
||||||
|
/// Convert a [`hir::ConstArg`] to a [`ty::Const`](Self).
|
||||||
|
#[instrument(skip(tcx), level = "debug")]
|
||||||
|
#[allow(irrefutable_let_patterns)]
|
||||||
|
pub fn from_const_arg(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
const_arg: &'tcx hir::ConstArg<'tcx>,
|
||||||
|
feed: FeedConstTy,
|
||||||
|
) -> Self {
|
||||||
|
if let FeedConstTy::Param(param_def_id) = feed
|
||||||
|
&& let hir::ConstArgKind::Anon(anon) = &const_arg.kind
|
||||||
|
{
|
||||||
|
tcx.feed_anon_const_type(anon.def_id, tcx.type_of(param_def_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
match const_arg.kind {
|
||||||
|
hir::ConstArgKind::Anon(anon) => Self::from_anon_const(tcx, anon.def_id),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Literals and const generic parameters are eagerly converted to a constant, everything else
|
/// Literals and const generic parameters are eagerly converted to a constant, everything else
|
||||||
/// becomes `Unevaluated`.
|
/// becomes `Unevaluated`.
|
||||||
#[instrument(skip(tcx), level = "debug")]
|
#[instrument(skip(tcx), level = "debug")]
|
||||||
pub fn from_anon_const(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self {
|
pub fn from_anon_const(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self {
|
||||||
let body_id = match tcx.hir_node_by_def_id(def) {
|
let body_id = match tcx.hir_node_by_def_id(def) {
|
||||||
hir::Node::AnonConst(ac) => ac.body,
|
hir::Node::AnonConst(ac) => ac.body,
|
||||||
_ => span_bug!(
|
node => span_bug!(
|
||||||
tcx.def_span(def.to_def_id()),
|
tcx.def_span(def.to_def_id()),
|
||||||
"from_anon_const can only process anonymous constants"
|
"from_anon_const can only process anonymous constants, not {node:?}"
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -200,7 +236,7 @@ impl<'tcx> Const<'tcx> {
|
||||||
|
|
||||||
let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");
|
let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");
|
||||||
|
|
||||||
match Self::try_from_lit_or_param(tcx, ty, expr) {
|
match Self::try_from_lit(tcx, ty, expr) {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => ty::Const::new_unevaluated(
|
None => ty::Const::new_unevaluated(
|
||||||
tcx,
|
tcx,
|
||||||
|
@ -212,12 +248,36 @@ impl<'tcx> Const<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Lower a const param to a [`Const`].
|
||||||
|
///
|
||||||
|
/// IMPORTANT: `qpath` must be a const param, otherwise this will panic
|
||||||
|
fn from_param(tcx: TyCtxt<'tcx>, qpath: hir::QPath<'tcx>, hir_id: HirId) -> Self {
|
||||||
|
let hir::QPath::Resolved(_, &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. }) =
|
||||||
|
qpath
|
||||||
|
else {
|
||||||
|
span_bug!(qpath.span(), "non-param {qpath:?} passed to Const::from_param")
|
||||||
|
};
|
||||||
|
|
||||||
|
match tcx.named_bound_var(hir_id) {
|
||||||
|
Some(rbv::ResolvedArg::EarlyBound(_)) => {
|
||||||
|
// Find the name and index of the const parameter by indexing the generics of
|
||||||
|
// the parent item and construct a `ParamConst`.
|
||||||
|
let item_def_id = tcx.parent(def_id);
|
||||||
|
let generics = tcx.generics_of(item_def_id);
|
||||||
|
let index = generics.param_def_id_to_index[&def_id];
|
||||||
|
let name = tcx.item_name(def_id);
|
||||||
|
ty::Const::new_param(tcx, ty::ParamConst::new(index, name))
|
||||||
|
}
|
||||||
|
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
|
||||||
|
ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index))
|
||||||
|
}
|
||||||
|
Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar),
|
||||||
|
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", hir_id),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[instrument(skip(tcx), level = "debug")]
|
#[instrument(skip(tcx), level = "debug")]
|
||||||
fn try_from_lit_or_param(
|
fn try_from_lit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>) -> Option<Self> {
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
ty: Ty<'tcx>,
|
|
||||||
expr: &'tcx hir::Expr<'tcx>,
|
|
||||||
) -> Option<Self> {
|
|
||||||
// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
|
// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
|
||||||
// currently have to be wrapped in curly brackets, so it's necessary to special-case.
|
// currently have to be wrapped in curly brackets, so it's necessary to special-case.
|
||||||
let expr = match &expr.kind {
|
let expr = match &expr.kind {
|
||||||
|
@ -250,34 +310,19 @@ impl<'tcx> Const<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(const_generics): We currently have to special case parameters because `min_const_generics`
|
if let hir::ExprKind::Path(
|
||||||
// does not provide the parents generics to anonymous constants. We still allow generic const
|
qpath @ hir::QPath::Resolved(
|
||||||
// parameters by themselves however, e.g. `N`. These constants would cause an ICE if we were to
|
|
||||||
// ever try to instantiate the generic parameters in their bodies.
|
|
||||||
match expr.kind {
|
|
||||||
hir::ExprKind::Path(hir::QPath::Resolved(
|
|
||||||
_,
|
_,
|
||||||
&hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. },
|
&hir::Path { res: Res::Def(DefKind::ConstParam, _), .. },
|
||||||
)) => {
|
),
|
||||||
match tcx.named_bound_var(expr.hir_id) {
|
) = expr.kind
|
||||||
Some(rbv::ResolvedArg::EarlyBound(_)) => {
|
{
|
||||||
// Find the name and index of the const parameter by indexing the generics of
|
// FIXME: once ConstArgKind::Path added, uncomment span_bug and delete return
|
||||||
// the parent item and construct a `ParamConst`.
|
// span_bug!(expr.span, "try_from_lit: received const param which shouldn't be possible")
|
||||||
let item_def_id = tcx.parent(def_id);
|
return Some(Self::from_param(tcx, qpath, expr.hir_id));
|
||||||
let generics = tcx.generics_of(item_def_id);
|
|
||||||
let index = generics.param_def_id_to_index[&def_id];
|
|
||||||
let name = tcx.item_name(def_id);
|
|
||||||
Some(ty::Const::new_param(tcx, ty::ParamConst::new(index, name)))
|
|
||||||
}
|
|
||||||
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
|
|
||||||
Some(ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index)))
|
|
||||||
}
|
|
||||||
Some(rbv::ResolvedArg::Error(guar)) => Some(ty::Const::new_error(tcx, guar)),
|
|
||||||
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -86,7 +86,7 @@ pub use self::closure::{
|
||||||
CAPTURE_STRUCT_LOCAL,
|
CAPTURE_STRUCT_LOCAL,
|
||||||
};
|
};
|
||||||
pub use self::consts::{
|
pub use self::consts::{
|
||||||
Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree,
|
Const, ConstInt, ConstKind, Expr, ExprKind, FeedConstTy, 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,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue