@@ -161,7 +161,7 @@ mod tests;
161161use crate :: any:: Any ;
162162use crate :: cell:: { Cell , OnceCell , UnsafeCell } ;
163163use crate :: env;
164- use crate :: ffi:: { CStr , CString } ;
164+ use crate :: ffi:: CStr ;
165165use crate :: fmt;
166166use crate :: io;
167167use crate :: marker:: PhantomData ;
@@ -487,11 +487,7 @@ impl Builder {
487487 amt
488488 } ) ;
489489
490- let my_thread = name. map_or_else ( Thread :: new_unnamed, |name| unsafe {
491- Thread :: new (
492- CString :: new ( name) . expect ( "thread name may not contain interior null bytes" ) ,
493- )
494- } ) ;
490+ let my_thread = name. map_or_else ( Thread :: new_unnamed, Thread :: new) ;
495491 let their_thread = my_thread. clone ( ) ;
496492
497493 let my_packet: Arc < Packet < ' scope , T > > = Arc :: new ( Packet {
@@ -1299,10 +1295,51 @@ impl ThreadId {
12991295/// The internal representation of a `Thread`'s name.
13001296enum ThreadName {
13011297 Main ,
1302- Other ( CString ) ,
1298+ Other ( ThreadNameString ) ,
13031299 Unnamed ,
13041300}
13051301
1302+ // This module ensures private fields are kept private, which is necessary to enforce the safety requirements.
1303+ mod thread_name_string {
1304+ use super :: ThreadName ;
1305+ use crate :: ffi:: { CStr , CString } ;
1306+ use core:: str;
1307+
1308+ /// Like a `String` it's guaranteed UTF-8 and like a `CString` it's null terminated.
1309+ pub ( crate ) struct ThreadNameString {
1310+ inner : CString ,
1311+ }
1312+ impl core:: ops:: Deref for ThreadNameString {
1313+ type Target = CStr ;
1314+ fn deref ( & self ) -> & CStr {
1315+ & self . inner
1316+ }
1317+ }
1318+ impl From < String > for ThreadNameString {
1319+ fn from ( s : String ) -> Self {
1320+ Self {
1321+ inner : CString :: new ( s) . expect ( "thread name may not contain interior null bytes" ) ,
1322+ }
1323+ }
1324+ }
1325+ impl ThreadName {
1326+ pub fn as_cstr ( & self ) -> Option < & CStr > {
1327+ match self {
1328+ ThreadName :: Main => Some ( c"main" ) ,
1329+ ThreadName :: Other ( other) => Some ( other) ,
1330+ ThreadName :: Unnamed => None ,
1331+ }
1332+ }
1333+
1334+ pub fn as_str ( & self ) -> Option < & str > {
1335+ // SAFETY: `as_cstr` can only return `Some` for a fixed CStr or a `ThreadNameString`,
1336+ // which is guaranteed to be UTF-8.
1337+ self . as_cstr ( ) . map ( |s| unsafe { str:: from_utf8_unchecked ( s. to_bytes ( ) ) } )
1338+ }
1339+ }
1340+ }
1341+ pub ( crate ) use thread_name_string:: ThreadNameString ;
1342+
13061343/// The internal representation of a `Thread` handle
13071344struct Inner {
13081345 name : ThreadName , // Guaranteed to be UTF-8
@@ -1342,25 +1379,20 @@ pub struct Thread {
13421379
13431380impl Thread {
13441381 /// Used only internally to construct a thread object without spawning.
1345- ///
1346- /// # Safety
1347- /// `name` must be valid UTF-8.
1348- pub ( crate ) unsafe fn new ( name : CString ) -> Thread {
1349- unsafe { Self :: new_inner ( ThreadName :: Other ( name) ) }
1382+ pub ( crate ) fn new ( name : String ) -> Thread {
1383+ Self :: new_inner ( ThreadName :: Other ( name. into ( ) ) )
13501384 }
13511385
13521386 pub ( crate ) fn new_unnamed ( ) -> Thread {
1353- unsafe { Self :: new_inner ( ThreadName :: Unnamed ) }
1387+ Self :: new_inner ( ThreadName :: Unnamed )
13541388 }
13551389
13561390 // Used in runtime to construct main thread
13571391 pub ( crate ) fn new_main ( ) -> Thread {
1358- unsafe { Self :: new_inner ( ThreadName :: Main ) }
1392+ Self :: new_inner ( ThreadName :: Main )
13591393 }
13601394
1361- /// # Safety
1362- /// If `name` is `ThreadName::Other(_)`, the contained string must be valid UTF-8.
1363- unsafe fn new_inner ( name : ThreadName ) -> Thread {
1395+ fn new_inner ( name : ThreadName ) -> Thread {
13641396 // We have to use `unsafe` here to construct the `Parker` in-place,
13651397 // which is required for the UNIX implementation.
13661398 //
@@ -1483,15 +1515,11 @@ impl Thread {
14831515 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
14841516 #[ must_use]
14851517 pub fn name ( & self ) -> Option < & str > {
1486- self . cname ( ) . map ( |s| unsafe { str :: from_utf8_unchecked ( s . to_bytes ( ) ) } )
1518+ self . inner . name . as_str ( )
14871519 }
14881520
14891521 fn cname ( & self ) -> Option < & CStr > {
1490- match & self . inner . name {
1491- ThreadName :: Main => Some ( c"main" ) ,
1492- ThreadName :: Other ( other) => Some ( & other) ,
1493- ThreadName :: Unnamed => None ,
1494- }
1522+ self . inner . name . as_cstr ( )
14951523 }
14961524}
14971525
0 commit comments