@@ -161,7 +161,7 @@ mod tests;
161
161
use crate :: any:: Any ;
162
162
use crate :: cell:: { Cell , OnceCell , UnsafeCell } ;
163
163
use crate :: env;
164
- use crate :: ffi:: { CStr , CString } ;
164
+ use crate :: ffi:: CStr ;
165
165
use crate :: fmt;
166
166
use crate :: io;
167
167
use crate :: marker:: PhantomData ;
@@ -487,11 +487,7 @@ impl Builder {
487
487
amt
488
488
} ) ;
489
489
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) ;
495
491
let their_thread = my_thread. clone ( ) ;
496
492
497
493
let my_packet: Arc < Packet < ' scope , T > > = Arc :: new ( Packet {
@@ -1299,10 +1295,51 @@ impl ThreadId {
1299
1295
/// The internal representation of a `Thread`'s name.
1300
1296
enum ThreadName {
1301
1297
Main ,
1302
- Other ( CString ) ,
1298
+ Other ( ThreadNameString ) ,
1303
1299
Unnamed ,
1304
1300
}
1305
1301
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
+
1306
1343
/// The internal representation of a `Thread` handle
1307
1344
struct Inner {
1308
1345
name : ThreadName , // Guaranteed to be UTF-8
@@ -1342,25 +1379,20 @@ pub struct Thread {
1342
1379
1343
1380
impl Thread {
1344
1381
/// 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 ( ) ) )
1350
1384
}
1351
1385
1352
1386
pub ( crate ) fn new_unnamed ( ) -> Thread {
1353
- unsafe { Self :: new_inner ( ThreadName :: Unnamed ) }
1387
+ Self :: new_inner ( ThreadName :: Unnamed )
1354
1388
}
1355
1389
1356
1390
// Used in runtime to construct main thread
1357
1391
pub ( crate ) fn new_main ( ) -> Thread {
1358
- unsafe { Self :: new_inner ( ThreadName :: Main ) }
1392
+ Self :: new_inner ( ThreadName :: Main )
1359
1393
}
1360
1394
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 {
1364
1396
// We have to use `unsafe` here to construct the `Parker` in-place,
1365
1397
// which is required for the UNIX implementation.
1366
1398
//
@@ -1483,15 +1515,11 @@ impl Thread {
1483
1515
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1484
1516
#[ must_use]
1485
1517
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 ( )
1487
1519
}
1488
1520
1489
1521
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 ( )
1495
1523
}
1496
1524
}
1497
1525
0 commit comments