@@ -547,7 +547,7 @@ pub fn try_evaluate_const<'tcx>(
547
547
// Postpone evaluation of constants that depend on generic parameters or
548
548
// inference variables.
549
549
//
550
- // We use `TypingMode::PostAnalysis` here which is not *technically* correct
550
+ // We use `TypingMode::PostAnalysis` here which is not *technically* correct
551
551
// to be revealing opaque types here as borrowcheck has not run yet. However,
552
552
// CTFE itself uses `TypingMode::PostAnalysis` unconditionally even during
553
553
// typeck and not doing so has a lot of (undesirable) fallout (#101478, #119821).
@@ -557,68 +557,90 @@ pub fn try_evaluate_const<'tcx>(
557
557
// instead of having this logic here
558
558
let ( args, typing_env) = if tcx. def_kind ( uv. def ) == DefKind :: AnonConst
559
559
&& let ty:: AnonConstKind :: GCEConst = tcx. anon_const_kind ( uv. def )
560
- && uv. has_non_region_infer ( )
561
560
{
562
- // `feature(generic_const_exprs)` causes anon consts to inherit all parent generics. This can cause
563
- // inference variables and generic parameters to show up in `ty::Const` even though the anon const
564
- // does not actually make use of them. We handle this case specially and attempt to evaluate anyway.
565
- match tcx. thir_abstract_const ( uv. def ) {
566
- Ok ( Some ( ct) ) => {
567
- let ct = tcx. expand_abstract_consts ( ct. instantiate ( tcx, uv. args ) ) ;
568
- if let Err ( e) = ct. error_reported ( ) {
569
- return Err ( EvaluateConstErr :: EvaluationFailure ( e) ) ;
570
- } else if ct. has_non_region_infer ( ) || ct. has_non_region_param ( ) {
571
- // If the anon const *does* actually use generic parameters or inference variables from
572
- // the generic arguments provided for it, then we should *not* attempt to evaluate it.
573
- return Err ( EvaluateConstErr :: HasGenericsOrInfers ) ;
574
- } else {
575
- let args = replace_param_and_infer_args_with_placeholder ( tcx, uv. args ) ;
576
- let typing_env = infcx
577
- . typing_env ( tcx. erase_regions ( param_env) )
578
- . with_post_analysis_normalized ( tcx) ;
561
+ // We handle `generic_const_exprs` separately as reasonable ways of handling constants in the type system
562
+ // completely fall apart under `generic_const_exprs` and makes this whole function Really hard to reason
563
+ // about if you have to consider gce whatsoever.
564
+
565
+ if uv. has_non_region_infer ( ) || uv. has_non_region_param ( ) {
566
+ // `feature(generic_const_exprs)` causes anon consts to inherit all parent generics. This can cause
567
+ // inference variables and generic parameters to show up in `ty::Const` even though the anon const
568
+ // does not actually make use of them. We handle this case specially and attempt to evaluate anyway.
569
+ match tcx. thir_abstract_const ( uv. def ) {
570
+ Ok ( Some ( ct) ) => {
571
+ let ct = tcx. expand_abstract_consts ( ct. instantiate ( tcx, uv. args ) ) ;
572
+ if let Err ( e) = ct. error_reported ( ) {
573
+ return Err ( EvaluateConstErr :: EvaluationFailure ( e) ) ;
574
+ } else if ct. has_non_region_infer ( ) || ct. has_non_region_param ( ) {
575
+ // If the anon const *does* actually use generic parameters or inference variables from
576
+ // the generic arguments provided for it, then we should *not* attempt to evaluate it.
577
+ return Err ( EvaluateConstErr :: HasGenericsOrInfers ) ;
578
+ } else {
579
+ let args =
580
+ replace_param_and_infer_args_with_placeholder ( tcx, uv. args ) ;
581
+ let typing_env = infcx
582
+ . typing_env ( tcx. erase_regions ( param_env) )
583
+ . with_post_analysis_normalized ( tcx) ;
584
+ ( args, typing_env)
585
+ }
586
+ }
587
+ Err ( _) | Ok ( None ) => {
588
+ let args = GenericArgs :: identity_for_item ( tcx, uv. def ) ;
589
+ let typing_env = ty:: TypingEnv :: post_analysis ( tcx, uv. def ) ;
579
590
( args, typing_env)
580
591
}
581
592
}
582
- Err ( _ ) | Ok ( None ) => {
583
- let args = GenericArgs :: identity_for_item ( tcx , uv . def ) ;
584
- let typing_env = ty :: TypingEnv :: post_analysis ( tcx, uv . def ) ;
585
- ( args , typing_env )
586
- }
593
+ } else {
594
+ let typing_env = infcx
595
+ . typing_env ( tcx. erase_regions ( param_env ) )
596
+ . with_post_analysis_normalized ( tcx ) ;
597
+ ( uv . args , typing_env )
587
598
}
588
599
} else if tcx. def_kind ( uv. def ) == DefKind :: AnonConst
589
600
&& let ty:: AnonConstKind :: RepeatExprCount = tcx. anon_const_kind ( uv. def )
590
- && uv. has_non_region_infer ( )
591
601
{
592
- // FIXME: remove this when `const_evaluatable_unchecked` is a hard error.
593
- //
594
- // Diagnostics will sometimes replace the identity args of anon consts in
595
- // array repeat expr counts with inference variables so we have to handle this
596
- // even though it is not something we should ever actually encounter.
597
- //
598
- // Array repeat expr counts are allowed to syntactically use generic parameters
599
- // but must not actually depend on them in order to evalaute successfully. This means
600
- // that it is actually fine to evalaute them in their own environment rather than with
601
- // the actually provided generic arguments.
602
- tcx . dcx ( ) . delayed_bug (
603
- "Encountered anon const with inference variable args but no error reported" ,
604
- ) ;
602
+ if uv . has_non_region_infer ( ) {
603
+ // Diagnostics will sometimes replace the identity args of anon consts in
604
+ // array repeat expr counts with inference variables so we have to handle this
605
+ // even though it is not something we should ever actually encounter.
606
+ //
607
+ // Array repeat expr counts are allowed to syntactically use generic parameters
608
+ // but must not actually depend on them in order to evalaute successfully. This means
609
+ // that it is actually fine to evalaute them in their own environment rather than with
610
+ // the actually provided generic arguments.
611
+ tcx . dcx ( ) . delayed_bug (
612
+ "Encountered anon const with inference variable args but no error reported" ,
613
+ ) ;
614
+ }
605
615
616
+ // The generic args of repeat expr counts under `min_const_generics` are not supposed to
617
+ // affect evaluation of the constant as this would make it a "truly" generic const arg.
618
+ // To prevent this we discard all the generic arguments and evalaute with identity args
619
+ // and in its own environment instead of the current environment we are normalizing in.
606
620
let args = GenericArgs :: identity_for_item ( tcx, uv. def ) ;
607
621
let typing_env = ty:: TypingEnv :: post_analysis ( tcx, uv. def ) ;
608
622
609
623
( args, typing_env)
610
624
} else {
611
- // FIXME: This codepath is reachable under `associated_const_equality` and in the
612
- // future will be reachable by `min_generic_const_args`. We should handle inference
613
- // variables and generic parameters properly instead of doing nothing.
625
+ // We are only dealing with "truly" generic/uninferred constants here:
626
+ // - GCEConsts have been handled separately
627
+ // - Repeat expr count back compat consts have also been handled separately
628
+ // So we are free to simply defer evaluation here.
629
+ //
630
+ // FIXME: This assumes that `args` are normalized which is not necessarily true
631
+ if uv. args . has_non_region_param ( ) || uv. args . has_non_region_infer ( ) {
632
+ return Err ( EvaluateConstErr :: HasGenericsOrInfers ) ;
633
+ }
634
+
614
635
let typing_env = infcx
615
636
. typing_env ( tcx. erase_regions ( param_env) )
616
637
. with_post_analysis_normalized ( tcx) ;
617
638
( uv. args , typing_env)
618
639
} ;
619
- let uv = ty:: UnevaluatedConst :: new ( uv. def , args) ;
620
640
641
+ let uv = ty:: UnevaluatedConst :: new ( uv. def , args) ;
621
642
let erased_uv = tcx. erase_regions ( uv) ;
643
+
622
644
use rustc_middle:: mir:: interpret:: ErrorHandled ;
623
645
match tcx. const_eval_resolve_for_typeck ( typing_env, erased_uv, DUMMY_SP ) {
624
646
Ok ( Ok ( val) ) => Ok ( ty:: Const :: new_value (
0 commit comments