@@ -709,7 +709,7 @@ impl Iterator for ReadDir {
709709 // thread safety for readdir() as long an individual DIR* is not accessed
710710 // concurrently, which is sufficient for Rust.
711711 super :: os:: set_errno ( 0 ) ;
712- let entry_ptr = readdir64 ( self . inner . dirp . 0 ) ;
712+ let entry_ptr: * const dirent64 = readdir64 ( self . inner . dirp . 0 ) ;
713713 if entry_ptr. is_null ( ) {
714714 // We either encountered an error, or reached the end. Either way,
715715 // the next call to next() should return None.
@@ -735,44 +735,34 @@ impl Iterator for ReadDir {
735735 // contents were "simply" partially initialized data.
736736 //
737737 // Like for uninitialized contents, converting entry_ptr to `&dirent64`
738- // would not be legal. However, unique to dirent64 is that we don't even
739- // get to use `&raw const (*entry_ptr).d_name` because that operation
740- // requires the full extent of *entry_ptr to be in bounds of the same
741- // allocation, which is not necessarily the case here.
742- //
743- // Instead we must access fields individually through their offsets.
744- macro_rules! offset_ptr {
745- ( $entry_ptr: expr, $field: ident) => { {
746- const OFFSET : isize = mem:: offset_of!( dirent64, $field) as isize ;
747- if true {
748- // Cast to the same type determined by the else branch.
749- $entry_ptr. byte_offset( OFFSET ) . cast:: <_>( )
750- } else {
751- #[ allow( deref_nullptr) ]
752- {
753- & raw const ( * ptr:: null:: <dirent64>( ) ) . $field
754- }
755- }
756- } } ;
738+ // would not be legal. However, we can use `&raw const (*entry_ptr).d_name`
739+ // to refer the fields individually, because that operation is equivalent
740+ // to `byte_offset` and thus does not require the full extent of `*entry_ptr`
741+ // to be in bounds of the same allocation, only the offset of the field
742+ // being referenced.
743+ macro_rules! entry_field_ptr {
744+ ( $field: ident) => {
745+ & raw const ( * entry_ptr) . $field
746+ } ;
757747 }
758748
759749 // d_name is guaranteed to be null-terminated.
760- let name = CStr :: from_ptr ( offset_ptr ! ( entry_ptr , d_name) . cast ( ) ) ;
750+ let name = CStr :: from_ptr ( entry_field_ptr ! ( d_name) . cast ( ) ) ;
761751 let name_bytes = name. to_bytes ( ) ;
762752 if name_bytes == b"." || name_bytes == b".." {
763753 continue ;
764754 }
765755
766756 #[ cfg( not( target_os = "vita" ) ) ]
767757 let entry = dirent64_min {
768- d_ino : * offset_ptr ! ( entry_ptr , d_ino) as u64 ,
758+ d_ino : * entry_field_ptr ! ( d_ino) as u64 ,
769759 #[ cfg( not( any(
770760 target_os = "solaris" ,
771761 target_os = "illumos" ,
772762 target_os = "aix" ,
773763 target_os = "nto" ,
774764 ) ) ) ]
775- d_type : * offset_ptr ! ( entry_ptr , d_type) as u8 ,
765+ d_type : * entry_field_ptr ! ( d_type) as u8 ,
776766 } ;
777767
778768 #[ cfg( target_os = "vita" ) ]
0 commit comments