@@ -537,10 +537,6 @@ impl Stream for Timer {
537537/// For higher-level primitives built on top of [`Async`], look into [`async-net`] or
538538/// [`async-process`] (on Unix).
539539///
540- /// The most notable caveat is that it is unsafe to access the inner I/O source mutably
541- /// using this primitive. Traits likes [`AsyncRead`] and [`AsyncWrite`] are not implemented by
542- /// default unless it is guaranteed that the resource won't be invalidated by reading or writing.
543- /// See the [`IoSafe`] trait for more information.
544540///
545541/// [`async-net`]: https://github.com/smol-rs/async-net
546542/// [`async-process`]: https://github.com/smol-rs/async-process
@@ -680,9 +676,7 @@ impl<T: AsFd> Async<T> {
680676 /// it is not set. If not set to non-blocking mode, I/O operations may block the current thread
681677 /// and cause a deadlock in an asynchronous context.
682678 pub fn new_nonblocking ( io : T ) -> io:: Result < Async < T > > {
683- // SAFETY: It is impossible to drop the I/O source while it is registered through
684- // this type.
685- let registration = unsafe { Registration :: new ( io. as_fd ( ) ) } ;
679+ let registration = Registration :: new ( io. as_fd ( ) ) ;
686680
687681 Ok ( Async {
688682 source : Reactor :: get ( ) . insert_io ( registration) ?,
@@ -775,10 +769,7 @@ impl<T: AsSocket> Async<T> {
775769 /// and cause a deadlock in an asynchronous context.
776770 pub fn new_nonblocking ( io : T ) -> io:: Result < Async < T > > {
777771 // Create the registration.
778- //
779- // SAFETY: It is impossible to drop the I/O source while it is registered through
780- // this type.
781- let registration = unsafe { Registration :: new ( io. as_socket ( ) ) } ;
772+ let registration = Registration :: new ( io. as_socket ( ) ) ;
782773
783774 Ok ( Async {
784775 source : Reactor :: get ( ) . insert_io ( registration) ?,
@@ -839,10 +830,6 @@ impl<T> Async<T> {
839830
840831 /// Gets a mutable reference to the inner I/O handle.
841832 ///
842- /// # Safety
843- ///
844- /// The underlying I/O source must not be dropped using this function.
845- ///
846833 /// # Examples
847834 ///
848835 /// ```
@@ -851,10 +838,10 @@ impl<T> Async<T> {
851838 ///
852839 /// # futures_lite::future::block_on(async {
853840 /// let mut listener = Async::<TcpListener>::bind(([127, 0, 0, 1], 0))?;
854- /// let inner = unsafe { listener.get_mut() } ;
841+ /// let inner = listener.get_mut();
855842 /// # std::io::Result::Ok(()) });
856843 /// ```
857- pub unsafe fn get_mut ( & mut self ) -> & mut T {
844+ pub fn get_mut ( & mut self ) -> & mut T {
858845 self . io . as_mut ( ) . unwrap ( )
859846 }
860847
@@ -1044,10 +1031,6 @@ impl<T> Async<T> {
10441031 ///
10451032 /// The closure receives a mutable reference to the I/O handle.
10461033 ///
1047- /// # Safety
1048- ///
1049- /// In the closure, the underlying I/O source must not be dropped.
1050- ///
10511034 /// # Examples
10521035 ///
10531036 /// ```no_run
@@ -1058,10 +1041,10 @@ impl<T> Async<T> {
10581041 /// let mut listener = Async::<TcpListener>::bind(([127, 0, 0, 1], 0))?;
10591042 ///
10601043 /// // Accept a new client asynchronously.
1061- /// let (stream, addr) = unsafe { listener.read_with_mut(|l| l.accept()).await? } ;
1044+ /// let (stream, addr) = listener.read_with_mut(|l| l.accept()).await?;
10621045 /// # std::io::Result::Ok(()) });
10631046 /// ```
1064- pub async unsafe fn read_with_mut < R > (
1047+ pub async fn read_with_mut < R > (
10651048 & mut self ,
10661049 op : impl FnMut ( & mut T ) -> io:: Result < R > ,
10671050 ) -> io:: Result < R > {
@@ -1116,11 +1099,6 @@ impl<T> Async<T> {
11161099 /// [`io::ErrorKind::WouldBlock`]. In between iterations of the loop, it waits until the OS
11171100 /// sends a notification that the I/O handle is writable.
11181101 ///
1119- /// # Safety
1120- ///
1121- /// The closure receives a mutable reference to the I/O handle. In the closure, the underlying
1122- /// I/O source must not be dropped.
1123- ///
11241102 /// # Examples
11251103 ///
11261104 /// ```no_run
@@ -1132,10 +1110,10 @@ impl<T> Async<T> {
11321110 /// socket.get_ref().connect("127.0.0.1:9000")?;
11331111 ///
11341112 /// let msg = b"hello";
1135- /// let len = unsafe { socket.write_with_mut(|s| s.send(msg)).await? } ;
1113+ /// let len = socket.write_with_mut(|s| s.send(msg)).await?;
11361114 /// # std::io::Result::Ok(()) });
11371115 /// ```
1138- pub async unsafe fn write_with_mut < R > (
1116+ pub async fn write_with_mut < R > (
11391117 & mut self ,
11401118 op : impl FnMut ( & mut T ) -> io:: Result < R > ,
11411119 ) -> io:: Result < R > {
@@ -1170,19 +1148,9 @@ impl<T> Drop for Async<T> {
11701148
11711149/// Types whose I/O trait implementations do not drop the underlying I/O source.
11721150///
1173- /// The resource contained inside of the [`Async`] cannot be invalidated. This invalidation can
1174- /// happen if the inner resource (the [`TcpStream`], [`UnixListener`] or other `T`) is moved out
1175- /// and dropped before the [`Async`]. Because of this, functions that grant mutable access to
1176- /// the inner type are unsafe, as there is no way to guarantee that the source won't be dropped
1177- /// and a dangling handle won't be left behind.
1178- ///
1179- /// Unfortunately this extends to implementations of [`Read`] and [`Write`]. Since methods on those
1180- /// traits take `&mut`, there is no guarantee that the implementor of those traits won't move the
1181- /// source out while the method is being run.
1182- ///
1183- /// This trait is an antidote to this predicament. By implementing this trait, the user pledges
1184- /// that using any I/O traits won't destroy the source. This way, [`Async`] can implement the
1185- /// `async` version of these I/O traits, like [`AsyncRead`] and [`AsyncWrite`].
1151+ /// Previously, this constraint was used to ensure only certain I/O sources could
1152+ /// be used with [`Async`]. But this constraint no longer applies, so this trait is
1153+ /// now deprecated.
11861154///
11871155/// # Safety
11881156///
@@ -1201,6 +1169,7 @@ impl<T> Drop for Async<T> {
12011169///
12021170/// [`AsyncRead`]: https://docs.rs/futures-io/latest/futures_io/trait.AsyncRead.html
12031171/// [`AsyncWrite`]: https://docs.rs/futures-io/latest/futures_io/trait.AsyncWrite.html
1172+ #[ deprecated = "this trait is now no longer required" ]
12041173pub unsafe trait IoSafe { }
12051174
12061175/// Reference types can't be mutated.
@@ -1234,46 +1203,67 @@ pub unsafe trait IoSafe {}
12341203///
12351204/// We solve this problem by only calling `as_fd()` once to get the original source. Implementations
12361205/// like this are considered buggy (but not unsound) and are thus not really supported by `async-io`.
1206+ #[ allow( deprecated) ]
12371207unsafe impl < T : ?Sized > IoSafe for & T { }
12381208
12391209// Can be implemented on top of libstd types.
1210+ #[ allow( deprecated) ]
12401211unsafe impl IoSafe for std:: fs:: File { }
1212+ #[ allow( deprecated) ]
12411213unsafe impl IoSafe for std:: io:: Stderr { }
1214+ #[ allow( deprecated) ]
12421215unsafe impl IoSafe for std:: io:: Stdin { }
1216+ #[ allow( deprecated) ]
12431217unsafe impl IoSafe for std:: io:: Stdout { }
1218+ #[ allow( deprecated) ]
12441219unsafe impl IoSafe for std:: io:: StderrLock < ' _ > { }
1220+ #[ allow( deprecated) ]
12451221unsafe impl IoSafe for std:: io:: StdinLock < ' _ > { }
1222+ #[ allow( deprecated) ]
12461223unsafe impl IoSafe for std:: io:: StdoutLock < ' _ > { }
1224+ #[ allow( deprecated) ]
12471225unsafe impl IoSafe for std:: net:: TcpStream { }
1226+ #[ allow( deprecated) ]
12481227unsafe impl IoSafe for std:: process:: ChildStdin { }
1228+ #[ allow( deprecated) ]
12491229unsafe impl IoSafe for std:: process:: ChildStdout { }
1230+ #[ allow( deprecated) ]
12501231unsafe impl IoSafe for std:: process:: ChildStderr { }
12511232
12521233#[ cfg( unix) ]
1234+ #[ allow( deprecated) ]
12531235unsafe impl IoSafe for std:: os:: unix:: net:: UnixStream { }
12541236
12551237// PipeReader & PipeWriter require std >= 1.87, our MSRV is 1.71, hence
12561238// conditional on cfg()s, generated from build.rs
12571239#[ cfg( not( async_io_no_pipe) ) ]
1240+ #[ allow( deprecated, clippy:: incompatible_msrv) ]
12581241unsafe impl IoSafe for std:: io:: PipeReader { }
12591242#[ cfg( not( async_io_no_pipe) ) ]
1243+ #[ allow( deprecated, clippy:: incompatible_msrv) ]
12601244unsafe impl IoSafe for std:: io:: PipeWriter { }
12611245
1246+ #[ allow( deprecated) ]
12621247unsafe impl < T : IoSafe + Read > IoSafe for std:: io:: BufReader < T > { }
1248+ #[ allow( deprecated) ]
12631249unsafe impl < T : IoSafe + Write > IoSafe for std:: io:: BufWriter < T > { }
1250+ #[ allow( deprecated) ]
12641251unsafe impl < T : IoSafe + Write > IoSafe for std:: io:: LineWriter < T > { }
1252+ #[ allow( deprecated) ]
12651253unsafe impl < T : IoSafe + ?Sized > IoSafe for & mut T { }
1254+ #[ allow( deprecated) ]
12661255unsafe impl < T : IoSafe + ?Sized > IoSafe for Box < T > { }
1256+ #[ allow( deprecated) ]
12671257unsafe impl < T : Clone + IoSafe > IoSafe for std:: borrow:: Cow < ' _ , T > { }
12681258
1269- impl < T : IoSafe + Read > AsyncRead for Async < T > {
1259+ impl < T : Read > AsyncRead for Async < T > {
12701260 fn poll_read (
12711261 mut self : Pin < & mut Self > ,
12721262 cx : & mut Context < ' _ > ,
12731263 buf : & mut [ u8 ] ,
12741264 ) -> Poll < io:: Result < usize > > {
12751265 loop {
1276- match unsafe { ( * self ) . get_mut ( ) } . read ( buf) {
1266+ match ( * self ) . get_mut ( ) . read ( buf) {
12771267 Err ( err) if err. kind ( ) == io:: ErrorKind :: WouldBlock => { }
12781268 res => return Poll :: Ready ( res) ,
12791269 }
@@ -1287,7 +1277,7 @@ impl<T: IoSafe + Read> AsyncRead for Async<T> {
12871277 bufs : & mut [ IoSliceMut < ' _ > ] ,
12881278 ) -> Poll < io:: Result < usize > > {
12891279 loop {
1290- match unsafe { ( * self ) . get_mut ( ) } . read_vectored ( bufs) {
1280+ match ( * self ) . get_mut ( ) . read_vectored ( bufs) {
12911281 Err ( err) if err. kind ( ) == io:: ErrorKind :: WouldBlock => { }
12921282 res => return Poll :: Ready ( res) ,
12931283 }
@@ -1331,14 +1321,14 @@ where
13311321 }
13321322}
13331323
1334- impl < T : IoSafe + Write > AsyncWrite for Async < T > {
1324+ impl < T : Write > AsyncWrite for Async < T > {
13351325 fn poll_write (
13361326 mut self : Pin < & mut Self > ,
13371327 cx : & mut Context < ' _ > ,
13381328 buf : & [ u8 ] ,
13391329 ) -> Poll < io:: Result < usize > > {
13401330 loop {
1341- match unsafe { ( * self ) . get_mut ( ) } . write ( buf) {
1331+ match ( * self ) . get_mut ( ) . write ( buf) {
13421332 Err ( err) if err. kind ( ) == io:: ErrorKind :: WouldBlock => { }
13431333 res => return Poll :: Ready ( res) ,
13441334 }
@@ -1352,7 +1342,7 @@ impl<T: IoSafe + Write> AsyncWrite for Async<T> {
13521342 bufs : & [ IoSlice < ' _ > ] ,
13531343 ) -> Poll < io:: Result < usize > > {
13541344 loop {
1355- match unsafe { ( * self ) . get_mut ( ) } . write_vectored ( bufs) {
1345+ match ( * self ) . get_mut ( ) . write_vectored ( bufs) {
13561346 Err ( err) if err. kind ( ) == io:: ErrorKind :: WouldBlock => { }
13571347 res => return Poll :: Ready ( res) ,
13581348 }
@@ -1362,7 +1352,7 @@ impl<T: IoSafe + Write> AsyncWrite for Async<T> {
13621352
13631353 fn poll_flush ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < io:: Result < ( ) > > {
13641354 loop {
1365- match unsafe { ( * self ) . get_mut ( ) } . flush ( ) {
1355+ match ( * self ) . get_mut ( ) . flush ( ) {
13661356 Err ( err) if err. kind ( ) == io:: ErrorKind :: WouldBlock => { }
13671357 res => return Poll :: Ready ( res) ,
13681358 }
0 commit comments