@@ -268,43 +268,41 @@ impl NonConstOp for CellBorrow {
268268}
269269
270270#[ derive( Debug ) ]
271+ /// This op is for `&mut` borrows in the trailing expression of a constant
272+ /// which uses the "enclosing scopes rule" to leak its locals into anonymous
273+ /// static or const items.
271274pub struct MutBorrow ( pub hir:: BorrowKind ) ;
272275
273276impl NonConstOp for MutBorrow {
274277 fn status_in_item ( & self , ccx : & ConstCx < ' _ , ' _ > ) -> Status {
275- // Forbid everywhere except in const fn with a feature gate
276- if ccx. const_kind ( ) == hir:: ConstContext :: ConstFn {
277- Status :: Unstable ( sym:: const_mut_refs)
278- } else {
279- Status :: Forbidden
278+ match ccx. const_kind ( ) {
279+ // Mutable statics can handle mutable references in their final value
280+ hir:: ConstContext :: Static ( hir:: Mutability :: Mut ) => Status :: Allowed ,
281+ _ => Status :: Forbidden ,
280282 }
281283 }
282284
285+ fn importance ( & self ) -> DiagnosticImportance {
286+ // If there were primary errors (like non-const function calls), do not emit further
287+ // errors about mutable references.
288+ DiagnosticImportance :: Secondary
289+ }
290+
283291 fn build_error ( & self , ccx : & ConstCx < ' _ , ' tcx > , span : Span ) -> DiagnosticBuilder < ' tcx > {
284292 let raw = match self . 0 {
285293 hir:: BorrowKind :: Raw => "raw " ,
286294 hir:: BorrowKind :: Ref => "" ,
287295 } ;
288296
289- let mut err = if ccx. const_kind ( ) == hir:: ConstContext :: ConstFn {
290- feature_err (
291- & ccx. tcx . sess . parse_sess ,
292- sym:: const_mut_refs,
293- span,
294- & format ! ( "{}mutable references are not allowed in {}s" , raw, ccx. const_kind( ) ) ,
295- )
296- } else {
297- let mut err = struct_span_err ! (
298- ccx. tcx. sess,
299- span,
300- E0764 ,
301- "{}mutable references are not allowed in {}s" ,
302- raw,
303- ccx. const_kind( ) ,
304- ) ;
305- err. span_label ( span, format ! ( "`&{}mut` is only allowed in `const fn`" , raw) ) ;
306- err
307- } ;
297+ let mut err = struct_span_err ! (
298+ ccx. tcx. sess,
299+ span,
300+ E0764 ,
301+ "{}mutable references are not allowed in final value of {}s" ,
302+ raw,
303+ ccx. const_kind( ) ,
304+ ) ;
305+
308306 if ccx. tcx . sess . teach ( & err. get_code ( ) . unwrap ( ) ) {
309307 err. note (
310308 "References in statics and constants may only refer \
@@ -321,6 +319,29 @@ impl NonConstOp for MutBorrow {
321319 }
322320}
323321
322+ #[ derive( Debug ) ]
323+ pub struct TransientMutBorrow ( pub hir:: BorrowKind ) ;
324+
325+ impl NonConstOp for TransientMutBorrow {
326+ fn status_in_item ( & self , _: & ConstCx < ' _ , ' _ > ) -> Status {
327+ Status :: Unstable ( sym:: const_mut_refs)
328+ }
329+
330+ fn build_error ( & self , ccx : & ConstCx < ' _ , ' tcx > , span : Span ) -> DiagnosticBuilder < ' tcx > {
331+ let raw = match self . 0 {
332+ hir:: BorrowKind :: Raw => "raw " ,
333+ hir:: BorrowKind :: Ref => "" ,
334+ } ;
335+
336+ feature_err (
337+ & ccx. tcx . sess . parse_sess ,
338+ sym:: const_mut_refs,
339+ span,
340+ & format ! ( "{}mutable references are not allowed in {}s" , raw, ccx. const_kind( ) ) ,
341+ )
342+ }
343+ }
344+
324345#[ derive( Debug ) ]
325346pub struct MutDeref ;
326347impl NonConstOp for MutDeref {
@@ -329,7 +350,7 @@ impl NonConstOp for MutDeref {
329350 }
330351
331352 fn importance ( & self ) -> DiagnosticImportance {
332- // Usually a side-effect of a `MutBorrow ` somewhere.
353+ // Usually a side-effect of a `TransientMutBorrow ` somewhere.
333354 DiagnosticImportance :: Secondary
334355 }
335356
0 commit comments