@@ -491,41 +491,46 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
491
491
this. super_place ( place, context, location) ;
492
492
match proj. elem {
493
493
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
+ ) ,
513
507
) ;
514
- err. help ( "A possible fix is to dereference your pointer \
515
- at some point in run-time.") ;
516
508
}
517
- err. emit ( ) ;
518
509
}
519
510
}
520
511
}
521
512
522
513
ProjectionElem :: Field ( ..) |
523
514
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
+ => { } ,
529
534
}
530
535
}
531
536
}
@@ -722,44 +727,17 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
722
727
match ( cast_in, cast_out) {
723
728
( CastTy :: Ptr ( _) , CastTy :: Int ( _) ) |
724
729
( 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
+ ) ,
733
740
) ;
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 ( ) ;
763
741
}
764
742
}
765
743
_ => { }
@@ -773,16 +751,16 @@ This does not pose a problem by itself because they can't be accessed directly."
773
751
op == BinOp :: Ge || op == BinOp :: Gt ||
774
752
op == BinOp :: Offset ) ;
775
753
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" ,
783
760
self . span ,
784
- "comparing raw pointers in static" )
785
- . emit ( ) ;
761
+ GateIssue :: Language ,
762
+ & format ! ( "comparing raw pointers inside {}" , self . mode) ,
763
+ ) ;
786
764
}
787
765
}
788
766
}
0 commit comments