diff options
6 files changed, 85 insertions, 79 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index dfe9d7af3ad..8b9fae732c1 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1836,9 +1836,9 @@ fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKin match tcx.hir_node(const_arg_id) { hir::Node::ConstArg(_) => { if tcx.features().generic_const_exprs() { - ty::AnonConstKind::GCEConst + ty::AnonConstKind::GCE } else if tcx.features().min_generic_const_args() { - ty::AnonConstKind::MCGConst + ty::AnonConstKind::MCG } else if let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Repeat(_, repeat_count), .. @@ -1847,7 +1847,7 @@ fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKin { ty::AnonConstKind::RepeatExprCount } else { - ty::AnonConstKind::MCGConst + ty::AnonConstKind::MCG } } _ => ty::AnonConstKind::NonTypeSystem, diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index d261f3f85fe..7eb896f0bf1 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -106,7 +106,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { match tcx.anon_const_kind(def_id) { // Stable: anon consts are not able to use any generic parameters... - ty::AnonConstKind::MCGConst => None, + ty::AnonConstKind::MCG => None, // we provide generics to repeat expr counts as a backwards compatibility hack. #76200 ty::AnonConstKind::RepeatExprCount => Some(parent_did), @@ -116,13 +116,13 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { // 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, + ty::AnonConstKind::GCE 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 + ty::AnonConstKind::GCE if let Some(param_id) = tcx.hir_opt_const_param_default_param_def_id(hir_id) => { @@ -169,7 +169,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { has_late_bound_regions: generics.has_late_bound_regions, }; } - ty::AnonConstKind::GCEConst => Some(parent_did), + ty::AnonConstKind::GCE => Some(parent_did), // Field defaults are allowed to use generic parameters, e.g. `field: u32 = /*defid: N + 1*/` ty::AnonConstKind::NonTypeSystem diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 2e8a2bceb38..6937b54eba2 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -2589,7 +2589,6 @@ rustc_queries! { 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 } } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index f1ea2152f3b..455ac660412 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -262,8 +262,13 @@ impl<'tcx> Const<'tcx> { #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable, HashStable)] pub enum AnonConstKind { - GCEConst, - MCGConst, + /// `feature(generic_const_exprs)` anon consts are allowed to use arbitrary generic parameters in scope + GCE, + /// stable `min_const_generics` anon consts are not allowed to use any generic parameters + MCG, + /// anon consts used as the length of a repeat expr are syntactically allowed to use generic parameters + /// but must not depend on the actual instantiation. See #76200 for more information RepeatExprCount, + /// anon consts outside of the type system, e.g. enum discriminants NonTypeSystem, } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index c174de44558..d8e83dc72b0 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -542,6 +542,9 @@ pub fn try_evaluate_const<'tcx>( | ty::ConstKind::Placeholder(_) | ty::ConstKind::Expr(_) => Err(EvaluateConstErr::HasGenericsOrInfers), ty::ConstKind::Unevaluated(uv) => { + let opt_anon_const_kind = + (tcx.def_kind(uv.def) == DefKind::AnonConst).then(|| tcx.anon_const_kind(uv.def)); + // Postpone evaluation of constants that depend on generic parameters or // inference variables. // @@ -553,87 +556,84 @@ 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.def_kind(uv.def) == DefKind::AnonConst - && let ty::AnonConstKind::GCEConst = tcx.anon_const_kind(uv.def) - { + let (args, typing_env) = match opt_anon_const_kind { // We handle `generic_const_exprs` separately as reasonable ways of handling constants in the type system // completely fall apart under `generic_const_exprs` and makes this whole function Really hard to reason // about if you have to consider gce whatsoever. - - if uv.has_non_region_infer() || uv.has_non_region_param() { - // `feature(generic_const_exprs)` causes anon consts to inherit all parent generics. This can cause - // inference variables and generic parameters to show up in `ty::Const` even though the anon const - // does not actually make use of them. We handle this case specially and attempt to evaluate anyway. - match tcx.thir_abstract_const(uv.def) { - Ok(Some(ct)) => { - let ct = tcx.expand_abstract_consts(ct.instantiate(tcx, uv.args)); - if let Err(e) = ct.error_reported() { - return Err(EvaluateConstErr::EvaluationFailure(e)); - } else if ct.has_non_region_infer() || ct.has_non_region_param() { - // If the anon const *does* actually use generic parameters or inference variables from - // the generic arguments provided for it, then we should *not* attempt to evaluate it. - return Err(EvaluateConstErr::HasGenericsOrInfers); - } else { - let args = - replace_param_and_infer_args_with_placeholder(tcx, uv.args); - let typing_env = infcx - .typing_env(tcx.erase_regions(param_env)) - .with_post_analysis_normalized(tcx); + Some(ty::AnonConstKind::GCE) => { + if uv.has_non_region_infer() || uv.has_non_region_param() { + // `feature(generic_const_exprs)` causes anon consts to inherit all parent generics. This can cause + // inference variables and generic parameters to show up in `ty::Const` even though the anon const + // does not actually make use of them. We handle this case specially and attempt to evaluate anyway. + match tcx.thir_abstract_const(uv.def) { + Ok(Some(ct)) => { + let ct = tcx.expand_abstract_consts(ct.instantiate(tcx, uv.args)); + if let Err(e) = ct.error_reported() { + return Err(EvaluateConstErr::EvaluationFailure(e)); + } else if ct.has_non_region_infer() || ct.has_non_region_param() { + // If the anon const *does* actually use generic parameters or inference variables from + // the generic arguments provided for it, then we should *not* attempt to evaluate it. + return Err(EvaluateConstErr::HasGenericsOrInfers); + } else { + let args = + replace_param_and_infer_args_with_placeholder(tcx, uv.args); + let typing_env = infcx + .typing_env(tcx.erase_regions(param_env)) + .with_post_analysis_normalized(tcx); + (args, typing_env) + } + } + Err(_) | Ok(None) => { + let args = GenericArgs::identity_for_item(tcx, uv.def); + let typing_env = ty::TypingEnv::post_analysis(tcx, uv.def); (args, typing_env) } } - Err(_) | Ok(None) => { - let args = GenericArgs::identity_for_item(tcx, uv.def); - let typing_env = ty::TypingEnv::post_analysis(tcx, uv.def); - (args, typing_env) - } + } else { + let typing_env = infcx + .typing_env(tcx.erase_regions(param_env)) + .with_post_analysis_normalized(tcx); + (uv.args, typing_env) } - } else { - let typing_env = infcx - .typing_env(tcx.erase_regions(param_env)) - .with_post_analysis_normalized(tcx); - (uv.args, typing_env) - } - } else if tcx.def_kind(uv.def) == DefKind::AnonConst - && let ty::AnonConstKind::RepeatExprCount = tcx.anon_const_kind(uv.def) - { - if uv.has_non_region_infer() { - // Diagnostics will sometimes replace the identity args of anon consts in - // array repeat expr counts with inference variables so we have to handle this - // even though it is not something we should ever actually encounter. - // - // Array repeat expr counts are allowed to syntactically use generic parameters - // but must not actually depend on them in order to evalaute successfully. This means - // that it is actually fine to evalaute them in their own environment rather than with - // the actually provided generic arguments. - tcx.dcx().delayed_bug( - "Encountered anon const with inference variable args but no error reported", - ); } + Some(ty::AnonConstKind::RepeatExprCount) => { + if uv.has_non_region_infer() { + // Diagnostics will sometimes replace the identity args of anon consts in + // array repeat expr counts with inference variables so we have to handle this + // even though it is not something we should ever actually encounter. + // + // Array repeat expr counts are allowed to syntactically use generic parameters + // but must not actually depend on them in order to evalaute successfully. This means + // that it is actually fine to evalaute them in their own environment rather than with + // the actually provided generic arguments. + tcx.dcx().delayed_bug("AnonConst with infer args but no error reported"); + } - // The generic args of repeat expr counts under `min_const_generics` are not supposed to - // affect evaluation of the constant as this would make it a "truly" generic const arg. - // To prevent this we discard all the generic arguments and evalaute with identity args - // and in its own environment instead of the current environment we are normalizing in. - let args = GenericArgs::identity_for_item(tcx, uv.def); - let typing_env = ty::TypingEnv::post_analysis(tcx, uv.def); + // The generic args of repeat expr counts under `min_const_generics` are not supposed to + // affect evaluation of the constant as this would make it a "truly" generic const arg. + // To prevent this we discard all the generic arguments and evalaute with identity args + // and in its own environment instead of the current environment we are normalizing in. + let args = GenericArgs::identity_for_item(tcx, uv.def); + let typing_env = ty::TypingEnv::post_analysis(tcx, uv.def); - (args, typing_env) - } else { - // We are only dealing with "truly" generic/uninferred constants here: - // - GCEConsts have been handled separately - // - Repeat expr count back compat consts have also been handled separately - // So we are free to simply defer evaluation here. - // - // FIXME: This assumes that `args` are normalized which is not necessarily true - if uv.args.has_non_region_param() || uv.args.has_non_region_infer() { - return Err(EvaluateConstErr::HasGenericsOrInfers); + (args, typing_env) } + _ => { + // We are only dealing with "truly" generic/uninferred constants here: + // - GCEConsts have been handled separately + // - Repeat expr count back compat consts have also been handled separately + // So we are free to simply defer evaluation here. + // + // FIXME: This assumes that `args` are normalized which is not necessarily true + if uv.args.has_non_region_param() || uv.args.has_non_region_infer() { + return Err(EvaluateConstErr::HasGenericsOrInfers); + } - let typing_env = infcx - .typing_env(tcx.erase_regions(param_env)) - .with_post_analysis_normalized(tcx); - (uv.args, typing_env) + let typing_env = infcx + .typing_env(tcx.erase_regions(param_env)) + .with_post_analysis_normalized(tcx); + (uv.args, typing_env) + } }; let uv = ty::UnevaluatedConst::new(uv.def, args); diff --git a/tests/ui/const-generics/associated_const_equality/unconstrained_impl_param.rs b/tests/ui/const-generics/associated_const_equality/unconstrained_impl_param.rs index 19cddb71b01..99318ef7598 100644 --- a/tests/ui/const-generics/associated_const_equality/unconstrained_impl_param.rs +++ b/tests/ui/const-generics/associated_const_equality/unconstrained_impl_param.rs @@ -22,3 +22,5 @@ where //~^ ERROR type mismatch resolving { } + +fn main() {} |
