@@ -39,153 +39,148 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
39
39
let tcx = infcx. tcx ;
40
40
41
41
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 ) ;
74
69
}
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
- }
81
70
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 ) ;
86
78
}
87
- } ) ;
88
79
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
100
81
}
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
+ } ) ;
109
86
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 ) ;
144
93
}
94
+ // returned below
95
+ FailureKind :: Concrete => { }
145
96
}
146
- _ => future_compat_lint ( ) ,
147
97
}
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
+ } ,
186
183
}
187
- Err ( ErrorHandled :: Reported ( e) ) => Err ( NotConstEvaluatable :: Error ( e) ) ,
188
- Ok ( _) => Ok ( ( ) ) ,
189
184
}
190
185
}
191
186
0 commit comments