@@ -545,7 +545,7 @@ pub fn try_evaluate_const<'tcx>(
545
545
// Postpone evaluation of constants that depend on generic parameters or
546
546
// inference variables.
547
547
//
548
- // We use `TypingMode::PostAnalysis` here which is not *technically* correct
548
+ // We use `TypingMode::PostAnalysis` here which is not *technically* correct
549
549
// to be revealing opaque types here as borrowcheck has not run yet. However,
550
550
// CTFE itself uses `TypingMode::PostAnalysis` unconditionally even during
551
551
// typeck and not doing so has a lot of (undesirable) fallout (#101478, #119821).
@@ -555,68 +555,90 @@ pub fn try_evaluate_const<'tcx>(
555
555
// instead of having this logic here
556
556
let ( args, typing_env) = if tcx. def_kind ( uv. def ) == DefKind :: AnonConst
557
557
&& let ty:: AnonConstKind :: GCEConst = tcx. anon_const_kind ( uv. def )
558
- && uv. has_non_region_infer ( )
559
558
{
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 ) ;
577
588
( args, typing_env)
578
589
}
579
590
}
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 )
585
596
}
586
597
} else if tcx. def_kind ( uv. def ) == DefKind :: AnonConst
587
598
&& let ty:: AnonConstKind :: RepeatExprCount = tcx. anon_const_kind ( uv. def )
588
- && uv. has_non_region_infer ( )
589
599
{
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
+ }
603
613
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.
604
618
let args = GenericArgs :: identity_for_item ( tcx, uv. def ) ;
605
619
let typing_env = ty:: TypingEnv :: post_analysis ( tcx, uv. def ) ;
606
620
607
621
( args, typing_env)
608
622
} 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
+
612
633
let typing_env = infcx
613
634
. typing_env ( tcx. erase_regions ( param_env) )
614
635
. with_post_analysis_normalized ( tcx) ;
615
636
( uv. args , typing_env)
616
637
} ;
617
- let uv = ty:: UnevaluatedConst :: new ( uv. def , args) ;
618
638
639
+ let uv = ty:: UnevaluatedConst :: new ( uv. def , args) ;
619
640
let erased_uv = tcx. erase_regions ( uv) ;
641
+
620
642
use rustc_middle:: mir:: interpret:: ErrorHandled ;
621
643
match tcx. const_eval_resolve_for_typeck ( typing_env, erased_uv, DUMMY_SP ) {
622
644
Ok ( Ok ( val) ) => Ok ( ty:: Const :: new_value (
0 commit comments