@@ -445,22 +445,22 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
445
445
// Determine whether this pointer expects to be pointing to something mutable.
446
446
let ptr_expected_mutbl = match ptr_kind {
447
447
PointerKind :: Box => Mutability :: Mut ,
448
- PointerKind :: Ref => {
449
- let tam = value. layout . ty . builtin_deref ( false ) . unwrap ( ) ;
450
- // ZST never require mutability. We do not take into account interior mutability
451
- // here since we cannot know if there really is an `UnsafeCell` inside
452
- // `Option<UnsafeCell>` -- so we check that in the recursive descent behind this
453
- // reference.
454
- if size == Size :: ZERO { Mutability :: Not } else { tam. mutbl }
448
+ PointerKind :: Ref ( mutbl) => {
449
+ // We do not take into account interior mutability here since we cannot know if
450
+ // there really is an `UnsafeCell` inside `Option<UnsafeCell>` -- so we check
451
+ // that in the recursive descent behind this reference (controlled by
452
+ // `allow_immutable_unsafe_cell`).
453
+ mutbl
455
454
}
456
455
} ;
457
456
// Proceed recursively even for ZST, no reason to skip them!
458
457
// `!` is a ZST and we want to validate it.
459
458
if let Ok ( ( alloc_id, _offset, _prov) ) = self . ecx . ptr_try_get_alloc_id ( place. ptr ( ) ) {
459
+ let mut skip_recursive_check = false ;
460
460
// Let's see what kind of memory this points to.
461
461
// `unwrap` since dangling pointers have already been handled.
462
462
let alloc_kind = self . ecx . tcx . try_get_global_alloc ( alloc_id) . unwrap ( ) ;
463
- match alloc_kind {
463
+ let alloc_actual_mutbl = match alloc_kind {
464
464
GlobalAlloc :: Static ( did) => {
465
465
// Special handling for pointers to statics (irrespective of their type).
466
466
assert ! ( !self . ecx. tcx. is_thread_local_static( did) ) ;
@@ -474,12 +474,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
474
474
. no_bound_vars ( )
475
475
. expect ( "statics should not have generic parameters" )
476
476
. is_freeze ( * self . ecx . tcx , ty:: ParamEnv :: reveal_all ( ) ) ;
477
- // Mutability check.
478
- if ptr_expected_mutbl == Mutability :: Mut {
479
- if !is_mut {
480
- throw_validation_failure ! ( self . path, MutableRefToImmutable ) ;
481
- }
482
- }
483
477
// Mode-specific checks
484
478
match self . ctfe_mode {
485
479
Some (
@@ -494,42 +488,49 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
494
488
// trigger cycle errors if we try to compute the value of the other static
495
489
// and that static refers back to us (potentially through a promoted).
496
490
// This could miss some UB, but that's fine.
497
- return Ok ( ( ) ) ;
491
+ skip_recursive_check = true ;
498
492
}
499
493
Some ( CtfeValidationMode :: Const { .. } ) => {
500
- // For consts on the other hand we have to recursively check;
501
- // pattern matching assumes a valid value. However we better make
502
- // sure this is not mutable.
503
- if is_mut {
504
- throw_validation_failure ! ( self . path, ConstRefToMutable ) ;
505
- }
506
494
// We can't recursively validate `extern static`, so we better reject them.
507
495
if self . ecx . tcx . is_foreign_item ( did) {
508
496
throw_validation_failure ! ( self . path, ConstRefToExtern ) ;
509
497
}
510
498
}
511
499
None => { }
512
500
}
501
+ // Return alloc mutability
502
+ if is_mut { Mutability :: Mut } else { Mutability :: Not }
513
503
}
514
- GlobalAlloc :: Memory ( alloc) => {
515
- if alloc. inner ( ) . mutability == Mutability :: Mut
516
- && matches ! ( self . ctfe_mode, Some ( CtfeValidationMode :: Const { .. } ) )
517
- {
518
- throw_validation_failure ! ( self . path, ConstRefToMutable ) ;
519
- }
520
- if ptr_expected_mutbl == Mutability :: Mut
521
- && alloc. inner ( ) . mutability == Mutability :: Not
522
- {
523
- throw_validation_failure ! ( self . path, MutableRefToImmutable ) ;
524
- }
525
- }
504
+ GlobalAlloc :: Memory ( alloc) => alloc. inner ( ) . mutability ,
526
505
GlobalAlloc :: Function ( ..) | GlobalAlloc :: VTable ( ..) => {
527
506
// These are immutable, we better don't allow mutable pointers here.
528
- if ptr_expected_mutbl == Mutability :: Mut {
529
- throw_validation_failure ! ( self . path, MutableRefToImmutable ) ;
530
- }
507
+ Mutability :: Not
508
+ }
509
+ } ;
510
+ // Mutability check.
511
+ // If this allocation has size zero, there is no actual mutability here.
512
+ let ( size, _align, _alloc_kind) = self . ecx . get_alloc_info ( alloc_id) ;
513
+ if size != Size :: ZERO {
514
+ if ptr_expected_mutbl == Mutability :: Mut
515
+ && alloc_actual_mutbl == Mutability :: Not
516
+ {
517
+ throw_validation_failure ! ( self . path, MutableRefToImmutable ) ;
518
+ }
519
+ if ptr_expected_mutbl == Mutability :: Mut
520
+ && self . ctfe_mode . is_some_and ( |c| !c. may_contain_mutable_ref ( ) )
521
+ {
522
+ throw_validation_failure ! ( self . path, MutableRefInConstOrStatic ) ;
523
+ }
524
+ if alloc_actual_mutbl == Mutability :: Mut
525
+ && matches ! ( self . ctfe_mode, Some ( CtfeValidationMode :: Const { .. } ) )
526
+ {
527
+ throw_validation_failure ! ( self . path, ConstRefToMutable ) ;
531
528
}
532
529
}
530
+ // Potentially skip recursive check.
531
+ if skip_recursive_check {
532
+ return Ok ( ( ) ) ;
533
+ }
533
534
}
534
535
let path = & self . path ;
535
536
ref_tracking. track ( place, || {
@@ -598,16 +599,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
598
599
}
599
600
Ok ( true )
600
601
}
601
- ty:: Ref ( _, ty, mutbl) => {
602
- if self . ctfe_mode . is_some_and ( |c| !c. may_contain_mutable_ref ( ) )
603
- && * mutbl == Mutability :: Mut
604
- {
605
- let layout = self . ecx . layout_of ( * ty) ?;
606
- if !layout. is_zst ( ) {
607
- throw_validation_failure ! ( self . path, MutableRefInConst ) ;
608
- }
609
- }
610
- self . check_safe_pointer ( value, PointerKind :: Ref ) ?;
602
+ ty:: Ref ( _, _ty, mutbl) => {
603
+ self . check_safe_pointer ( value, PointerKind :: Ref ( * mutbl) ) ?;
611
604
Ok ( true )
612
605
}
613
606
ty:: FnPtr ( _sig) => {
0 commit comments