@@ -491,41 +491,46 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
491491 this. super_place ( place, context, location) ;
492492 match proj. elem {
493493 ProjectionElem :: Deref => {
494- this. add ( Qualif :: NOT_CONST ) ;
495-
496- let base_ty = proj. base . ty ( this. mir , this. tcx ) . to_ty ( this. tcx ) ;
497- if let ty:: TyRawPtr ( _) = base_ty. sty {
498- if this. mode != Mode :: Fn {
499- let mut err = struct_span_err ! (
500- this. tcx. sess,
501- this. span,
502- E0396 ,
503- "raw pointers cannot be dereferenced in {}s" ,
504- this. mode
505- ) ;
506- err. span_label ( this. span ,
507- "dereference of raw pointer in constant" ) ;
508- if this. tcx . sess . teach ( & err. get_code ( ) . unwrap ( ) ) {
509- err. note (
510- "The value behind a raw pointer can't be determined \
511- at compile-time (or even link-time), which means it \
512- can't be used in a constant expression."
494+ if let Mode :: Fn = this. mode {
495+ this. add ( Qualif :: NOT_CONST ) ;
496+ } else {
497+ let base_ty = proj. base . ty ( this. mir , this. tcx ) . to_ty ( this. tcx ) ;
498+ if let ty:: TyRawPtr ( _) = base_ty. sty {
499+ if !this. tcx . sess . features_untracked ( ) . const_raw_ptr_deref {
500+ emit_feature_err (
501+ & this. tcx . sess . parse_sess , "const_raw_ptr_deref" ,
502+ this. span , GateIssue :: Language ,
503+ & format ! (
504+ "dereferencing raw pointers in {}s is unstable" ,
505+ this. mode,
506+ ) ,
513507 ) ;
514- err. help ( "A possible fix is to dereference your pointer \
515- at some point in run-time.") ;
516508 }
517- err. emit ( ) ;
518509 }
519510 }
520511 }
521512
522513 ProjectionElem :: Field ( ..) |
523514 ProjectionElem :: Index ( _) => {
524- if this. mode == Mode :: Fn {
525- let base_ty = proj. base . ty ( this. mir , this. tcx ) . to_ty ( this. tcx ) ;
526- if let Some ( def) = base_ty. ty_adt_def ( ) {
527- if def. is_union ( ) {
528- this. not_const ( ) ;
515+ let base_ty = proj. base . ty ( this. mir , this. tcx ) . to_ty ( this. tcx ) ;
516+ if let Some ( def) = base_ty. ty_adt_def ( ) {
517+ if def. is_union ( ) {
518+ match this. mode {
519+ Mode :: Fn => this. not_const ( ) ,
520+ Mode :: ConstFn => {
521+ if !this. tcx . sess . features_untracked ( ) . const_fn_union {
522+ emit_feature_err (
523+ & this. tcx . sess . parse_sess , "const_fn_union" ,
524+ this. span , GateIssue :: Language ,
525+ "unions in const fn are unstable" ,
526+ ) ;
527+ }
528+ } ,
529+
530+ | Mode :: Static
531+ | Mode :: StaticMut
532+ | Mode :: Const
533+ => { } ,
529534 }
530535 }
531536 }
@@ -722,44 +727,17 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
722727 match ( cast_in, cast_out) {
723728 ( CastTy :: Ptr ( _) , CastTy :: Int ( _) ) |
724729 ( CastTy :: FnPtr , CastTy :: Int ( _) ) => {
725- self . add ( Qualif :: NOT_CONST ) ;
726- if self . mode != Mode :: Fn {
727- let mut err = struct_span_err ! (
728- self . tcx. sess,
729- self . span,
730- E0018 ,
731- "raw pointers cannot be cast to integers in {}s" ,
732- self . mode
730+ if let Mode :: Fn = self . mode {
731+ self . add ( Qualif :: NOT_CONST ) ;
732+ } else if !self . tcx . sess . features_untracked ( ) . const_raw_ptr_to_usize_cast {
733+ emit_feature_err (
734+ & self . tcx . sess . parse_sess , "const_raw_ptr_to_usize_cast" ,
735+ self . span , GateIssue :: Language ,
736+ & format ! (
737+ "casting pointers to integers in {}s is unstable" ,
738+ self . mode,
739+ ) ,
733740 ) ;
734- if self . tcx . sess . teach ( & err. get_code ( ) . unwrap ( ) ) {
735- err. note ( "\
736- The value of static and constant integers must be known at compile time. You can't cast a pointer \
737- to an integer because the address of a pointer can vary.
738-
739- For example, if you write:
740-
741- ```
742- static MY_STATIC: u32 = 42;
743- static MY_STATIC_ADDR: usize = &MY_STATIC as *const _ as usize;
744- static WHAT: usize = (MY_STATIC_ADDR^17) + MY_STATIC_ADDR;
745- ```
746-
747- Then `MY_STATIC_ADDR` would contain the address of `MY_STATIC`. However, the address can change \
748- when the program is linked, as well as change between different executions due to ASLR, and many \
749- linkers would not be able to calculate the value of `WHAT`.
750-
751- On the other hand, static and constant pointers can point either to a known numeric address or to \
752- the address of a symbol.
753-
754- ```
755- static MY_STATIC: u32 = 42;
756- static MY_STATIC_ADDR: &'static u32 = &MY_STATIC;
757- const CONST_ADDR: *const u8 = 0x5f3759df as *const u8;
758- ```
759-
760- This does not pose a problem by itself because they can't be accessed directly." ) ;
761- }
762- err. emit ( ) ;
763741 }
764742 }
765743 _ => { }
@@ -773,16 +751,16 @@ This does not pose a problem by itself because they can't be accessed directly."
773751 op == BinOp :: Ge || op == BinOp :: Gt ||
774752 op == BinOp :: Offset ) ;
775753
776- self . add ( Qualif :: NOT_CONST ) ;
777- if self . mode != Mode :: Fn {
778- struct_span_err ! (
779- self . tcx. sess, self . span, E0395 ,
780- "raw pointers cannot be compared in {}s" ,
781- self . mode)
782- . span_label (
754+ if let Mode :: Fn = self . mode {
755+ self . add ( Qualif :: NOT_CONST ) ;
756+ } else if !self . tcx . sess . features_untracked ( ) . const_compare_raw_pointers {
757+ emit_feature_err (
758+ & self . tcx . sess . parse_sess ,
759+ "const_compare_raw_pointers" ,
783760 self . span ,
784- "comparing raw pointers in static" )
785- . emit ( ) ;
761+ GateIssue :: Language ,
762+ & format ! ( "comparing raw pointers inside {}" , self . mode) ,
763+ ) ;
786764 }
787765 }
788766 }
0 commit comments