Skip to content

std: per-platform decode_error_kind copies have drifted (wasi/teeos missing arms) #158490

Description

@valentynkit

library/std/src/sys/io/error/ has a separate hand-written decode_error_kind (raw OS errno → io::ErrorKind) for each platform. Three of them, unix.rs, wasi.rs, and teeos.rs, decode the POSIX/libc errno space and are near-identical copies; the rest (windows.rs, uefi.rs, and the smaller targets) have their own error namespaces.

The three POSIX copies are maintained by hand, and they have drifted. There seem to be two parts to this: a few missing mappings, and a question about whether the drift is worth preventing.

The gaps

teeos.rs states at the top of its table that it is a copy of unix:

// library/std/src/sys/io/error/teeos.rs
// Note: code below is 1:1 copied from unix/mod.rs

The copies have since drifted apart, each in its own way. Taking unix.rs as the reference (current master):

errno → kind unix.rs wasi.rs teeos.rs
ENOTEMPTYDirectoryNotEmpty yes (cfg(not(aix))) missing yes
EINPROGRESSInProgress yes yes missing
EMFILE/ENFILETooManyOpenFiles yes yes missing
EOPNOTSUPPUnsupported yes yes missing

So teeos.rs is missing three of unix's arms and wasi.rs is missing a different one. On each affected target the errno decodes to Uncategorized instead of its specific kind, which a caller can only recover with raw_os_error(). As far as I can tell nothing in the test suite asserts these mappings, so the drift isn't caught by CI.

These look like straightforward parity fixes: add the missing arms, each already present in the other POSIX tables. I can put up a PR for them if that's useful.

The open question

This is not the first time the copies have drifted:

Every new errno mapping has to be added to each POSIX copy separately, and a missed one is a silent per-platform difference that no test catches. Would it be worth having the POSIX targets share one decode core, with each supplying only its real deltas (errnos that differ or do not exist there, like the existing cfg(not(aix)) on ENOTEMPTY)? A new mapping would then be written once and inherited everywhere.

I wanted to ask first rather than send a PR for that, since the tricky part is real: not every errno constant exists on every target (libc gates them), so a shared table would need careful per-target cfg/feature handling, which may be why the copies exist today. There is also in-flight work moving io::Error into core (#153915, #155625) that a change here should stay clear of.

If the split is deliberate, that's a fine answer; the missing arms are probably worth adding either way.

@rustbot label +T-libs +A-io

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ioArea: `std::io`, `std::fs`, `std::net` and `std::path`T-libsRelevant to the library team, which will review and decide on the PR/issue.needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions