Skip to content

Commit 39ef359

Browse files
committed
Introduce tcx.anon_const_kind query
1 parent aeee65a commit 39ef359

File tree

11 files changed

+86
-47
lines changed

11 files changed

+86
-47
lines changed

compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ pub(crate) fn provide(providers: &mut Providers) {
8989
opaque_ty_origin,
9090
rendered_precise_capturing_args,
9191
const_param_default,
92+
anon_const_kind,
9293
..*providers
9394
};
9495
}
@@ -1828,3 +1829,27 @@ fn const_param_default<'tcx>(
18281829
.lower_const_arg(default_ct, FeedConstTy::Param(def_id.to_def_id(), identity_args));
18291830
ty::EarlyBinder::bind(ct)
18301831
}
1832+
1833+
fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKind {
1834+
let hir_id = tcx.local_def_id_to_hir_id(def);
1835+
let const_arg_id = tcx.parent_hir_id(hir_id);
1836+
match tcx.hir_node(const_arg_id) {
1837+
hir::Node::ConstArg(_) => {
1838+
if tcx.features().generic_const_exprs() {
1839+
ty::AnonConstKind::GCEConst
1840+
} else if tcx.features().min_generic_const_args() {
1841+
ty::AnonConstKind::MCGConst
1842+
} else if let hir::Node::Expr(hir::Expr {
1843+
kind: hir::ExprKind::Repeat(_, repeat_count),
1844+
..
1845+
}) = tcx.hir_node(tcx.parent_hir_id(const_arg_id))
1846+
&& repeat_count.hir_id == const_arg_id
1847+
{
1848+
ty::AnonConstKind::RepeatExprCount
1849+
} else {
1850+
ty::AnonConstKind::MCGConst
1851+
}
1852+
}
1853+
_ => ty::AnonConstKind::NonTypeSystem,
1854+
}
1855+
}

compiler/rustc_hir_analysis/src/collect/generics_of.rs

Lines changed: 30 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -104,20 +104,27 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
104104
}
105105
}
106106

107-
if in_param_ty {
108-
// We do not allow generic parameters in anon consts if we are inside
109-
// of a const parameter type, e.g. `struct Foo<const N: usize, const M: [u8; N]>` is not allowed.
110-
None
111-
} else if tcx.features().generic_const_exprs() {
112-
let parent_node = tcx.parent_hir_node(hir_id);
113-
debug!(?parent_node);
114-
if let Node::Variant(Variant { disr_expr: Some(constant), .. }) = parent_node
115-
&& constant.hir_id == hir_id
116-
{
117-
// enum variant discriminants are not allowed to use any kind of generics
118-
None
119-
} else if let Some(param_id) =
120-
tcx.hir().opt_const_param_default_param_def_id(hir_id)
107+
match tcx.anon_const_kind(def_id) {
108+
// Stable: anon consts are not able to use any generic parameters...
109+
ty::AnonConstKind::MCGConst => None,
110+
// we provide generics to repeat expr counts as a backwards compatibility hack. #76200
111+
ty::AnonConstKind::RepeatExprCount => Some(parent_did),
112+
113+
// Even GCE anon const should not be allowed to use generic parameters as it would be
114+
// trivially forward declared uses once desugared. E.g. `const N: [u8; ANON::<N>]`.
115+
//
116+
// We could potentially mirror the hack done for defaults of generic parameters but
117+
// this case just doesn't come up much compared to `const N: u32 = ...`. Long term the
118+
// hack for defaulted parameters should be removed eventually anyway.
119+
ty::AnonConstKind::GCEConst if in_param_ty => None,
120+
// GCE anon consts as a default for a generic parameter should have their provided generics
121+
// "truncated" up to whatever generic parameter this anon const is within the default of.
122+
//
123+
// FIXME(generic_const_exprs): This only handles `const N: usize = /*defid*/` but not type
124+
// parameter defaults, e.g. `T = Foo</*defid*/>`.
125+
ty::AnonConstKind::GCEConst
126+
if let Some(param_id) =
127+
tcx.hir().opt_const_param_default_param_def_id(hir_id) =>
121128
{
122129
// If the def_id we are calling generics_of on is an anon ct default i.e:
123130
//
@@ -161,36 +168,17 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
161168
has_self: generics.has_self,
162169
has_late_bound_regions: generics.has_late_bound_regions,
163170
};
164-
} else {
165-
// HACK(eddyb) this provides the correct generics when
166-
// `feature(generic_const_expressions)` is enabled, so that const expressions
167-
// used with const generics, e.g. `Foo<{N+1}>`, can work at all.
168-
//
169-
// Note that we do not supply the parent generics when using
170-
// `min_const_generics`.
171-
Some(parent_did)
172171
}
173-
} else {
174-
let parent_node = tcx.parent_hir_node(hir_id);
175-
let parent_node = match parent_node {
176-
Node::ConstArg(ca) => tcx.parent_hir_node(ca.hir_id),
177-
_ => parent_node,
178-
};
179-
match parent_node {
180-
// HACK(eddyb) this provides the correct generics for repeat
181-
// expressions' count (i.e. `N` in `[x; N]`), and explicit
182-
// `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`),
183-
// as they shouldn't be able to cause query cycle errors.
184-
Node::Expr(Expr { kind: ExprKind::Repeat(_, ct), .. })
185-
if ct.anon_const_hir_id() == Some(hir_id) =>
186-
{
187-
Some(parent_did)
188-
}
189-
Node::TyPat(_) => Some(parent_did),
190-
// Field default values inherit the ADT's generics.
191-
Node::Field(_) => Some(parent_did),
192-
_ => None,
172+
ty::AnonConstKind::GCEConst => Some(parent_did),
173+
174+
// Field defaults are allowed to use generic parameters, e.g. `field: u32 = /*defid: N + 1*/`
175+
ty::AnonConstKind::NonTypeSystem
176+
if matches!(tcx.parent_hir_node(hir_id), Node::TyPat(_) | Node::Field(_)) =>
177+
{
178+
Some(parent_did)
193179
}
180+
// Default to no generic parameters for other kinds of anon consts
181+
ty::AnonConstKind::NonTypeSystem => None,
194182
}
195183
}
196184
Node::ConstBlock(_)

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ provide! { tcx, def_id, other, cdata,
429429
doc_link_traits_in_scope => {
430430
tcx.arena.alloc_from_iter(cdata.get_doc_link_traits_in_scope(def_id.index))
431431
}
432+
anon_const_kind => { table }
432433
}
433434

434435
pub(in crate::rmeta) fn provide(providers: &mut Providers) {

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1565,6 +1565,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
15651565
<- tcx.explicit_implied_const_bounds(def_id).skip_binder());
15661566
}
15671567
}
1568+
if let DefKind::AnonConst = def_kind {
1569+
record!(self.tables.anon_const_kind[def_id] <- self.tcx.anon_const_kind(def_id));
1570+
}
15681571
if tcx.impl_method_has_trait_impl_trait_tys(def_id)
15691572
&& let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
15701573
{

compiler/rustc_metadata/src/rmeta/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,7 @@ define_tables! {
469469
doc_link_traits_in_scope: Table<DefIndex, LazyArray<DefId>>,
470470
assumed_wf_types_for_rpitit: Table<DefIndex, LazyArray<(Ty<'static>, Span)>>,
471471
opaque_ty_origin: Table<DefIndex, LazyValue<hir::OpaqueTyOrigin<DefId>>>,
472+
anon_const_kind: Table<DefIndex, LazyValue<ty::AnonConstKind>>,
472473
}
473474

474475
#[derive(TyEncodable, TyDecodable)]

compiler/rustc_middle/src/query/erase.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ trivial! {
300300
rustc_middle::ty::Asyncness,
301301
rustc_middle::ty::AsyncDestructor,
302302
rustc_middle::ty::BoundVariableKind,
303+
rustc_middle::ty::AnonConstKind,
303304
rustc_middle::ty::DeducedParamAttrs,
304305
rustc_middle::ty::Destructor,
305306
rustc_middle::ty::fast_reject::SimplifiedType,

compiler/rustc_middle/src/query/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2513,6 +2513,12 @@ rustc_queries! {
25132513
desc { "estimating codegen size of `{}`", key }
25142514
cache_on_disk_if { true }
25152515
}
2516+
2517+
query anon_const_kind(def_id: DefId) -> ty::AnonConstKind {
2518+
desc { |tcx| "looking up anon const kind of `{}`", tcx.def_path_str(def_id) }
2519+
cache_on_disk_if { def_id.is_local() }
2520+
separate_provide_extern
2521+
}
25162522
}
25172523

25182524
rustc_query_append! { define_callbacks! }

compiler/rustc_middle/src/ty/consts.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::borrow::Cow;
22

33
use rustc_data_structures::intern::Interned;
44
use rustc_error_messages::MultiSpan;
5-
use rustc_macros::HashStable;
5+
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
66
use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
77

88
use crate::ty::{self, Ty, TyCtxt};
@@ -244,3 +244,11 @@ impl<'tcx> Const<'tcx> {
244244
matches!(self.kind(), ty::ConstKind::Infer(_))
245245
}
246246
}
247+
248+
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable, HashStable)]
249+
pub enum AnonConstKind {
250+
GCEConst,
251+
MCGConst,
252+
RepeatExprCount,
253+
NonTypeSystem,
254+
}

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ pub use self::closure::{
6060
place_to_string_for_capture,
6161
};
6262
pub use self::consts::{
63-
Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree, ValTreeKind,
64-
Value,
63+
AnonConstKind, Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst,
64+
ValTree, ValTreeKind, Value,
6565
};
6666
pub use self::context::{
6767
CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt,

compiler/rustc_middle/src/ty/parameterized.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ trivially_parameterized_over_tcx! {
6666
crate::mir::ConstQualifs,
6767
ty::AssocItemContainer,
6868
ty::Asyncness,
69+
ty::AnonConstKind,
6970
ty::DeducedParamAttrs,
7071
ty::Generics,
7172
ty::ImplPolarity,

compiler/rustc_trait_selection/src/traits/mod.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,8 @@ pub fn try_evaluate_const<'tcx>(
555555
//
556556
// FIXME: `const_eval_resolve_for_typeck` should probably just modify the env itself
557557
// instead of having this logic here
558-
let (args, typing_env) = if tcx.features().generic_const_exprs()
558+
let (args, typing_env) = if tcx.def_kind(uv.def) == DefKind::AnonConst
559+
&& let ty::AnonConstKind::GCEConst = tcx.anon_const_kind(uv.def)
559560
&& uv.has_non_region_infer()
560561
{
561562
// `feature(generic_const_exprs)` causes anon consts to inherit all parent generics. This can cause
@@ -584,7 +585,10 @@ pub fn try_evaluate_const<'tcx>(
584585
(args, typing_env)
585586
}
586587
}
587-
} else if tcx.def_kind(uv.def) == DefKind::AnonConst && uv.has_non_region_infer() {
588+
} else if tcx.def_kind(uv.def) == DefKind::AnonConst
589+
&& let ty::AnonConstKind::RepeatExprCount = tcx.anon_const_kind(uv.def)
590+
&& uv.has_non_region_infer()
591+
{
588592
// FIXME: remove this when `const_evaluatable_unchecked` is a hard error.
589593
//
590594
// Diagnostics will sometimes replace the identity args of anon consts in
@@ -601,6 +605,7 @@ pub fn try_evaluate_const<'tcx>(
601605

602606
let args = GenericArgs::identity_for_item(tcx, uv.def);
603607
let typing_env = ty::TypingEnv::post_analysis(tcx, uv.def);
608+
604609
(args, typing_env)
605610
} else {
606611
// FIXME: This codepath is reachable under `associated_const_equality` and in the

0 commit comments

Comments
 (0)