Skip to content

Commit 5a4ab26

Browse files
committed
Auto merge of rust-lang#78880 - CDirkx:not_supported, r=joshtriplett
Add `Unsupported` to `std::io::ErrorKind` I noticed a significant portion of the uses of `ErrorKind::Other` in std is for unsupported operations. The notion that a specific operation is not available on a target (and will thus never succeed) seems semantically distinct enough from just "an unspecified error occurred", which is why I am proposing to add the variant `Unsupported` to `std::io::ErrorKind`. **Implementation**: The following variant will be added to `std::io::ErrorKind`: ```rust /// This operation is unsupported on this platform. Unsupported ``` `std::io::ErrorKind::Unsupported` is an error returned when a given operation is not supported on a platform, and will thus never succeed; there is no way for the software to recover. It will be used instead of `Other` where appropriate, e.g. on wasm for file and network operations. `decode_error_kind` will be updated to decode operating system errors to `Unsupported`: - Unix and VxWorks: `libc::ENOSYS` - Windows: `c::ERROR_CALL_NOT_IMPLEMENTED` - WASI: `wasi::ERRNO_NOSYS` **Stability**: This changes the kind of error returned by some functions on some platforms, which I think is not covered by the stability guarantees of the std? User code could depend on this behavior, expecting `ErrorKind::Other`, however the docs already mention: > Errors that are `Other` now may move to a different or a new `ErrorKind` variant in the future. It is not recommended to match an error against `Other` and to expect any additional characteristics, e.g., a specific `Error::raw_os_error` return value. The most recent variant added to `ErrorKind` was `UnexpectedEof` in `1.6.0` (almost 5 years ago), but `ErrorKind` is marked as `#[non_exhaustive]` and the docs warn about exhaustively matching on it, so adding a new variant per se should not be a breaking change. The variant `Unsupported` itself could be marked as `#[unstable]`, however, because this PR also immediately uses this new variant and changes the errors returned by functions I'm inclined to agree with the others in this thread that the variant should be insta-stabilized.
2 parents ef88434 + 5b5afae commit 5a4ab26

File tree

20 files changed

+81
-56
lines changed

20 files changed

+81
-56
lines changed

library/std/src/fs/tests.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1329,7 +1329,9 @@ fn metadata_access_times() {
13291329
match (a.created(), b.created()) {
13301330
(Ok(t1), Ok(t2)) => assert!(t1 <= t2),
13311331
(Err(e1), Err(e2))
1332-
if e1.kind() == ErrorKind::Other && e2.kind() == ErrorKind::Other => {}
1332+
if e1.kind() == ErrorKind::Other && e2.kind() == ErrorKind::Other
1333+
|| e1.kind() == ErrorKind::Unsupported
1334+
&& e2.kind() == ErrorKind::Unsupported => {}
13331335
(a, b) => {
13341336
panic!("creation time must be always supported or not supported: {:?} {:?}", a, b,)
13351337
}

library/std/src/io/error.rs

+7
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,12 @@ pub enum ErrorKind {
180180
/// read.
181181
#[stable(feature = "read_exact", since = "1.6.0")]
182182
UnexpectedEof,
183+
184+
/// This operation is unsupported on this platform.
185+
///
186+
/// This means that the operation can never succeed.
187+
#[stable(feature = "unsupported_error", since = "1.53.0")]
188+
Unsupported,
183189
}
184190

185191
impl ErrorKind {
@@ -203,6 +209,7 @@ impl ErrorKind {
203209
ErrorKind::Interrupted => "operation interrupted",
204210
ErrorKind::Other => "other os error",
205211
ErrorKind::UnexpectedEof => "unexpected end of file",
212+
ErrorKind::Unsupported => "unsupported",
206213
}
207214
}
208215
}

library/std/src/sys/hermit/fd.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
#![unstable(reason = "not public", issue = "none", feature = "fd")]
22

3-
use crate::io::{self, ErrorKind, Read};
3+
use crate::io::{self, Read};
44
use crate::mem;
55
use crate::sys::cvt;
66
use crate::sys::hermit::abi;
7+
use crate::sys::unsupported;
78
use crate::sys_common::AsInner;
89

910
#[derive(Debug)]
@@ -46,19 +47,19 @@ impl FileDesc {
4647
self.duplicate_path(&[])
4748
}
4849
pub fn duplicate_path(&self, _path: &[u8]) -> io::Result<FileDesc> {
49-
Err(io::Error::new_const(ErrorKind::Other, &"duplicate isn't supported"))
50+
unsupported()
5051
}
5152

5253
pub fn nonblocking(&self) -> io::Result<bool> {
5354
Ok(false)
5455
}
5556

5657
pub fn set_cloexec(&self) -> io::Result<()> {
57-
Err(io::Error::new_const(ErrorKind::Other, &"cloexec isn't supported"))
58+
unsupported()
5859
}
5960

6061
pub fn set_nonblocking(&self, _nonblocking: bool) -> io::Result<()> {
61-
Err(io::Error::new_const(ErrorKind::Other, &"nonblocking isn't supported"))
62+
unsupported()
6263
}
6364
}
6465

library/std/src/sys/hermit/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ pub fn unsupported<T>() -> crate::io::Result<T> {
5656

5757
pub fn unsupported_err() -> crate::io::Error {
5858
crate::io::Error::new_const(
59-
crate::io::ErrorKind::Other,
59+
crate::io::ErrorKind::Unsupported,
6060
&"operation not supported on HermitCore yet",
6161
)
6262
}

library/std/src/sys/hermit/net.rs

+39-39
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ impl TcpStream {
166166
}
167167

168168
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
169-
Err(io::Error::new_const(ErrorKind::Other, &"socket_addr isn't supported"))
169+
unsupported()
170170
}
171171

172172
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
@@ -199,7 +199,7 @@ impl TcpStream {
199199
}
200200

201201
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
202-
Err(io::Error::new_const(ErrorKind::Other, &"take_error isn't supported"))
202+
unsupported()
203203
}
204204

205205
pub fn set_nonblocking(&self, mode: bool) -> io::Result<()> {
@@ -247,27 +247,27 @@ impl TcpListener {
247247
}
248248

249249
pub fn set_ttl(&self, _: u32) -> io::Result<()> {
250-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
250+
unsupported()
251251
}
252252

253253
pub fn ttl(&self) -> io::Result<u32> {
254-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
254+
unsupported()
255255
}
256256

257257
pub fn set_only_v6(&self, _: bool) -> io::Result<()> {
258-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
258+
unsupported()
259259
}
260260

261261
pub fn only_v6(&self) -> io::Result<bool> {
262-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
262+
unsupported()
263263
}
264264

265265
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
266-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
266+
unsupported()
267267
}
268268

269269
pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
270-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
270+
unsupported()
271271
}
272272
}
273273

@@ -281,127 +281,127 @@ pub struct UdpSocket(abi::Handle);
281281

282282
impl UdpSocket {
283283
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
284-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
284+
unsupported()
285285
}
286286

287287
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
288-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
288+
unsupported()
289289
}
290290

291291
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
292-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
292+
unsupported()
293293
}
294294

295295
pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
296-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
296+
unsupported()
297297
}
298298

299299
pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
300-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
300+
unsupported()
301301
}
302302

303303
pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result<usize> {
304-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
304+
unsupported()
305305
}
306306

307307
pub fn duplicate(&self) -> io::Result<UdpSocket> {
308-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
308+
unsupported()
309309
}
310310

311311
pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
312-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
312+
unsupported()
313313
}
314314

315315
pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
316-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
316+
unsupported()
317317
}
318318

319319
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
320-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
320+
unsupported()
321321
}
322322

323323
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
324-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
324+
unsupported()
325325
}
326326

327327
pub fn set_broadcast(&self, _: bool) -> io::Result<()> {
328-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
328+
unsupported()
329329
}
330330

331331
pub fn broadcast(&self) -> io::Result<bool> {
332-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
332+
unsupported()
333333
}
334334

335335
pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> {
336-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
336+
unsupported()
337337
}
338338

339339
pub fn multicast_loop_v4(&self) -> io::Result<bool> {
340-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
340+
unsupported()
341341
}
342342

343343
pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> {
344-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
344+
unsupported()
345345
}
346346

347347
pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
348-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
348+
unsupported()
349349
}
350350

351351
pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> {
352-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
352+
unsupported()
353353
}
354354

355355
pub fn multicast_loop_v6(&self) -> io::Result<bool> {
356-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
356+
unsupported()
357357
}
358358

359359
pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
360-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
360+
unsupported()
361361
}
362362

363363
pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
364-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
364+
unsupported()
365365
}
366366

367367
pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
368-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
368+
unsupported()
369369
}
370370

371371
pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
372-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
372+
unsupported()
373373
}
374374

375375
pub fn set_ttl(&self, _: u32) -> io::Result<()> {
376-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
376+
unsupported()
377377
}
378378

379379
pub fn ttl(&self) -> io::Result<u32> {
380-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
380+
unsupported()
381381
}
382382

383383
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
384-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
384+
unsupported()
385385
}
386386

387387
pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
388-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
388+
unsupported()
389389
}
390390

391391
pub fn recv(&self, _: &mut [u8]) -> io::Result<usize> {
392-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
392+
unsupported()
393393
}
394394

395395
pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
396-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
396+
unsupported()
397397
}
398398

399399
pub fn send(&self, _: &[u8]) -> io::Result<usize> {
400-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
400+
unsupported()
401401
}
402402

403403
pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
404-
Err(io::Error::new_const(ErrorKind::Other, &"not supported"))
404+
unsupported()
405405
}
406406
}
407407

library/std/src/sys/sgx/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ pub fn unsupported<T>() -> crate::io::Result<T> {
5050
}
5151

5252
pub fn unsupported_err() -> crate::io::Error {
53-
crate::io::Error::new_const(ErrorKind::Other, &"operation not supported on SGX yet")
53+
crate::io::Error::new_const(ErrorKind::Unsupported, &"operation not supported on SGX yet")
5454
}
5555

5656
/// This function is used to implement various functions that doesn't exist,

library/std/src/sys/unix/fs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ impl FileAttr {
366366
}
367367

368368
Err(io::Error::new_const(
369-
io::ErrorKind::Other,
369+
io::ErrorKind::Unsupported,
370370
&"creation time is not available on this platform \
371371
currently",
372372
))

library/std/src/sys/unix/l4re.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
macro_rules! unimpl {
22
() => {
3-
return Err(io::Error::new_const(io::ErrorKind::Other, &"No networking available on L4Re."));
3+
return Err(io::Error::new_const(
4+
io::ErrorKind::Unsupported,
5+
&"No networking available on L4Re.",
6+
));
47
};
58
}
69

library/std/src/sys/unix/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
148148
libc::EINVAL => ErrorKind::InvalidInput,
149149
libc::ETIMEDOUT => ErrorKind::TimedOut,
150150
libc::EEXIST => ErrorKind::AlreadyExists,
151+
libc::ENOSYS => ErrorKind::Unsupported,
151152

152153
// These two constants can have the same value on some systems,
153154
// but different values on others, so we can't use a match

library/std/src/sys/unix/os.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
447447
#[cfg(any(target_os = "fuchsia", target_os = "l4re"))]
448448
pub fn current_exe() -> io::Result<PathBuf> {
449449
use crate::io::ErrorKind;
450-
Err(io::Error::new_const(ErrorKind::Other, &"Not yet implemented!"))
450+
Err(io::Error::new_const(ErrorKind::Unsupported, &"Not yet implemented!"))
451451
}
452452

453453
#[cfg(target_os = "vxworks")]

library/std/src/sys/unsupported/common.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ pub fn unsupported<T>() -> std_io::Result<T> {
1818
}
1919

2020
pub fn unsupported_err() -> std_io::Error {
21-
std_io::Error::new_const(std_io::ErrorKind::Other, &"operation not supported on this platform")
21+
std_io::Error::new_const(
22+
std_io::ErrorKind::Unsupported,
23+
&"operation not supported on this platform",
24+
)
2225
}
2326

2427
pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind {

library/std/src/sys/unsupported/os.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,11 @@ pub fn getenv(_: &OsStr) -> io::Result<Option<OsString>> {
8080
}
8181

8282
pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {
83-
Err(io::Error::new_const(io::ErrorKind::Other, &"cannot set env vars on this platform"))
83+
Err(io::Error::new_const(io::ErrorKind::Unsupported, &"cannot set env vars on this platform"))
8484
}
8585

8686
pub fn unsetenv(_: &OsStr) -> io::Result<()> {
87-
Err(io::Error::new_const(io::ErrorKind::Other, &"cannot unset env vars on this platform"))
87+
Err(io::Error::new_const(io::ErrorKind::Unsupported, &"cannot unset env vars on this platform"))
8888
}
8989

9090
pub fn temp_dir() -> PathBuf {

library/std/src/sys/vxworks/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
8383
libc::EINVAL => ErrorKind::InvalidInput,
8484
libc::ETIMEDOUT => ErrorKind::TimedOut,
8585
libc::EEXIST => ErrorKind::AlreadyExists,
86+
libc::ENOSYS => ErrorKind::Unsupported,
8687

8788
// These two constants can have the same value on some systems,
8889
// but different values on others, so we can't use a match

library/std/src/sys/wasi/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind {
7878
wasi::ERRNO_TIMEDOUT => TimedOut,
7979
wasi::ERRNO_EXIST => AlreadyExists,
8080
wasi::ERRNO_AGAIN => WouldBlock,
81+
wasi::ERRNO_NOSYS => Unsupported,
8182
_ => Other,
8283
}
8384
}

library/std/src/sys/windows/fs.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -802,7 +802,10 @@ pub fn link(original: &Path, link: &Path) -> io::Result<()> {
802802

803803
#[cfg(target_vendor = "uwp")]
804804
pub fn link(_original: &Path, _link: &Path) -> io::Result<()> {
805-
return Err(io::Error::new_const(io::ErrorKind::Other, &"hard link are not supported on UWP"));
805+
return Err(io::Error::new_const(
806+
io::ErrorKind::Unsupported,
807+
&"hard link are not supported on UWP",
808+
));
806809
}
807810

808811
pub fn stat(path: &Path) -> io::Result<FileAttr> {

library/std/src/sys/windows/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
7878
| c::ERROR_IPSEC_IKE_TIMED_OUT
7979
| c::ERROR_RUNLEVEL_SWITCH_TIMEOUT
8080
| c::ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT => return ErrorKind::TimedOut,
81+
c::ERROR_CALL_NOT_IMPLEMENTED => return ErrorKind::Unsupported,
8182
_ => {}
8283
}
8384

0 commit comments

Comments
 (0)