-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
std: Add a new env
module
#21787
std: Add a new env
module
#21787
Conversation
r? @pcwalton (rust_highfive has picked a reviewer for you, use r? to override) |
r? @aturon note that rust-lang/rfcs#578 has not yet been merged and this should hold off on approval until that time. |
9908425
to
a9452d6
Compare
⌛ Testing commit b05dbc6 with merge 48a923d... |
💔 Test failed - auto-mac-64-nopt-t |
@bors: r=aturon 630df23 |
⌛ Testing commit 630df23 with merge a097829... |
💔 Test failed - auto-win-64-nopt-t |
This is an implementation of [RFC 578][rfc] which adds a new `std::env` module to replace most of the functionality in the current `std::os` module. More details can be found in the RFC itself, but as a summary the following methods have all been deprecated: [rfc]: rust-lang/rfcs#578 * `os::args_as_bytes` => `env::args` * `os::args` => `env::args` * `os::consts` => `env::consts` * `os::dll_filename` => no replacement, use `env::consts` directly * `os::page_size` => `env::page_size` * `os::make_absolute` => use `env::current_dir` + `join` instead * `os::getcwd` => `env::current_dir` * `os::change_dir` => `env::set_current_dir` * `os::homedir` => `env::home_dir` * `os::tmpdir` => `env::temp_dir` * `os::join_paths` => `env::join_paths` * `os::split_paths` => `env::split_paths` * `os::self_exe_name` => `env::current_exe` * `os::self_exe_path` => use `env::current_exe` + `pop` * `os::set_exit_status` => `env::set_exit_status` * `os::get_exit_status` => `env::get_exit_status` * `os::env` => `env::vars` * `os::env_as_bytes` => `env::vars` * `os::getenv` => `env::var` or `env::var_string` * `os::getenv_as_bytes` => `env::var` * `os::setenv` => `env::set_var` * `os::unsetenv` => `env::remove_var` Many function signatures have also been tweaked for various purposes, but the main changes were: * `Vec`-returning APIs now all return iterators instead * All APIs are now centered around `OsString` instead of `Vec<u8>` or `String`. There is currently on convenience API, `env::var_string`, which can be used to get the value of an environment variable as a unicode `String`. All old APIs are `#[deprecated]` in-place and will remain for some time to allow for migrations. The semantics of the APIs have been tweaked slightly with regard to dealing with invalid unicode (panic instead of replacement). The new `std::env` module is all contained within the `env` feature, so crates must add the following to access the new APIs: #![feature(env)] [breaking-change]
Conflicts: src/libstd/sys/unix/backtrace.rs src/libstd/sys/unix/os.rs
- add `_SC_GETPW_R_SIZE_MAX` constant - declare `struct passwd` - convert `load_self` to `current_exe` Note: OpenBSD don't provide system function to return a valuable Path for `env::current_exe`. The implementation is currently based on the value of `argv[0]`, which couldn't be used when executable is called via PATH.
This is great! With this, to get the command line arguments as a vector of strings, you simply write
Now, new programmers learning Rust will have to understand closures, iterators, functional programming, and UTF8 vs OS strings just to get past "Hello World". That will keep out the Code Academy riff-raff! Put in a convenience function in env::args for this. For a sense of the pain caused by this, see this Stack Overflow question: |
@John-Nagle your example panics if any of the arguments contain non-unicode data which is not that uncommon. Let’s not allow sloppy programming practices proliferate. |
I know. "pub fn into_string_lossy(Self) -> String;" for OsString doesn't seem to have been implemented yet. If you have non-Unicode data from OsString conversion of command line args, something is badly broken. |
Are you implying any system which uses non utf-8 locale is broken? |
I'm sympathetic to your original comment; the prominence of An alternative API that pushes stronger for Unicode-by-default might be: pub fn args() -> Args // Iterator<Item = String>
pub fn args_os() -> ArgsOs // Iterator<Item = OsString>
pub fn var<K: ?Sized>(key: &K) -> Result<String, VarError> where K: AsOsStr
pub fn var_os<K: ?Sized>(key: &K) -> Option<OsString> where K: AsOsStr
pub fn vars() -> Vars // Iterator<Item = (String, String)>
pub fn vars_os() -> VarsOs // Iterator<Item = (OsString, OsString)> where the non-OS versions will panic on non-Unicode data, just as your example does. We're likely to grow such variants regardless; the main question is what the un-decorated names like While I'm also sympathetic to worries about how much newcomers have to learn at once, I don't particularly buy the point about
The |
No, that's handled. OsString is an opaque type. See This whole area seems way overdesigned. The old approach was much simpler, and the use case for all this complexity seems to be corrupted UCS-2 on Windows. Anything Windows can represent as UCS-2, even with surrogate pairs, can be represented as a UTF-8 Rust string. Some conversions in the other direction won't work, and they should raise exceptions. Yes, this may mean that you can't put emoji into a Windows file name. |
The other side of Note that "the old approach" already had things like That said, as I wrote above, I think we probably want to consider making the "default" variants work with |
@John-Nagle yes, this is handled by Which is exactly why I argue against any methods converting to |
This appears to be backwards. UCS-2 is a superset of UTF-16. That means that e.g. Rust strings can be converted to UCS-2 without loss, but not vice versa. Regardless, the motivation for |
That seems to be the most practical approach. New Rust programmers should not have to comprehend all the topics covered in this discussion just to access the command line arguments. |
This is an implementation of RFC 578 which adds a new
std::env
moduleto replace most of the functionality in the current
std::os
module. Moredetails can be found in the RFC itself, but as a summary the following methods
have all been deprecated:
os::args_as_bytes
=>env::args
os::args
=>env::args
os::consts
=>env::consts
os::dll_filename
=> no replacement, useenv::consts
directlyos::page_size
=>env::page_size
os::make_absolute
=> useenv::current_dir
+join
insteados::getcwd
=>env::current_dir
os::change_dir
=>env::set_current_dir
os::homedir
=>env::home_dir
os::tmpdir
=>env::temp_dir
os::join_paths
=>env::join_paths
os::split_paths
=>env::split_paths
os::self_exe_name
=>env::current_exe
os::self_exe_path
=> useenv::current_exe
+pop
os::set_exit_status
=>env::set_exit_status
os::get_exit_status
=>env::get_exit_status
os::env
=>env::vars
os::env_as_bytes
=>env::vars
os::getenv
=>env::var
orenv::var_string
os::getenv_as_bytes
=>env::var
os::setenv
=>env::set_var
os::unsetenv
=>env::remove_var
Many function signatures have also been tweaked for various purposes, but the
main changes were:
Vec
-returning APIs now all return iterators insteadOsString
instead ofVec<u8>
orString
.There is currently on convenience API,
env::var_string
, which can be used toget the value of an environment variable as a unicode
String
.All old APIs are
#[deprecated]
in-place and will remain for some time to allowfor migrations. The semantics of the APIs have been tweaked slightly with regard
to dealing with invalid unicode (panic instead of replacement).
The new
std::env
module is all contained within theenv
feature, so cratesmust add the following to access the new APIs:
[breaking-change]