@@ -545,7 +545,7 @@ pub fn try_evaluate_const<'tcx>(
545545 // Postpone evaluation of constants that depend on generic parameters or
546546 // inference variables.
547547 //
548- // We use `TypingMode::PostAnalysis` here which is not *technically* correct
548+ // We use `TypingMode::PostAnalysis` here which is not *technically* correct
549549 // to be revealing opaque types here as borrowcheck has not run yet. However,
550550 // CTFE itself uses `TypingMode::PostAnalysis` unconditionally even during
551551 // typeck and not doing so has a lot of (undesirable) fallout (#101478, #119821).
@@ -555,68 +555,90 @@ pub fn try_evaluate_const<'tcx>(
555555 // instead of having this logic here
556556 let ( args, typing_env) = if tcx. def_kind ( uv. def ) == DefKind :: AnonConst
557557 && let ty:: AnonConstKind :: GCEConst = tcx. anon_const_kind ( uv. def )
558- && uv. has_non_region_infer ( )
559558 {
560- // `feature(generic_const_exprs)` causes anon consts to inherit all parent generics. This can cause
561- // inference variables and generic parameters to show up in `ty::Const` even though the anon const
562- // does not actually make use of them. We handle this case specially and attempt to evaluate anyway.
563- match tcx. thir_abstract_const ( uv. def ) {
564- Ok ( Some ( ct) ) => {
565- let ct = tcx. expand_abstract_consts ( ct. instantiate ( tcx, uv. args ) ) ;
566- if let Err ( e) = ct. error_reported ( ) {
567- return Err ( EvaluateConstErr :: EvaluationFailure ( e) ) ;
568- } else if ct. has_non_region_infer ( ) || ct. has_non_region_param ( ) {
569- // If the anon const *does* actually use generic parameters or inference variables from
570- // the generic arguments provided for it, then we should *not* attempt to evaluate it.
571- return Err ( EvaluateConstErr :: HasGenericsOrInfers ) ;
572- } else {
573- let args = replace_param_and_infer_args_with_placeholder ( tcx, uv. args ) ;
574- let typing_env = infcx
575- . typing_env ( tcx. erase_regions ( param_env) )
576- . with_post_analysis_normalized ( tcx) ;
559+ // We handle `generic_const_exprs` separately as reasonable ways of handling constants in the type system
560+ // completely fall apart under `generic_const_exprs` and makes this whole function Really hard to reason
561+ // 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) ;
582+ ( args, typing_env)
583+ }
584+ }
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 ) ;
577588 ( args, typing_env)
578589 }
579590 }
580- Err ( _ ) | Ok ( None ) => {
581- let args = GenericArgs :: identity_for_item ( tcx , uv . def ) ;
582- let typing_env = ty :: TypingEnv :: post_analysis ( tcx, uv . def ) ;
583- ( args , typing_env )
584- }
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 )
585596 }
586597 } else if tcx. def_kind ( uv. def ) == DefKind :: AnonConst
587598 && let ty:: AnonConstKind :: RepeatExprCount = tcx. anon_const_kind ( uv. def )
588- && uv. has_non_region_infer ( )
589599 {
590- // FIXME: remove this when `const_evaluatable_unchecked` is a hard error.
591- //
592- // Diagnostics will sometimes replace the identity args of anon consts in
593- // array repeat expr counts with inference variables so we have to handle this
594- // even though it is not something we should ever actually encounter.
595- //
596- // Array repeat expr counts are allowed to syntactically use generic parameters
597- // but must not actually depend on them in order to evalaute successfully. This means
598- // that it is actually fine to evalaute them in their own environment rather than with
599- // the actually provided generic arguments.
600- tcx . dcx ( ) . delayed_bug (
601- "Encountered anon const with inference variable args but no error reported" ,
602- ) ;
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+ ) ;
612+ }
603613
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.
604618 let args = GenericArgs :: identity_for_item ( tcx, uv. def ) ;
605619 let typing_env = ty:: TypingEnv :: post_analysis ( tcx, uv. def ) ;
606620
607621 ( args, typing_env)
608622 } else {
609- // FIXME: This codepath is reachable under `associated_const_equality` and in the
610- // future will be reachable by `min_generic_const_args`. We should handle inference
611- // variables and generic parameters properly instead of doing nothing.
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 ) ;
631+ }
632+
612633 let typing_env = infcx
613634 . typing_env ( tcx. erase_regions ( param_env) )
614635 . with_post_analysis_normalized ( tcx) ;
615636 ( uv. args , typing_env)
616637 } ;
617- let uv = ty:: UnevaluatedConst :: new ( uv. def , args) ;
618638
639+ let uv = ty:: UnevaluatedConst :: new ( uv. def , args) ;
619640 let erased_uv = tcx. erase_regions ( uv) ;
641+
620642 use rustc_middle:: mir:: interpret:: ErrorHandled ;
621643 match tcx. const_eval_resolve_for_typeck ( typing_env, erased_uv, DUMMY_SP ) {
622644 Ok ( Ok ( val) ) => Ok ( ty:: Const :: new_value (
0 commit comments