Introduce min_generic_const_args
and directly represent paths
Co-authored-by: Boxy UwU <rust@boxyuwu.dev> Co-authored-by: León Orell Valerian Liehr <me@fmease.dev>
This commit is contained in:
parent
b71fb5edc0
commit
59e339f766
21 changed files with 361 additions and 195 deletions
|
@ -1,13 +1,14 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_error_messages::MultiSpan;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::{self as hir, HirId};
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::{self as hir};
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use crate::middle::resolve_bound_vars as rbv;
|
||||
use crate::mir::interpret::{LitToConstInput, Scalar};
|
||||
use crate::ty::{self, GenericArgs, Ty, TyCtxt, TypeVisitableExt};
|
||||
|
||||
|
@ -142,7 +143,7 @@ impl<'tcx> Const<'tcx> {
|
|||
pub fn new_error_with_message<S: Into<MultiSpan>>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
span: S,
|
||||
msg: &'static str,
|
||||
msg: impl Into<Cow<'static, str>>,
|
||||
) -> Const<'tcx> {
|
||||
let reported = tcx.dcx().span_delayed_bug(span, msg);
|
||||
Const::new_error(tcx, reported)
|
||||
|
@ -183,46 +184,8 @@ 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> {
|
||||
/// Convert a [`hir::ConstArg`] to a [`ty::Const`](Self).
|
||||
#[instrument(skip(tcx), level = "debug")]
|
||||
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::Path(qpath) => {
|
||||
// FIXME(min_generic_const_args): for now only params are lowered to ConstArgKind::Path
|
||||
Self::from_param(tcx, qpath, const_arg.hir_id)
|
||||
}
|
||||
hir::ConstArgKind::Anon(anon) => Self::from_anon_const(tcx, anon.def_id),
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: move this and try_from_lit to hir_ty_lowering like lower_const_arg/from_const_arg
|
||||
/// Literals and const generic parameters are eagerly converted to a constant, everything else
|
||||
/// becomes `Unevaluated`.
|
||||
#[instrument(skip(tcx), level = "debug")]
|
||||
|
@ -240,7 +203,7 @@ impl<'tcx> Const<'tcx> {
|
|||
|
||||
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,
|
||||
None => ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst {
|
||||
def: def.to_def_id(),
|
||||
|
@ -249,40 +212,8 @@ 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")]
|
||||
fn try_from_lit_or_param(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
expr: &'tcx hir::Expr<'tcx>,
|
||||
) -> Option<Self> {
|
||||
fn try_from_lit(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
|
||||
// currently have to be wrapped in curly brackets, so it's necessary to special-case.
|
||||
let expr = match &expr.kind {
|
||||
|
@ -321,7 +252,7 @@ impl<'tcx> Const<'tcx> {
|
|||
Err(e) => {
|
||||
tcx.dcx().span_delayed_bug(
|
||||
expr.span,
|
||||
format!("Const::from_anon_const: couldn't lit_to_const {e:?}"),
|
||||
format!("Const::try_from_lit: couldn't lit_to_const {e:?}"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -414,20 +345,3 @@ impl<'tcx> Const<'tcx> {
|
|||
matches!(self.kind(), ty::ConstKind::Infer(_))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn const_param_default<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: LocalDefId,
|
||||
) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
|
||||
let default_ct = match tcx.hir_node_by_def_id(def_id) {
|
||||
hir::Node::GenericParam(hir::GenericParam {
|
||||
kind: hir::GenericParamKind::Const { default: Some(ct), .. },
|
||||
..
|
||||
}) => ct,
|
||||
_ => span_bug!(
|
||||
tcx.def_span(def_id),
|
||||
"`const_param_default` expected a generic parameter with a constant"
|
||||
),
|
||||
};
|
||||
ty::EarlyBinder::bind(Const::from_const_arg(tcx, default_ct, FeedConstTy::No))
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ use rustc_errors::{
|
|||
Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, LintDiagnostic, MultiSpan,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def::{CtorKind, DefKind};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
|
||||
use rustc_hir::definitions::Definitions;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
|
@ -230,7 +230,9 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||
DefKind::OpaqueTy => ty::AliasTermKind::OpaqueTy,
|
||||
DefKind::TyAlias => ty::AliasTermKind::WeakTy,
|
||||
DefKind::AssocConst => ty::AliasTermKind::ProjectionConst,
|
||||
DefKind::AnonConst => ty::AliasTermKind::UnevaluatedConst,
|
||||
DefKind::AnonConst | DefKind::Const | DefKind::Ctor(_, CtorKind::Const) => {
|
||||
ty::AliasTermKind::UnevaluatedConst
|
||||
}
|
||||
kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ pub use self::closure::{
|
|||
place_to_string_for_capture,
|
||||
};
|
||||
pub use self::consts::{
|
||||
Const, ConstInt, ConstKind, Expr, ExprKind, FeedConstTy, ScalarInt, UnevaluatedConst, ValTree,
|
||||
Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree,
|
||||
};
|
||||
pub use self::context::{
|
||||
CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt,
|
||||
|
@ -2249,7 +2249,6 @@ pub fn provide(providers: &mut Providers) {
|
|||
incoherent_impls: trait_def::incoherent_impls_provider,
|
||||
trait_impls_in_crate: trait_def::trait_impls_in_crate_provider,
|
||||
traits: trait_def::traits_provider,
|
||||
const_param_default: consts::const_param_default,
|
||||
vtable_allocation: vtable::vtable_allocation_provider,
|
||||
..*providers
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue