Skip to content

Commit 52bf0cf

Browse files
committed
Auto merge of rust-lang#140553 - BoxyUwU:defer_type_system_ctfe, r=compiler-errors
Defer evaluating type system constants when they use infers or params Split out of rust-lang#137972, the parts necessary for associated const equality and min generic const args to make progress and have correct semantics around when CTFE is invoked. According to a [previous perf run](https://perf.rust-lang.org/compare.html?start=93257e2d20809d82d1bc0fcc1942480d1a66d7cd&end=01b4cbf0f47c3f782330db88fa5ba199bba1f8a2&stat=instructions:u) of adding the new `const_arg_kind` query we should expect minor regressions here. I think this is acceptable as we should be able to remove this query relatively soon once mgca is more complete as we'll then be able to implement GCE in terms of mgca and rip out `GCEConst` at which point it's trivial to determine what kind of anon const we're dealing with (either it has generics and is a repeat expr hack, or it doesnt and is a normal anon const). This should only affect unstable code as we handle repeat exprs specially and those are the only kinds of type system consts that are allowed to make use of generic parameters. Fixes rust-lang#133066 Fixes rust-lang#133199 Fixes rust-lang#136894 Fixes rust-lang#137813 r? compiler-errors
2 parents e7f4317 + fdccb42 commit 52bf0cf

31 files changed

+546
-189
lines changed

compiler/rustc_hir_analysis/src/collect.rs

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

compiler/rustc_hir_analysis/src/collect/generics_of.rs

Lines changed: 30 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -104,19 +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) = 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::MCG => 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::GCE 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::GCE
126+
if let Some(param_id) =
127+
tcx.hir_opt_const_param_default_param_def_id(hir_id) =>
120128
{
121129
// If the def_id we are calling generics_of on is an anon ct default i.e:
122130
//
@@ -160,36 +168,17 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
160168
has_self: generics.has_self,
161169
has_late_bound_regions: generics.has_late_bound_regions,
162170
};
163-
} else {
164-
// HACK(eddyb) this provides the correct generics when
165-
// `feature(generic_const_expressions)` is enabled, so that const expressions
166-
// used with const generics, e.g. `Foo<{N+1}>`, can work at all.
167-
//
168-
// Note that we do not supply the parent generics when using
169-
// `min_const_generics`.
170-
Some(parent_did)
171171
}
172-
} else {
173-
let parent_node = tcx.parent_hir_node(hir_id);
174-
let parent_node = match parent_node {
175-
Node::ConstArg(ca) => tcx.parent_hir_node(ca.hir_id),
176-
_ => parent_node,
177-
};
178-
match parent_node {
179-
// HACK(eddyb) this provides the correct generics for repeat
180-
// expressions' count (i.e. `N` in `[x; N]`), and explicit
181-
// `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`),
182-
// as they shouldn't be able to cause query cycle errors.
183-
Node::Expr(Expr { kind: ExprKind::Repeat(_, ct), .. })
184-
if ct.anon_const_hir_id() == Some(hir_id) =>
185-
{
186-
Some(parent_did)
187-
}
188-
Node::TyPat(_) => Some(parent_did),
189-
// Field default values inherit the ADT's generics.
190-
Node::Field(_) => Some(parent_did),
191-
_ => None,
172+
ty::AnonConstKind::GCE => 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)
192179
}
180+
// Default to no generic parameters for other kinds of anon consts
181+
ty::AnonConstKind::NonTypeSystem => None,
193182
}
194183
}
195184
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
@@ -425,6 +425,7 @@ provide! { tcx, def_id, other, cdata,
425425
doc_link_traits_in_scope => {
426426
tcx.arena.alloc_from_iter(cdata.get_doc_link_traits_in_scope(def_id.index))
427427
}
428+
anon_const_kind => { table }
428429
}
429430

430431
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
@@ -1569,6 +1569,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
15691569
<- tcx.explicit_implied_const_bounds(def_id).skip_binder());
15701570
}
15711571
}
1572+
if let DefKind::AnonConst = def_kind {
1573+
record!(self.tables.anon_const_kind[def_id] <- self.tcx.anon_const_kind(def_id));
1574+
}
15721575
if tcx.impl_method_has_trait_impl_trait_tys(def_id)
15731576
&& let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
15741577
{

compiler/rustc_metadata/src/rmeta/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,7 @@ define_tables! {
480480
doc_link_traits_in_scope: Table<DefIndex, LazyArray<DefId>>,
481481
assumed_wf_types_for_rpitit: Table<DefIndex, LazyArray<(Ty<'static>, Span)>>,
482482
opaque_ty_origin: Table<DefIndex, LazyValue<hir::OpaqueTyOrigin<DefId>>>,
483+
anon_const_kind: Table<DefIndex, LazyValue<ty::AnonConstKind>>,
483484
}
484485

485486
#[derive(TyEncodable, TyDecodable)]

compiler/rustc_middle/src/query/erase.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ trivial! {
316316
rustc_middle::ty::Asyncness,
317317
rustc_middle::ty::AsyncDestructor,
318318
rustc_middle::ty::BoundVariableKind,
319+
rustc_middle::ty::AnonConstKind,
319320
rustc_middle::ty::DeducedParamAttrs,
320321
rustc_middle::ty::Destructor,
321322
rustc_middle::ty::fast_reject::SimplifiedType,

compiler/rustc_middle/src/query/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2592,6 +2592,11 @@ rustc_queries! {
25922592
desc { "estimating codegen size of `{}`", key }
25932593
cache_on_disk_if { true }
25942594
}
2595+
2596+
query anon_const_kind(def_id: DefId) -> ty::AnonConstKind {
2597+
desc { |tcx| "looking up anon const kind of `{}`", tcx.def_path_str(def_id) }
2598+
separate_provide_extern
2599+
}
25952600
}
25962601

25972602
rustc_with_all_queries! { define_callbacks! }

compiler/rustc_middle/src/ty/consts.rs

Lines changed: 14 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::walk::TypeWalker;
77
use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
88

@@ -259,3 +259,16 @@ impl<'tcx> Const<'tcx> {
259259
TypeWalker::new(self.into())
260260
}
261261
}
262+
263+
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable, HashStable)]
264+
pub enum AnonConstKind {
265+
/// `feature(generic_const_exprs)` anon consts are allowed to use arbitrary generic parameters in scope
266+
GCE,
267+
/// stable `min_const_generics` anon consts are not allowed to use any generic parameters
268+
MCG,
269+
/// anon consts used as the length of a repeat expr are syntactically allowed to use generic parameters
270+
/// but must not depend on the actual instantiation. See #76200 for more information
271+
RepeatExprCount,
272+
/// anon consts outside of the type system, e.g. enum discriminants
273+
NonTypeSystem,
274+
}

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ pub use self::closure::{
7474
place_to_string_for_capture,
7575
};
7676
pub use self::consts::{
77-
Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree, ValTreeKind,
78-
Value,
77+
AnonConstKind, Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst,
78+
ValTree, ValTreeKind, Value,
7979
};
8080
pub use self::context::{
8181
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
@@ -68,6 +68,7 @@ trivially_parameterized_over_tcx! {
6868
ty::AsyncDestructor,
6969
ty::AssocItemContainer,
7070
ty::Asyncness,
71+
ty::AnonConstKind,
7172
ty::DeducedParamAttrs,
7273
ty::Destructor,
7374
ty::Generics,

0 commit comments

Comments
 (0)