Skip to content

Commit

Permalink
Move Const::from_const_arg to HIR ty lowering
Browse files Browse the repository at this point in the history
This makes more sense and will allow us to start lowering all paths to
`ConstArgKind::Path`, rather than just bare params.
  • Loading branch information
camelid committed Oct 21, 2024
1 parent b6b6d99 commit 3c1ec62
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 114 deletions.
22 changes: 21 additions & 1 deletion compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ use tracing::{debug, instrument};

use crate::check::intrinsic::intrinsic_operation_unsafety;
use crate::errors;
use crate::hir_ty_lowering::{HirTyLowerer, RegionInferReason};
use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer, RegionInferReason};

pub(crate) mod dump;
mod generics_of;
Expand Down Expand Up @@ -86,6 +86,7 @@ pub fn provide(providers: &mut Providers) {
coroutine_for_closure,
is_type_alias_impl_trait,
rendered_precise_capturing_args,
const_param_default,
..*providers
};
}
Expand Down Expand Up @@ -1777,3 +1778,22 @@ fn rendered_precise_capturing_args<'tcx>(
_ => None,
})
}

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"
),
};
let icx = ItemCtxt::new(tcx, def_id);
let ct = icx.lowerer().lower_const_arg(default_ct, FeedConstTy::No);
ty::EarlyBinder::bind(ct)
}
8 changes: 4 additions & 4 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ use tracing::{debug, instrument};
use super::errors::GenericsArgsErrExtend;
use crate::bounds::Bounds;
use crate::errors;
use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer, PredicateFilter, RegionInferReason};
use crate::hir_ty_lowering::{
AssocItemQSelf, FeedConstTy, HirTyLowerer, PredicateFilter, RegionInferReason,
};

impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
/// Add a `Sized` bound to the `bounds` if appropriate.
Expand Down Expand Up @@ -353,9 +355,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
hir::AssocItemConstraintKind::Equality { term } => {
let term = match term {
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
hir::Term::Const(ct) => {
ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::No).into()
}
hir::Term::Const(ct) => self.lower_const_arg(ct, FeedConstTy::No).into(),
};

// Find any late-bound regions declared in `ty` that are not
Expand Down
79 changes: 74 additions & 5 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,23 @@ impl AssocItemQSelf {
}
}

/// 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,
}

/// New-typed boolean indicating whether explicit late-bound lifetimes
/// are present in a set of generic arguments.
///
Expand Down Expand Up @@ -486,8 +503,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
handle_ty_args(has_default, &inf.to_ty())
}
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::Param(param.def_id))
.into()
self.lowerer.lower_const_arg(ct, FeedConstTy::Param(param.def_id)).into()
}
(&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
self.lowerer.ct_infer(Some(param), inf.span).into()
Expand Down Expand Up @@ -904,8 +920,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let term: ty::Term<'_> = match term {
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
hir::Term::Const(ct) => {
ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::No)
.into()
self.lower_const_arg(ct, FeedConstTy::No).into()
}
};
// FIXME(#97583): This isn't syntactically well-formed!
Expand Down Expand Up @@ -1979,6 +1994,60 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
}

/// Convert a [`hir::ConstArg`] to a [`ty::Const`](Const).
#[instrument(skip(self), level = "debug")]
pub fn lower_const_arg(
&self,
const_arg: &hir::ConstArg<'tcx>,
feed: FeedConstTy,
) -> Const<'tcx> {
let tcx = self.tcx();

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.lower_const_arg_param(qpath, const_arg.hir_id)
}
hir::ConstArgKind::Anon(anon) => Const::from_anon_const(tcx, anon.def_id),
}
}

/// Lower a use of a const param to a [`Const`].
///
/// IMPORTANT: `qpath` must be a const param, otherwise this will panic
fn lower_const_arg_param(&self, qpath: hir::QPath<'tcx>, hir_id: HirId) -> Const<'tcx> {
let tcx = self.tcx();

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

fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> {
let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id());
match idx {
Expand Down Expand Up @@ -2122,7 +2191,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let length = match length {
hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
hir::ArrayLen::Body(constant) => {
ty::Const::from_const_arg(tcx, constant, ty::FeedConstTy::No)
self.lower_const_arg(constant, FeedConstTy::No)
}
};

Expand Down
14 changes: 13 additions & 1 deletion compiler/rustc_hir_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,15 @@ use rustc_hir::def::DefKind;
use rustc_middle::middle;
use rustc_middle::mir::interpret::GlobalId;
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{self, Const, Ty, TyCtxt};
use rustc_session::parse::feature_err;
use rustc_span::Span;
use rustc_span::symbol::sym;
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits;

use self::hir_ty_lowering::{FeedConstTy, HirTyLowerer};

rustc_fluent_macro::fluent_messages! { "../messages.ftl" }

fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
Expand Down Expand Up @@ -227,3 +229,13 @@ pub fn lower_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
let env_def_id = tcx.hir().get_parent_item(hir_ty.hir_id);
collect::ItemCtxt::new(tcx, env_def_id.def_id).lower_ty(hir_ty)
}

/// This is for rustdoc and clippy.
pub fn lower_const_arg<'tcx>(
tcx: TyCtxt<'tcx>,
hir_ct: &hir::ConstArg<'tcx>,
feed: FeedConstTy,
) -> Const<'tcx> {
let env_def_id = tcx.hir().get_parent_item(hir_ct.hir_id);
collect::ItemCtxt::new(tcx, env_def_id.def_id).lowerer().lower_const_arg(hir_ct, feed)
}
9 changes: 4 additions & 5 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ use rustc_hir_analysis::hir_ty_lowering::generics::{
check_generic_arg_count_for_call, lower_generic_args,
};
use rustc_hir_analysis::hir_ty_lowering::{
ExplicitLateBound, GenericArgCountMismatch, GenericArgCountResult, GenericArgsLowerer,
GenericPathSegment, HirTyLowerer, IsMethodCall, RegionInferReason,
ExplicitLateBound, FeedConstTy, GenericArgCountMismatch, GenericArgCountResult,
GenericArgsLowerer, GenericPathSegment, HirTyLowerer, IsMethodCall, RegionInferReason,
};
use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
use rustc_infer::infer::{DefineOpaqueTypes, InferResult};
Expand Down Expand Up @@ -469,7 +469,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
hir::ArrayLen::Body(const_arg) => {
let span = const_arg.span();
let c = ty::Const::from_const_arg(self.tcx, const_arg, ty::FeedConstTy::No);
let c = self.lowerer().lower_const_arg(const_arg, FeedConstTy::No);
self.register_wf_obligation(c.into(), span, ObligationCauseCode::WellFormed(None));
self.normalize(span, c)
}
Expand All @@ -481,8 +481,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
const_arg: &'tcx hir::ConstArg<'tcx>,
param_def_id: DefId,
) -> ty::Const<'tcx> {
let ct =
ty::Const::from_const_arg(self.tcx, const_arg, ty::FeedConstTy::Param(param_def_id));
let ct = self.lowerer().lower_const_arg(const_arg, FeedConstTy::Param(param_def_id));
self.register_wf_obligation(
ct.into(),
self.tcx.hir().span(const_arg.hir_id),
Expand Down
89 changes: 2 additions & 87 deletions compiler/rustc_middle/src/ty/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ use either::Either;
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::{ErrorHandled, LitToConstInput, Scalar};
use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};

Expand Down Expand Up @@ -183,46 +182,7 @@ 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),
}
}

/// Literals and const generic parameters are eagerly converted to a constant, everything else
/// becomes `Unevaluated`.
#[instrument(skip(tcx), level = "debug")]
Expand All @@ -249,34 +209,6 @@ 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(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
Expand Down Expand Up @@ -459,20 +391,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))
}
3 changes: 1 addition & 2 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,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,
Expand Down Expand Up @@ -2101,7 +2101,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
};
Expand Down
Loading

0 comments on commit 3c1ec62

Please sign in to comment.