@@ -14,35 +14,32 @@ use super::ConstCx;
14
14
pub fn non_const < O : NonConstOp > ( ccx : & ConstCx < ' _ , ' _ > , op : O , span : Span ) {
15
15
debug ! ( "illegal_op: op={:?}" , op) ;
16
16
17
- if op. is_allowed_in_item ( ccx) {
18
- return ;
19
- }
17
+ let gate = match op. status_in_item ( ccx) {
18
+ Status :: Allowed => return ,
19
+ Status :: Unstable ( gate) if ccx. tcx . features ( ) . enabled ( gate) => return ,
20
+ Status :: Unstable ( gate) => Some ( gate) ,
21
+ Status :: Forbidden => None ,
22
+ } ;
20
23
21
24
if ccx. tcx . sess . opts . debugging_opts . unleash_the_miri_inside_of_you {
22
- ccx. tcx . sess . miri_unleashed_feature ( span, O :: feature_gate ( ) ) ;
25
+ ccx. tcx . sess . miri_unleashed_feature ( span, gate ) ;
23
26
return ;
24
27
}
25
28
26
29
op. emit_error ( ccx, span) ;
27
30
}
28
31
32
+ pub enum Status {
33
+ Allowed ,
34
+ Unstable ( Symbol ) ,
35
+ Forbidden ,
36
+ }
37
+
29
38
/// An operation that is not *always* allowed in a const context.
30
39
pub trait NonConstOp : std:: fmt:: Debug {
31
- /// Returns the `Symbol` corresponding to the feature gate that would enable this operation,
32
- /// or `None` if such a feature gate does not exist.
33
- fn feature_gate ( ) -> Option < Symbol > {
34
- None
35
- }
36
-
37
- /// Returns `true` if this operation is allowed in the given item.
38
- ///
39
- /// This check should assume that we are not in a non-const `fn`, where all operations are
40
- /// legal.
41
- ///
42
- /// By default, it returns `true` if and only if this operation has a corresponding feature
43
- /// gate and that gate is enabled.
44
- fn is_allowed_in_item ( & self , ccx : & ConstCx < ' _ , ' _ > ) -> bool {
45
- Self :: feature_gate ( ) . map_or ( false , |gate| ccx. tcx . features ( ) . enabled ( gate) )
40
+ /// Returns an enum indicating whether this operation is allowed within the given item.
41
+ fn status_in_item ( & self , _ccx : & ConstCx < ' _ , ' _ > ) -> Status {
42
+ Status :: Forbidden
46
43
}
47
44
48
45
fn emit_error ( & self , ccx : & ConstCx < ' _ , ' _ > , span : Span ) {
@@ -53,9 +50,13 @@ pub trait NonConstOp: std::fmt::Debug {
53
50
"{} contains unimplemented expression type" ,
54
51
ccx. const_kind( )
55
52
) ;
56
- if let Some ( feat) = Self :: feature_gate ( ) {
57
- err. help ( & format ! ( "add `#![feature({})]` to the crate attributes to enable" , feat) ) ;
53
+
54
+ if let Status :: Unstable ( gate) = self . status_in_item ( ccx) {
55
+ if !ccx. tcx . features ( ) . enabled ( gate) && nightly_options:: is_nightly_build ( ) {
56
+ err. help ( & format ! ( "add `#![feature({})]` to the crate attributes to enable" , gate) ) ;
57
+ }
58
58
}
59
+
59
60
if ccx. tcx . sess . teach ( & err. get_code ( ) . unwrap ( ) ) {
60
61
err. note (
61
62
"A function call isn't allowed in the const's initialization expression \
@@ -182,14 +183,13 @@ impl NonConstOp for CellBorrow {
182
183
#[ derive( Debug ) ]
183
184
pub struct MutBorrow ;
184
185
impl NonConstOp for MutBorrow {
185
- fn is_allowed_in_item ( & self , ccx : & ConstCx < ' _ , ' _ > ) -> bool {
186
- // Forbid everywhere except in const fn
187
- ccx. const_kind ( ) == hir:: ConstContext :: ConstFn
188
- && ccx. tcx . features ( ) . enabled ( Self :: feature_gate ( ) . unwrap ( ) )
189
- }
190
-
191
- fn feature_gate ( ) -> Option < Symbol > {
192
- Some ( sym:: const_mut_refs)
186
+ fn status_in_item ( & self , ccx : & ConstCx < ' _ , ' _ > ) -> Status {
187
+ // Forbid everywhere except in const fn with a feature gate
188
+ if ccx. const_kind ( ) == hir:: ConstContext :: ConstFn {
189
+ Status :: Unstable ( sym:: const_mut_refs)
190
+ } else {
191
+ Status :: Forbidden
192
+ }
193
193
}
194
194
195
195
fn emit_error ( & self , ccx : & ConstCx < ' _ , ' _ > , span : Span ) {
@@ -201,15 +201,16 @@ impl NonConstOp for MutBorrow {
201
201
& format ! ( "mutable references are not allowed in {}s" , ccx. const_kind( ) ) ,
202
202
)
203
203
} else {
204
- struct_span_err ! (
204
+ let mut err = struct_span_err ! (
205
205
ccx. tcx. sess,
206
206
span,
207
207
E0764 ,
208
208
"mutable references are not allowed in {}s" ,
209
209
ccx. const_kind( ) ,
210
- )
210
+ ) ;
211
+ err. span_label ( span, format ! ( "`&mut` is only allowed in `const fn`" ) ) ;
212
+ err
211
213
} ;
212
- err. span_label ( span, "`&mut` is only allowed in `const fn`" . to_string ( ) ) ;
213
214
if ccx. tcx . sess . teach ( & err. get_code ( ) . unwrap ( ) ) {
214
215
err. note (
215
216
"References in statics and constants may only refer \
@@ -226,11 +227,17 @@ impl NonConstOp for MutBorrow {
226
227
}
227
228
}
228
229
230
+ // FIXME(ecstaticmorse): Unify this with `MutBorrow`. It has basically the same issues.
229
231
#[ derive( Debug ) ]
230
232
pub struct MutAddressOf ;
231
233
impl NonConstOp for MutAddressOf {
232
- fn feature_gate ( ) -> Option < Symbol > {
233
- Some ( sym:: const_mut_refs)
234
+ fn status_in_item ( & self , ccx : & ConstCx < ' _ , ' _ > ) -> Status {
235
+ // Forbid everywhere except in const fn with a feature gate
236
+ if ccx. const_kind ( ) == hir:: ConstContext :: ConstFn {
237
+ Status :: Unstable ( sym:: const_mut_refs)
238
+ } else {
239
+ Status :: Forbidden
240
+ }
234
241
}
235
242
236
243
fn emit_error ( & self , ccx : & ConstCx < ' _ , ' _ > , span : Span ) {
@@ -247,16 +254,16 @@ impl NonConstOp for MutAddressOf {
247
254
#[ derive( Debug ) ]
248
255
pub struct MutDeref ;
249
256
impl NonConstOp for MutDeref {
250
- fn feature_gate ( ) -> Option < Symbol > {
251
- Some ( sym:: const_mut_refs)
257
+ fn status_in_item ( & self , _ : & ConstCx < ' _ , ' _ > ) -> Status {
258
+ Status :: Unstable ( sym:: const_mut_refs)
252
259
}
253
260
}
254
261
255
262
#[ derive( Debug ) ]
256
263
pub struct Panic ;
257
264
impl NonConstOp for Panic {
258
- fn feature_gate ( ) -> Option < Symbol > {
259
- Some ( sym:: const_panic)
265
+ fn status_in_item ( & self , _ : & ConstCx < ' _ , ' _ > ) -> Status {
266
+ Status :: Unstable ( sym:: const_panic)
260
267
}
261
268
262
269
fn emit_error ( & self , ccx : & ConstCx < ' _ , ' _ > , span : Span ) {
@@ -289,8 +296,8 @@ impl NonConstOp for RawPtrComparison {
289
296
#[ derive( Debug ) ]
290
297
pub struct RawPtrDeref ;
291
298
impl NonConstOp for RawPtrDeref {
292
- fn feature_gate ( ) -> Option < Symbol > {
293
- Some ( sym:: const_raw_ptr_deref)
299
+ fn status_in_item ( & self , _ : & ConstCx < ' _ , ' _ > ) -> Status {
300
+ Status :: Unstable ( sym:: const_raw_ptr_deref)
294
301
}
295
302
296
303
fn emit_error ( & self , ccx : & ConstCx < ' _ , ' _ > , span : Span ) {
@@ -307,8 +314,8 @@ impl NonConstOp for RawPtrDeref {
307
314
#[ derive( Debug ) ]
308
315
pub struct RawPtrToIntCast ;
309
316
impl NonConstOp for RawPtrToIntCast {
310
- fn feature_gate ( ) -> Option < Symbol > {
311
- Some ( sym:: const_raw_ptr_to_usize_cast)
317
+ fn status_in_item ( & self , _ : & ConstCx < ' _ , ' _ > ) -> Status {
318
+ Status :: Unstable ( sym:: const_raw_ptr_to_usize_cast)
312
319
}
313
320
314
321
fn emit_error ( & self , ccx : & ConstCx < ' _ , ' _ > , span : Span ) {
@@ -326,8 +333,12 @@ impl NonConstOp for RawPtrToIntCast {
326
333
#[ derive( Debug ) ]
327
334
pub struct StaticAccess ;
328
335
impl NonConstOp for StaticAccess {
329
- fn is_allowed_in_item ( & self , ccx : & ConstCx < ' _ , ' _ > ) -> bool {
330
- matches ! ( ccx. const_kind( ) , hir:: ConstContext :: Static ( _) )
336
+ fn status_in_item ( & self , ccx : & ConstCx < ' _ , ' _ > ) -> Status {
337
+ if let hir:: ConstContext :: Static ( _) = ccx. const_kind ( ) {
338
+ Status :: Allowed
339
+ } else {
340
+ Status :: Forbidden
341
+ }
331
342
}
332
343
333
344
fn emit_error ( & self , ccx : & ConstCx < ' _ , ' _ > , span : Span ) {
@@ -371,14 +382,13 @@ impl NonConstOp for ThreadLocalAccess {
371
382
#[ derive( Debug ) ]
372
383
pub struct UnionAccess ;
373
384
impl NonConstOp for UnionAccess {
374
- fn is_allowed_in_item ( & self , ccx : & ConstCx < ' _ , ' _ > ) -> bool {
385
+ fn status_in_item ( & self , ccx : & ConstCx < ' _ , ' _ > ) -> Status {
375
386
// Union accesses are stable in all contexts except `const fn`.
376
- ccx. const_kind ( ) != hir:: ConstContext :: ConstFn
377
- || ccx. tcx . features ( ) . enabled ( Self :: feature_gate ( ) . unwrap ( ) )
378
- }
379
-
380
- fn feature_gate ( ) -> Option < Symbol > {
381
- Some ( sym:: const_fn_union)
387
+ if ccx. const_kind ( ) != hir:: ConstContext :: ConstFn {
388
+ Status :: Allowed
389
+ } else {
390
+ Status :: Unstable ( sym:: const_fn_union)
391
+ }
382
392
}
383
393
384
394
fn emit_error ( & self , ccx : & ConstCx < ' _ , ' _ > , span : Span ) {
0 commit comments