Introduce tcx.anon_const_kind query
This commit is contained in:
parent
356f2d0774
commit
996a185ba7
11 changed files with 86 additions and 46 deletions
|
|
@ -89,6 +89,7 @@ pub(crate) fn provide(providers: &mut Providers) {
|
|||
opaque_ty_origin,
|
||||
rendered_precise_capturing_args,
|
||||
const_param_default,
|
||||
anon_const_kind,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
|
@ -1828,3 +1829,27 @@ fn const_param_default<'tcx>(
|
|||
.lower_const_arg(default_ct, FeedConstTy::Param(def_id.to_def_id(), identity_args));
|
||||
ty::EarlyBinder::bind(ct)
|
||||
}
|
||||
|
||||
fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKind {
|
||||
let hir_id = tcx.local_def_id_to_hir_id(def);
|
||||
let const_arg_id = tcx.parent_hir_id(hir_id);
|
||||
match tcx.hir_node(const_arg_id) {
|
||||
hir::Node::ConstArg(_) => {
|
||||
if tcx.features().generic_const_exprs() {
|
||||
ty::AnonConstKind::GCEConst
|
||||
} else if tcx.features().min_generic_const_args() {
|
||||
ty::AnonConstKind::MCGConst
|
||||
} else if let hir::Node::Expr(hir::Expr {
|
||||
kind: hir::ExprKind::Repeat(_, repeat_count),
|
||||
..
|
||||
}) = tcx.hir_node(tcx.parent_hir_id(const_arg_id))
|
||||
&& repeat_count.hir_id == const_arg_id
|
||||
{
|
||||
ty::AnonConstKind::RepeatExprCount
|
||||
} else {
|
||||
ty::AnonConstKind::MCGConst
|
||||
}
|
||||
}
|
||||
_ => ty::AnonConstKind::NonTypeSystem,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,19 +104,27 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
|||
}
|
||||
}
|
||||
|
||||
if in_param_ty {
|
||||
// We do not allow generic parameters in anon consts if we are inside
|
||||
// of a const parameter type, e.g. `struct Foo<const N: usize, const M: [u8; N]>` is not allowed.
|
||||
None
|
||||
} else if tcx.features().generic_const_exprs() {
|
||||
let parent_node = tcx.parent_hir_node(hir_id);
|
||||
debug!(?parent_node);
|
||||
if let Node::Variant(Variant { disr_expr: Some(constant), .. }) = parent_node
|
||||
&& constant.hir_id == hir_id
|
||||
{
|
||||
// enum variant discriminants are not allowed to use any kind of generics
|
||||
None
|
||||
} else if let Some(param_id) = tcx.hir_opt_const_param_default_param_def_id(hir_id)
|
||||
match tcx.anon_const_kind(def_id) {
|
||||
// Stable: anon consts are not able to use any generic parameters...
|
||||
ty::AnonConstKind::MCGConst => None,
|
||||
// we provide generics to repeat expr counts as a backwards compatibility hack. #76200
|
||||
ty::AnonConstKind::RepeatExprCount => Some(parent_did),
|
||||
|
||||
// Even GCE anon const should not be allowed to use generic parameters as it would be
|
||||
// trivially forward declared uses once desugared. E.g. `const N: [u8; ANON::<N>]`.
|
||||
//
|
||||
// We could potentially mirror the hack done for defaults of generic parameters but
|
||||
// this case just doesn't come up much compared to `const N: u32 = ...`. Long term the
|
||||
// hack for defaulted parameters should be removed eventually anyway.
|
||||
ty::AnonConstKind::GCEConst if in_param_ty => None,
|
||||
// GCE anon consts as a default for a generic parameter should have their provided generics
|
||||
// "truncated" up to whatever generic parameter this anon const is within the default of.
|
||||
//
|
||||
// FIXME(generic_const_exprs): This only handles `const N: usize = /*defid*/` but not type
|
||||
// parameter defaults, e.g. `T = Foo</*defid*/>`.
|
||||
ty::AnonConstKind::GCEConst
|
||||
if let Some(param_id) =
|
||||
tcx.hir_opt_const_param_default_param_def_id(hir_id) =>
|
||||
{
|
||||
// If the def_id we are calling generics_of on is an anon ct default i.e:
|
||||
//
|
||||
|
|
@ -160,36 +168,17 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
|||
has_self: generics.has_self,
|
||||
has_late_bound_regions: generics.has_late_bound_regions,
|
||||
};
|
||||
} else {
|
||||
// HACK(eddyb) this provides the correct generics when
|
||||
// `feature(generic_const_expressions)` is enabled, so that const expressions
|
||||
// used with const generics, e.g. `Foo<{N+1}>`, can work at all.
|
||||
//
|
||||
// Note that we do not supply the parent generics when using
|
||||
// `min_const_generics`.
|
||||
}
|
||||
ty::AnonConstKind::GCEConst => Some(parent_did),
|
||||
|
||||
// Field defaults are allowed to use generic parameters, e.g. `field: u32 = /*defid: N + 1*/`
|
||||
ty::AnonConstKind::NonTypeSystem
|
||||
if matches!(tcx.parent_hir_node(hir_id), Node::TyPat(_) | Node::Field(_)) =>
|
||||
{
|
||||
Some(parent_did)
|
||||
}
|
||||
} else {
|
||||
let parent_node = tcx.parent_hir_node(hir_id);
|
||||
let parent_node = match parent_node {
|
||||
Node::ConstArg(ca) => tcx.parent_hir_node(ca.hir_id),
|
||||
_ => parent_node,
|
||||
};
|
||||
match parent_node {
|
||||
// HACK(eddyb) this provides the correct generics for repeat
|
||||
// expressions' count (i.e. `N` in `[x; N]`), and explicit
|
||||
// `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`),
|
||||
// as they shouldn't be able to cause query cycle errors.
|
||||
Node::Expr(Expr { kind: ExprKind::Repeat(_, ct), .. })
|
||||
if ct.anon_const_hir_id() == Some(hir_id) =>
|
||||
{
|
||||
Some(parent_did)
|
||||
}
|
||||
Node::TyPat(_) => Some(parent_did),
|
||||
// Field default values inherit the ADT's generics.
|
||||
Node::Field(_) => Some(parent_did),
|
||||
_ => None,
|
||||
}
|
||||
// Default to no generic parameters for other kinds of anon consts
|
||||
ty::AnonConstKind::NonTypeSystem => None,
|
||||
}
|
||||
}
|
||||
Node::ConstBlock(_)
|
||||
|
|
|
|||
|
|
@ -425,6 +425,7 @@ provide! { tcx, def_id, other, cdata,
|
|||
doc_link_traits_in_scope => {
|
||||
tcx.arena.alloc_from_iter(cdata.get_doc_link_traits_in_scope(def_id.index))
|
||||
}
|
||||
anon_const_kind => { table }
|
||||
}
|
||||
|
||||
pub(in crate::rmeta) fn provide(providers: &mut Providers) {
|
||||
|
|
|
|||
|
|
@ -1569,6 +1569,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
<- tcx.explicit_implied_const_bounds(def_id).skip_binder());
|
||||
}
|
||||
}
|
||||
if let DefKind::AnonConst = def_kind {
|
||||
record!(self.tables.anon_const_kind[def_id] <- self.tcx.anon_const_kind(def_id));
|
||||
}
|
||||
if tcx.impl_method_has_trait_impl_trait_tys(def_id)
|
||||
&& let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -480,6 +480,7 @@ define_tables! {
|
|||
doc_link_traits_in_scope: Table<DefIndex, LazyArray<DefId>>,
|
||||
assumed_wf_types_for_rpitit: Table<DefIndex, LazyArray<(Ty<'static>, Span)>>,
|
||||
opaque_ty_origin: Table<DefIndex, LazyValue<hir::OpaqueTyOrigin<DefId>>>,
|
||||
anon_const_kind: Table<DefIndex, LazyValue<ty::AnonConstKind>>,
|
||||
}
|
||||
|
||||
#[derive(TyEncodable, TyDecodable)]
|
||||
|
|
|
|||
|
|
@ -311,6 +311,7 @@ trivial! {
|
|||
rustc_middle::ty::Asyncness,
|
||||
rustc_middle::ty::AsyncDestructor,
|
||||
rustc_middle::ty::BoundVariableKind,
|
||||
rustc_middle::ty::AnonConstKind,
|
||||
rustc_middle::ty::DeducedParamAttrs,
|
||||
rustc_middle::ty::Destructor,
|
||||
rustc_middle::ty::fast_reject::SimplifiedType,
|
||||
|
|
|
|||
|
|
@ -2586,6 +2586,12 @@ rustc_queries! {
|
|||
desc { "estimating codegen size of `{}`", key }
|
||||
cache_on_disk_if { true }
|
||||
}
|
||||
|
||||
query anon_const_kind(def_id: DefId) -> ty::AnonConstKind {
|
||||
desc { |tcx| "looking up anon const kind of `{}`", tcx.def_path_str(def_id) }
|
||||
cache_on_disk_if { def_id.is_local() }
|
||||
separate_provide_extern
|
||||
}
|
||||
}
|
||||
|
||||
rustc_with_all_queries! { define_callbacks! }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::borrow::Cow;
|
|||
|
||||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_error_messages::MultiSpan;
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
|
||||
use rustc_type_ir::walk::TypeWalker;
|
||||
use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
|
||||
|
||||
|
|
@ -259,3 +259,11 @@ impl<'tcx> Const<'tcx> {
|
|||
TypeWalker::new(self.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable, HashStable)]
|
||||
pub enum AnonConstKind {
|
||||
GCEConst,
|
||||
MCGConst,
|
||||
RepeatExprCount,
|
||||
NonTypeSystem,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,8 +74,8 @@ pub use self::closure::{
|
|||
place_to_string_for_capture,
|
||||
};
|
||||
pub use self::consts::{
|
||||
Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree, ValTreeKind,
|
||||
Value,
|
||||
AnonConstKind, Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst,
|
||||
ValTree, ValTreeKind, Value,
|
||||
};
|
||||
pub use self::context::{
|
||||
CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt,
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ trivially_parameterized_over_tcx! {
|
|||
ty::AsyncDestructor,
|
||||
ty::AssocItemContainer,
|
||||
ty::Asyncness,
|
||||
ty::AnonConstKind,
|
||||
ty::DeducedParamAttrs,
|
||||
ty::Destructor,
|
||||
ty::Generics,
|
||||
|
|
|
|||
|
|
@ -553,7 +553,8 @@ pub fn try_evaluate_const<'tcx>(
|
|||
//
|
||||
// FIXME: `const_eval_resolve_for_typeck` should probably just modify the env itself
|
||||
// instead of having this logic here
|
||||
let (args, typing_env) = if tcx.features().generic_const_exprs()
|
||||
let (args, typing_env) = if tcx.def_kind(uv.def) == DefKind::AnonConst
|
||||
&& let ty::AnonConstKind::GCEConst = tcx.anon_const_kind(uv.def)
|
||||
&& uv.has_non_region_infer()
|
||||
{
|
||||
// `feature(generic_const_exprs)` causes anon consts to inherit all parent generics. This can cause
|
||||
|
|
@ -582,7 +583,10 @@ pub fn try_evaluate_const<'tcx>(
|
|||
(args, typing_env)
|
||||
}
|
||||
}
|
||||
} else if tcx.def_kind(uv.def) == DefKind::AnonConst && uv.has_non_region_infer() {
|
||||
} else if tcx.def_kind(uv.def) == DefKind::AnonConst
|
||||
&& let ty::AnonConstKind::RepeatExprCount = tcx.anon_const_kind(uv.def)
|
||||
&& uv.has_non_region_infer()
|
||||
{
|
||||
// FIXME: remove this when `const_evaluatable_unchecked` is a hard error.
|
||||
//
|
||||
// Diagnostics will sometimes replace the identity args of anon consts in
|
||||
|
|
@ -599,6 +603,7 @@ pub fn try_evaluate_const<'tcx>(
|
|||
|
||||
let args = GenericArgs::identity_for_item(tcx, uv.def);
|
||||
let typing_env = ty::TypingEnv::post_analysis(tcx, uv.def);
|
||||
|
||||
(args, typing_env)
|
||||
} else {
|
||||
// FIXME: This codepath is reachable under `associated_const_equality` and in the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue