@@ -39,153 +39,148 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
3939 let tcx = infcx. tcx ;
4040
4141 if tcx. features ( ) . generic_const_exprs {
42- match AbstractConst :: new ( tcx, uv) ? {
43- // We are looking at a generic abstract constant.
44- Some ( ct) => {
45- if satisfied_from_param_env ( tcx, ct, param_env) ? {
46- return Ok ( ( ) ) ;
47- }
48-
49- // We were unable to unify the abstract constant with
50- // a constant found in the caller bounds, there are
51- // now three possible cases here.
52- #[ derive( Debug , Copy , Clone , PartialEq , Eq , PartialOrd , Ord ) ]
53- enum FailureKind {
54- /// The abstract const still references an inference
55- /// variable, in this case we return `TooGeneric`.
56- MentionsInfer ,
57- /// The abstract const references a generic parameter,
58- /// this means that we emit an error here.
59- MentionsParam ,
60- /// The substs are concrete enough that we can simply
61- /// try and evaluate the given constant.
62- Concrete ,
63- }
64- let mut failure_kind = FailureKind :: Concrete ;
65- walk_abstract_const :: < !, _ > ( tcx, ct, |node| match node. root ( tcx) {
66- Node :: Leaf ( leaf) => {
67- if leaf. has_infer_types_or_consts ( ) {
68- failure_kind = FailureKind :: MentionsInfer ;
69- } else if leaf. has_param_types_or_consts ( ) {
70- failure_kind = cmp:: min ( failure_kind, FailureKind :: MentionsParam ) ;
71- }
72-
73- ControlFlow :: CONTINUE
42+ if let Some ( ct) = AbstractConst :: new ( tcx, uv) ? {
43+ if satisfied_from_param_env ( tcx, ct, param_env) ? {
44+ return Ok ( ( ) ) ;
45+ }
46+
47+ // We were unable to unify the abstract constant with
48+ // a constant found in the caller bounds, there are
49+ // now three possible cases here.
50+ #[ derive( Debug , Copy , Clone , PartialEq , Eq , PartialOrd , Ord ) ]
51+ enum FailureKind {
52+ /// The abstract const still references an inference
53+ /// variable, in this case we return `TooGeneric`.
54+ MentionsInfer ,
55+ /// The abstract const references a generic parameter,
56+ /// this means that we emit an error here.
57+ MentionsParam ,
58+ /// The substs are concrete enough that we can simply
59+ /// try and evaluate the given constant.
60+ Concrete ,
61+ }
62+ let mut failure_kind = FailureKind :: Concrete ;
63+ walk_abstract_const :: < !, _ > ( tcx, ct, |node| match node. root ( tcx) {
64+ Node :: Leaf ( leaf) => {
65+ if leaf. has_infer_types_or_consts ( ) {
66+ failure_kind = FailureKind :: MentionsInfer ;
67+ } else if leaf. has_param_types_or_consts ( ) {
68+ failure_kind = cmp:: min ( failure_kind, FailureKind :: MentionsParam ) ;
7469 }
75- Node :: Cast ( _, _, ty) => {
76- if ty. has_infer_types_or_consts ( ) {
77- failure_kind = FailureKind :: MentionsInfer ;
78- } else if ty. has_param_types_or_consts ( ) {
79- failure_kind = cmp:: min ( failure_kind, FailureKind :: MentionsParam ) ;
80- }
8170
82- ControlFlow :: CONTINUE
83- }
84- Node :: Binop ( _, _, _) | Node :: UnaryOp ( _, _) | Node :: FunctionCall ( _, _) => {
85- ControlFlow :: CONTINUE
71+ ControlFlow :: CONTINUE
72+ }
73+ Node :: Cast ( _, _, ty) => {
74+ if ty. has_infer_types_or_consts ( ) {
75+ failure_kind = FailureKind :: MentionsInfer ;
76+ } else if ty. has_param_types_or_consts ( ) {
77+ failure_kind = cmp:: min ( failure_kind, FailureKind :: MentionsParam ) ;
8678 }
87- } ) ;
8879
89- match failure_kind {
90- FailureKind :: MentionsInfer => {
91- return Err ( NotConstEvaluatable :: MentionsInfer ) ;
92- }
93- FailureKind :: MentionsParam => {
94- return Err ( NotConstEvaluatable :: MentionsParam ) ;
95- }
96- FailureKind :: Concrete => {
97- // Dealt with below by the same code which handles this
98- // without the feature gate.
99- }
80+ ControlFlow :: CONTINUE
10081 }
101- }
102- None => {
103- // If we are dealing with a concrete constant, we can
104- // reuse the old code path and try to evaluate
105- // the constant.
106- }
107- }
108- }
82+ Node :: Binop ( _, _, _) | Node :: UnaryOp ( _, _) | Node :: FunctionCall ( _, _) => {
83+ ControlFlow :: CONTINUE
84+ }
85+ } ) ;
10986
110- let future_compat_lint = || {
111- if tcx. features ( ) . generic_const_exprs {
112- return ;
113- }
114- if let Some ( local_def_id) = uv. def . did . as_local ( ) {
115- infcx. tcx . struct_span_lint_hir (
116- lint:: builtin:: CONST_EVALUATABLE_UNCHECKED ,
117- infcx. tcx . hir ( ) . local_def_id_to_hir_id ( local_def_id) ,
118- span,
119- |err| {
120- err. build ( "cannot use constants which depend on generic parameters in types" )
121- . emit ( ) ;
122- } ,
123- ) ;
124- }
125- } ;
126-
127- // FIXME: We should only try to evaluate a given constant here if it is fully concrete
128- // as we don't want to allow things like `[u8; std::mem::size_of::<*mut T>()]`.
129- //
130- // We previously did not check this, so we only emit a future compat warning if
131- // const evaluation succeeds and the given constant is still polymorphic for now
132- // and hopefully soon change this to an error.
133- //
134- // See #74595 for more details about this.
135- let concrete = infcx. const_eval_resolve ( param_env, uv. expand ( ) , Some ( span) ) ;
136-
137- if concrete. is_ok ( ) && uv. substs . has_param_types_or_consts ( ) {
138- match infcx. tcx . def_kind ( uv. def . did ) {
139- DefKind :: AnonConst | DefKind :: InlineConst => {
140- let mir_body = infcx. tcx . mir_for_ctfe_opt_const_arg ( uv. def ) ;
141-
142- if mir_body. is_polymorphic {
143- future_compat_lint ( ) ;
87+ match failure_kind {
88+ FailureKind :: MentionsInfer => {
89+ return Err ( NotConstEvaluatable :: MentionsInfer ) ;
90+ }
91+ FailureKind :: MentionsParam => {
92+ return Err ( NotConstEvaluatable :: MentionsParam ) ;
14493 }
94+ // returned below
95+ FailureKind :: Concrete => { }
14596 }
146- _ => future_compat_lint ( ) ,
14797 }
148- }
149-
150- // If we're evaluating a foreign constant, under a nightly compiler without generic
151- // const exprs, AND it would've passed if that expression had been evaluated with
152- // generic const exprs, then suggest using generic const exprs.
153- if concrete. is_err ( )
154- && tcx. sess . is_nightly_build ( )
155- && !uv. def . did . is_local ( )
156- && !tcx. features ( ) . generic_const_exprs
157- && let Ok ( Some ( ct) ) = AbstractConst :: new ( tcx, uv)
158- && satisfied_from_param_env ( tcx, ct, param_env) == Ok ( true )
159- {
160- tcx. sess
161- . struct_span_fatal (
162- // Slightly better span than just using `span` alone
163- if span == rustc_span:: DUMMY_SP { tcx. def_span ( uv. def . did ) } else { span } ,
164- "failed to evaluate generic const expression" ,
165- )
166- . note ( "the crate this constant originates from uses `#![feature(generic_const_exprs)]`" )
167- . span_suggestion_verbose (
168- rustc_span:: DUMMY_SP ,
169- "consider enabling this feature" ,
170- "#![feature(generic_const_exprs)]\n " . to_string ( ) ,
171- rustc_errors:: Applicability :: MaybeIncorrect ,
172- )
173- . emit ( )
174- }
175-
176- debug ! ( ?concrete, "is_const_evaluatable" ) ;
177- match concrete {
178- Err ( ErrorHandled :: TooGeneric ) => Err ( match uv. has_infer_types_or_consts ( ) {
179- true => NotConstEvaluatable :: MentionsInfer ,
180- false => NotConstEvaluatable :: MentionsParam ,
181- } ) ,
182- Err ( ErrorHandled :: Linted ) => {
183- let reported =
184- infcx. tcx . sess . delay_span_bug ( span, "constant in type had error reported as lint" ) ;
185- Err ( NotConstEvaluatable :: Error ( reported) )
98+ let concrete = infcx. const_eval_resolve ( param_env, uv. expand ( ) , Some ( span) ) ;
99+ match concrete {
100+ Err ( ErrorHandled :: TooGeneric ) => Err ( if !uv. has_infer_types_or_consts ( ) {
101+ infcx
102+ . tcx
103+ . sess
104+ . delay_span_bug ( span, & format ! ( "unexpected `TooGeneric` for {:?}" , uv) ) ;
105+ NotConstEvaluatable :: MentionsParam
106+ } else {
107+ NotConstEvaluatable :: MentionsInfer
108+ } ) ,
109+ Err ( ErrorHandled :: Linted ) => {
110+ let reported = infcx
111+ . tcx
112+ . sess
113+ . delay_span_bug ( span, "constant in type had error reported as lint" ) ;
114+ Err ( NotConstEvaluatable :: Error ( reported) )
115+ }
116+ Err ( ErrorHandled :: Reported ( e) ) => Err ( NotConstEvaluatable :: Error ( e) ) ,
117+ Ok ( _) => Ok ( ( ) ) ,
118+ }
119+ } else {
120+ // FIXME: We should only try to evaluate a given constant here if it is fully concrete
121+ // as we don't want to allow things like `[u8; std::mem::size_of::<*mut T>()]`.
122+ //
123+ // We previously did not check this, so we only emit a future compat warning if
124+ // const evaluation succeeds and the given constant is still polymorphic for now
125+ // and hopefully soon change this to an error.
126+ //
127+ // See #74595 for more details about this.
128+ let concrete = infcx. const_eval_resolve ( param_env, uv. expand ( ) , Some ( span) ) ;
129+
130+ match concrete {
131+ // If we're evaluating a foreign constant, under a nightly compiler without generic
132+ // const exprs, AND it would've passed if that expression had been evaluated with
133+ // generic const exprs, then suggest using generic const exprs.
134+ Err ( _) if tcx. sess . is_nightly_build ( )
135+ && let Ok ( Some ( ct) ) = AbstractConst :: new ( tcx, uv)
136+ && satisfied_from_param_env ( tcx, ct, param_env) == Ok ( true ) => {
137+ tcx. sess
138+ . struct_span_fatal (
139+ // Slightly better span than just using `span` alone
140+ if span == rustc_span:: DUMMY_SP { tcx. def_span ( uv. def . did ) } else { span } ,
141+ "failed to evaluate generic const expression" ,
142+ )
143+ . note ( "the crate this constant originates from uses `#![feature(generic_const_exprs)]`" )
144+ . span_suggestion_verbose (
145+ rustc_span:: DUMMY_SP ,
146+ "consider enabling this feature" ,
147+ "#![feature(generic_const_exprs)]\n " . to_string ( ) ,
148+ rustc_errors:: Applicability :: MaybeIncorrect ,
149+ )
150+ . emit ( )
151+ }
152+
153+ Err ( ErrorHandled :: TooGeneric ) => Err ( if uv. has_infer_types_or_consts ( ) {
154+ NotConstEvaluatable :: MentionsInfer
155+ } else {
156+ NotConstEvaluatable :: MentionsParam
157+ } ) ,
158+ Err ( ErrorHandled :: Linted ) => {
159+ let reported =
160+ infcx. tcx . sess . delay_span_bug ( span, "constant in type had error reported as lint" ) ;
161+ Err ( NotConstEvaluatable :: Error ( reported) )
162+ }
163+ Err ( ErrorHandled :: Reported ( e) ) => Err ( NotConstEvaluatable :: Error ( e) ) ,
164+ Ok ( _) => {
165+ if uv. substs . has_param_types_or_consts ( ) {
166+ assert ! ( matches!( infcx. tcx. def_kind( uv. def. did) , DefKind :: AnonConst ) ) ;
167+ let mir_body = infcx. tcx . mir_for_ctfe_opt_const_arg ( uv. def ) ;
168+
169+ if mir_body. is_polymorphic {
170+ let Some ( local_def_id) = uv. def . did . as_local ( ) else { return Ok ( ( ) ) } ;
171+ tcx. struct_span_lint_hir (
172+ lint:: builtin:: CONST_EVALUATABLE_UNCHECKED ,
173+ tcx. hir ( ) . local_def_id_to_hir_id ( local_def_id) ,
174+ span,
175+ |err| {
176+ err. build ( "cannot use constants which depend on generic parameters in types" ) . emit ( ) ;
177+ } )
178+ }
179+ }
180+
181+ Ok ( ( ) )
182+ } ,
186183 }
187- Err ( ErrorHandled :: Reported ( e) ) => Err ( NotConstEvaluatable :: Error ( e) ) ,
188- Ok ( _) => Ok ( ( ) ) ,
189184 }
190185}
191186
0 commit comments