Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

io::Error should be usable without allocation #12

Open
jethrogb opened this issue Mar 7, 2018 · 11 comments
Open

io::Error should be usable without allocation #12

jethrogb opened this issue Mar 7, 2018 · 11 comments
Labels

Comments

@jethrogb
Copy link
Collaborator

jethrogb commented Mar 7, 2018

In the mean time, see https://crates.io/crates/core_io

@Ericson2314
Copy link
Collaborator

Ericson2314 commented Mar 9, 2018

I'd prefer a plan like the one outlined here rust-lang/rfcs#2262 where we introduce core::io Read/Write traits with an associated error type, and then blanket impl the std::io ones in terms of that.

IMO the big fat error types like io::Error are an untyped kludge inherited from Unix and friends. There's no reason to be so coarse-grained on greenfield systems and I'd hope we could allow the standard library to support that. Also, even on conventional systems, it can be nice to know that e.g. the methods on slice won't fail. Finally, by putting versions of those traits in core, we can move more functionality below the platform-specific layers. As platform-agnostic code, that's where they both should be IMO, but practically, that allows them used by those layers which makes writing those layers much easier.

@Ericson2314
Copy link
Collaborator

rust-lang/rust#35121 fwiw if my !-based plan is to be taken, it would be nice if we could hack in !: From<_>, but we only have until beta hits stable!

@japaric
Copy link
Member

japaric commented Mar 27, 2018

I'd prefer a plan like the one outlined here rust-lang/rfcs#2262 where we introduce core::io Read/Write traits with an associated error type, and then blanket impl the std::io ones in terms of that.

Could the portability WG make an official-ish crate (or bless one of the existing ones) for that (Read/Write traits with associated types)? in the issue tracker of that crate / repo we could discuss whether we want to land them in the official core.

I have wanted those traits before and I'd rather not create and maintain such crate. I'm pretty sure I've seen at least one crate that defines such traits on crates.io and I think I've also seen those traits defined in the std implementation of some OS thing (?). We should all agree on a single definition of those traits, IMO.

@glandium
Copy link

There's core_io (https://crates.io/crates/core_io) but it's autogenerated at build time, which is not nice for vendoring.

@japaric
Copy link
Member

japaric commented Mar 27, 2018

There's core_io

That crate does not have the Read / Write traits with associated Error types. It has a port of std::io::Error to core.

@Ericson2314
Copy link
Collaborator

Ericson2314 commented Mar 27, 2018

@japaric Well of course I'd be happy to clean up my own https://github.com/QuiltOS/core-io and make it official /s.

In seriousness I'd to first gather consensus we're on board experimenting with this (maybe with an eRFC), and then implement on a branch/fork in the actual repo. The finer-grained design details would be pend on what we discover during the implementation, as it's nigh impossible to predict without actually doing the work, and a waste of effort to expect an implementation first.

@Ericson2314
Copy link
Collaborator

@fluffysquirrels picking up from rust-lang/rfcs#2262 (comment)

Regarding Read::read_to_vec and similar, perhaps core::io could have a feature flag to toggle features that require alloc.

I don't think the feature flag is so good because then every instance also needs the feature flag. For example, there are uses for these core::io in situations where dynamic memory management (real time systems). Many instances for such things could also be extended with Read::read_to_vec, and I think it's easier to just optionally depend on alloc to write that optional impl, than optionally depend on your dependencies feature flag to depend on alloc and also directly optional depend on alloc, and and optionally include the method with the impl. And if the where clause on the impl is more restricted in the alloc case, then even more cfg machinery is needed!

@fluffysquirrels
Copy link

Optional dependencies and feature flags are very similar (cargo docs on features), so whichever is fine. If you have downstream dependencies that optionally use alloc/std, I think you may need feature flags to toggle their options.

Last I looked importing alloc in a no_std crate actually required a crate attribute #![feature(alloc)] rather than a dependency in Cargo.toml, but this may have moved on.

I have worked with no_std, no alloc crates for microcontrollers, and personally I found that feature flags are straightforward to use once you implement your first one and get used to the recipe:

  • Add a feature flag to cargo.toml
  • Document feature flag in crate lib for consumers
  • Optionally specify the feature flag for all your dependencies that require it
  • Add [cfg(...)] blocks to all relevant items in source code

@jocutajar
Copy link

jocutajar commented Mar 28, 2019

Ahoj, taking this thread to 2019, I'm wondering where we are with this topic?

Over on https://internals.rust-lang.org/t/idea-lowering-std-io-to-core/7341 I learned from rpjohnst that

the portability lint should eventually allow #![no_std]-like applications that depend on a more granularly-defined subset of std than just "core vs std." This would let you do what you want, even to the point of omitting read_to_end/read_to_string in applications with no global allocator.

I imagine at that point we could move everything into std and reduce core to a compatibility crate that re-exports the things it used to define.

This seems to be a move in a completely opposite direction. Do I get it right that as long as I'm not touching allocation requiring methods, I can work against std even without an allocator? Can someone shed a light on this? Is that already available? It sounds like dark magic to me.

I'd like to produce a library without std dependency, but exposing Read / Write implementation for interoperability. I find the Err associated type more Rusty, but I cannot foresee the implications. Looking at QuiltOS/core-io I was surprised how simple it is. Such a simple thing doesn't probably require much maintenance. Perhaps it is time for a breaking change and Read2 / Write2? :D Or perhaps the more generic but less feature-rich Read2 / Write2 could be expanded on in std to deliver compatible features?

@lygstate
Copy link

Seems discussed a lot, what's the real blocker?

@ColinFinck
Copy link

To put the current situation in a nutshell after asking in various chats (please correct me if I'm wrong on anything):

  • std::io::Read and std::io::Write hardcode the return type to std::io::Error, which is why the entire core::io discussion is always about the error type.
  • std::io::Error is usually created via std::io::Error::new and stores arbitrary errors in a Box field. Both things require heap allocations, which are not available in every no_std environment. Hence, std::io::Error can never be turned into core::io::Error in its current form.
  • On the other hand, std::io::Error has also been stabilized, so we can't remove the Box anymore.

Taking all of that together, we need a new error type for core::io that is different from std::io::Error.
But I also take it that Rust only ever moved identical things from std to core (e.g. core::time::Duration is the same as std::time::Duration).
Hence, a new I/O error type that is different from std::io::Error cannot be called core::io::Error.

Considering these facts, is there any chance for stabilized core::io::{Error, Read, Write} at all? (even if under a different name)
Or should this task be forever outsourced to external crates like https://github.com/Kixunil/genio?

CC'ing the Error Handling Project Group, which looks like the new place to handle this issue: rust-lang/project-error-handling#11
The Rust Portability WG seems dead: #22 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

8 participants