@@ -542,6 +542,9 @@ pub fn try_evaluate_const<'tcx>(
542542 | ty:: ConstKind :: Placeholder ( _)
543543 | ty:: ConstKind :: Expr ( _) => Err ( EvaluateConstErr :: HasGenericsOrInfers ) ,
544544 ty:: ConstKind :: Unevaluated ( uv) => {
545+ let opt_anon_const_kind =
546+ ( tcx. def_kind ( uv. def ) == DefKind :: AnonConst ) . then ( || tcx. anon_const_kind ( uv. def ) ) ;
547+
545548 // Postpone evaluation of constants that depend on generic parameters or
546549 // inference variables.
547550 //
@@ -553,87 +556,90 @@ pub fn try_evaluate_const<'tcx>(
553556 //
554557 // FIXME: `const_eval_resolve_for_typeck` should probably just modify the env itself
555558 // instead of having this logic here
556- let ( args, typing_env) = if tcx. def_kind ( uv. def ) == DefKind :: AnonConst
557- && let ty:: AnonConstKind :: GCEConst = tcx. anon_const_kind ( uv. def )
558- {
559+ let ( args, typing_env) = match opt_anon_const_kind {
559560 // We handle `generic_const_exprs` separately as reasonable ways of handling constants in the type system
560561 // completely fall apart under `generic_const_exprs` and makes this whole function Really hard to reason
561562 // about if you have to consider gce whatsoever.
562-
563- if uv. has_non_region_infer ( ) || uv. has_non_region_param ( ) {
564- // `feature(generic_const_exprs)` causes anon consts to inherit all parent generics. This can cause
565- // inference variables and generic parameters to show up in `ty::Const` even though the anon const
566- // does not actually make use of them. We handle this case specially and attempt to evaluate anyway.
567- match tcx. thir_abstract_const ( uv. def ) {
568- Ok ( Some ( ct) ) => {
569- let ct = tcx. expand_abstract_consts ( ct. instantiate ( tcx, uv. args ) ) ;
570- if let Err ( e) = ct. error_reported ( ) {
571- return Err ( EvaluateConstErr :: EvaluationFailure ( e) ) ;
572- } else if ct. has_non_region_infer ( ) || ct. has_non_region_param ( ) {
573- // If the anon const *does* actually use generic parameters or inference variables from
574- // the generic arguments provided for it, then we should *not* attempt to evaluate it.
575- return Err ( EvaluateConstErr :: HasGenericsOrInfers ) ;
576- } else {
577- let args =
578- replace_param_and_infer_args_with_placeholder ( tcx, uv. args ) ;
579- let typing_env = infcx
580- . typing_env ( tcx. erase_regions ( param_env) )
581- . with_post_analysis_normalized ( tcx) ;
563+ Some ( ty:: AnonConstKind :: GCE ) => {
564+ if uv. has_non_region_infer ( ) || uv. has_non_region_param ( ) {
565+ // `feature(generic_const_exprs)` causes anon consts to inherit all parent generics. This can cause
566+ // inference variables and generic parameters to show up in `ty::Const` even though the anon const
567+ // does not actually make use of them. We handle this case specially and attempt to evaluate anyway.
568+ match tcx. thir_abstract_const ( uv. def ) {
569+ Ok ( Some ( ct) ) => {
570+ let ct = tcx. expand_abstract_consts ( ct. instantiate ( tcx, uv. args ) ) ;
571+ if let Err ( e) = ct. error_reported ( ) {
572+ return Err ( EvaluateConstErr :: EvaluationFailure ( e) ) ;
573+ } else if ct. has_non_region_infer ( ) || ct. has_non_region_param ( ) {
574+ // If the anon const *does* actually use generic parameters or inference variables from
575+ // the generic arguments provided for it, then we should *not* attempt to evaluate it.
576+ return Err ( EvaluateConstErr :: HasGenericsOrInfers ) ;
577+ } else {
578+ let args =
579+ replace_param_and_infer_args_with_placeholder ( tcx, uv. args ) ;
580+ let typing_env = infcx
581+ . typing_env ( tcx. erase_regions ( param_env) )
582+ . with_post_analysis_normalized ( tcx) ;
583+ ( args, typing_env)
584+ }
585+ }
586+ Err ( _) | Ok ( None ) => {
587+ let args = GenericArgs :: identity_for_item ( tcx, uv. def ) ;
588+ let typing_env = ty:: TypingEnv :: post_analysis ( tcx, uv. def ) ;
582589 ( args, typing_env)
583590 }
584591 }
585- Err ( _ ) | Ok ( None ) => {
586- let args = GenericArgs :: identity_for_item ( tcx , uv . def ) ;
587- let typing_env = ty :: TypingEnv :: post_analysis ( tcx, uv . def ) ;
588- ( args , typing_env )
589- }
592+ } else {
593+ let typing_env = infcx
594+ . typing_env ( tcx. erase_regions ( param_env ) )
595+ . with_post_analysis_normalized ( tcx ) ;
596+ ( uv . args , typing_env )
590597 }
591- } else {
592- let typing_env = infcx
593- . typing_env ( tcx. erase_regions ( param_env) )
594- . with_post_analysis_normalized ( tcx) ;
595- ( uv. args , typing_env)
596- }
597- } else if tcx. def_kind ( uv. def ) == DefKind :: AnonConst
598- && let ty:: AnonConstKind :: RepeatExprCount = tcx. anon_const_kind ( uv. def )
599- {
600- if uv. has_non_region_infer ( ) {
601- // Diagnostics will sometimes replace the identity args of anon consts in
602- // array repeat expr counts with inference variables so we have to handle this
603- // even though it is not something we should ever actually encounter.
604- //
605- // Array repeat expr counts are allowed to syntactically use generic parameters
606- // but must not actually depend on them in order to evalaute successfully. This means
607- // that it is actually fine to evalaute them in their own environment rather than with
608- // the actually provided generic arguments.
609- tcx. dcx ( ) . delayed_bug (
610- "Encountered anon const with inference variable args but no error reported" ,
611- ) ;
612598 }
599+ Some ( ty:: AnonConstKind :: RepeatExprCount ) => {
600+ if uv. has_non_region_infer ( ) {
601+ // Diagnostics will sometimes replace the identity args of anon consts in
602+ // array repeat expr counts with inference variables so we have to handle this
603+ // even though it is not something we should ever actually encounter.
604+ //
605+ // Array repeat expr counts are allowed to syntactically use generic parameters
606+ // but must not actually depend on them in order to evalaute successfully. This means
607+ // that it is actually fine to evalaute them in their own environment rather than with
608+ // the actually provided generic arguments.
609+ tcx. dcx ( ) . delayed_bug ( "AnonConst with infer args but no error reported" ) ;
610+ }
613611
614- // The generic args of repeat expr counts under `min_const_generics` are not supposed to
615- // affect evaluation of the constant as this would make it a "truly" generic const arg.
616- // To prevent this we discard all the generic arguments and evalaute with identity args
617- // and in its own environment instead of the current environment we are normalizing in.
618- let args = GenericArgs :: identity_for_item ( tcx, uv. def ) ;
619- let typing_env = ty:: TypingEnv :: post_analysis ( tcx, uv. def ) ;
612+ // The generic args of repeat expr counts under `min_const_generics` are not supposed to
613+ // affect evaluation of the constant as this would make it a "truly" generic const arg.
614+ // To prevent this we discard all the generic arguments and evalaute with identity args
615+ // and in its own environment instead of the current environment we are normalizing in.
616+ let args = GenericArgs :: identity_for_item ( tcx, uv. def ) ;
617+ let typing_env = ty:: TypingEnv :: post_analysis ( tcx, uv. def ) ;
620618
621- ( args, typing_env)
622- } else {
623- // We are only dealing with "truly" generic/uninferred constants here:
624- // - GCEConsts have been handled separately
625- // - Repeat expr count back compat consts have also been handled separately
626- // So we are free to simply defer evaluation here.
627- //
628- // FIXME: This assumes that `args` are normalized which is not necessarily true
629- if uv. args . has_non_region_param ( ) || uv. args . has_non_region_infer ( ) {
630- return Err ( EvaluateConstErr :: HasGenericsOrInfers ) ;
619+ ( args, typing_env)
631620 }
621+ _ => {
622+ // We are only dealing with "truly" generic/uninferred constants here:
623+ // - GCEConsts have been handled separately
624+ // - Repeat expr count back compat consts have also been handled separately
625+ // So we are free to simply defer evaluation here.
626+ //
627+ // FIXME: This assumes that `args` are normalized which is not necessarily true
628+ //
629+ // Const patterns are converted to type system constants before being
630+ // evaluated. However, we don't care about them here as pattern evaluation
631+ // logic does not go through type system normalization. If it did this would
632+ // be a backwards compatibility problem as we do not enforce "syntactic" non-
633+ // usage of generic parameters like we do here.
634+ if uv. args . has_non_region_param ( ) || uv. args . has_non_region_infer ( ) {
635+ return Err ( EvaluateConstErr :: HasGenericsOrInfers ) ;
636+ }
632637
633- let typing_env = infcx
634- . typing_env ( tcx. erase_regions ( param_env) )
635- . with_post_analysis_normalized ( tcx) ;
636- ( uv. args , typing_env)
638+ let typing_env = infcx
639+ . typing_env ( tcx. erase_regions ( param_env) )
640+ . with_post_analysis_normalized ( tcx) ;
641+ ( uv. args , typing_env)
642+ }
637643 } ;
638644
639645 let uv = ty:: UnevaluatedConst :: new ( uv. def , args) ;
0 commit comments