Based on @paolobarbolini's tip that the unsafe block was unnecessary in
this case.
Not much left of `hexify()` after this, so seemed clearer to just inline
it.
To make this work, the `#[rustc_on_unimplemented]` data needs to be used to
report method resolution errors, which is most of what this commit does.
Fixes#94581
Add core::hint::must_use
The example code in this documentation is minimized from a real-world situation in the `anyhow` crate where this function would have been valuable.
Having this provided by the standard library is especially useful for proc macros, even more than for macro_rules. That's because proc macro crates aren't allowed to export anything other than macros, so they couldn't make their own `must_use` function for their macro-generated code to call.
<br>
## Rendered documentation
> An identity function that causes an `unused_must_use` warning to be triggered if the given value is not used (returned, stored in a variable, etc) by the caller.
>
> This is primarily intended for use in macro-generated code, in which a [`#[must_use]` attribute][must_use] either on a type or a function would not be convenient.
>
> [must_use]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute
>
> ### Example
>
> ```rust
> #![feature(hint_must_use)]
>
> use core::fmt;
>
> pub struct Error(/* ... */);
>
> #[macro_export]
> macro_rules! make_error {
> ($($args:expr),*) => {
> core::hint::must_use({
> let error = $crate::make_error(core::format_args!($($args),*));
> error
> })
> };
> }
>
> // Implementation detail of make_error! macro.
> #[doc(hidden)]
> pub fn make_error(args: fmt::Arguments<'_>) -> Error {
> Error(/* ... */)
> }
>
> fn demo() -> Option<Error> {
> if true {
> // Oops, meant to write `return Some(make_error!("..."));`
> Some(make_error!("..."));
> }
> None
> }
> ```
>
> In the above example, we'd like an `unused_must_use` lint to apply to the value created by `make_error!`. However, neither `#[must_use]` on a struct nor `#[must_use]` on a function is appropriate here, so the macro expands using `core::hint::must_use` instead.
>
> - We wouldn't want `#[must_use]` on the `struct Error` because that would make the following unproblematic code trigger a warning:
>
> ```rust
> fn f(arg: &str) -> Result<(), Error>
>
> #[test]
> fn t() {
> // Assert that `f` returns error if passed an empty string.
> // A value of type `Error` is unused here but that's not a problem.
> f("").unwrap_err();
> }
> ```
>
> - Using `#[must_use]` on `fn make_error` can't help because the return value *is* used, as the right-hand side of a `let` statement. The `let` statement looks useless but is in fact necessary for ensuring that temporaries within the `format_args` expansion are not kept alive past the creation of the `Error`, as keeping them alive past that point can cause autotrait issues in async code:
>
> ```rust
> async fn f() {
> // Using `let` inside the make_error expansion causes temporaries like
> // `unsync()` to drop at the semicolon of that `let` statement, which
> // is prior to the await point. They would otherwise stay around until
> // the semicolon on *this* statement, which is after the await point,
> // and the enclosing Future would not implement Send.
> log(make_error!("look: {:p}", unsync())).await;
> }
>
> async fn log(error: Error) {/* ... */}
>
> // Returns something without a Sync impl.
> fn unsync() -> *const () {
> 0 as *const ()
> }
> ```
Remove argument from closure in thread::Scope::spawn.
This implements ```@danielhenrymantilla's``` [suggestion](https://github.com/rust-lang/rust/issues/93203#issuecomment-1040798286) for improving the scoped threads interface.
Summary:
The `Scope` type gets an extra lifetime argument, which represents basically its own lifetime that will be used in `&'scope Scope<'scope, 'env>`:
```diff
- pub struct Scope<'env> { .. };
+ pub struct Scope<'scope, 'env: 'scope> { .. }
pub fn scope<'env, F, T>(f: F) -> T
where
- F: FnOnce(&Scope<'env>) -> T;
+ F: for<'scope> FnOnce(&'scope Scope<'scope, 'env>) -> T;
```
This simplifies the `spawn` function, which now no longer passes an argument to the closure you give it, and now uses the `'scope` lifetime for everything:
```diff
- pub fn spawn<'scope, F, T>(&'scope self, f: F) -> ScopedJoinHandle<'scope, T>
+ pub fn spawn<F, T>(&'scope self, f: F) -> ScopedJoinHandle<'scope, T>
where
- F: FnOnce(&Scope<'env>) -> T + Send + 'env,
+ F: FnOnce() -> T + Send + 'scope,
- T: Send + 'env;
+ T: Send + 'scope;
```
The only difference the user will notice, is that their closure now takes no arguments anymore, even when spawning threads from spawned threads:
```diff
thread::scope(|s| {
- s.spawn(|_| {
+ s.spawn(|| {
...
});
- s.spawn(|s| {
+ s.spawn(|| {
...
- s.spawn(|_| ...);
+ s.spawn(|| ...);
});
});
```
<details><summary>And, as a bonus, errors get <em>slightly</em> better because now any lifetime issues point to the outermost <code>s</code> (since there is only one <code>s</code>), rather than the innermost <code>s</code>, making it clear that the lifetime lasts for the entire <code>thread::scope</code>.
</summary>
```diff
error[E0373]: closure may outlive the current function, but it borrows `a`, which is owned by the current function
--> src/main.rs:9:21
|
- 7 | s.spawn(|s| {
- | - has type `&Scope<'1>`
+ 6 | thread::scope(|s| {
+ | - lifetime `'1` appears in the type of `s`
9 | s.spawn(|| println!("{:?}", a)); // might run after `a` is dropped
| ^^ - `a` is borrowed here
| |
| may outlive borrowed value `a`
|
note: function requires argument type to outlive `'1`
--> src/main.rs:9:13
|
9 | s.spawn(|| println!("{:?}", a)); // might run after `a` is dropped
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to force the closure to take ownership of `a` (and any other referenced variables), use the `move` keyword
|
9 | s.spawn(move || println!("{:?}", a)); // might run after `a` is dropped
| ++++
"
```
</details>
The downside is that the signature of `scope` and `Scope` gets slightly more complex, but in most cases the user wouldn't need to write those, as they just use the argument provided by `thread::scope` without having to name its type.
Another downside is that this does not work nicely in Rust 2015 and Rust 2018, since in those editions, `s` would be captured by reference and not by copy. In those editions, the user would need to use `move ||` to capture `s` by copy. (Which is what the compiler suggests in the error.)
Add Result::{ok, err, and, or, unwrap_or} as const
Already opened tracking issue #92384.
I don't think that this should actually cause any issues as long as the constness is unstable, but we may want to double-check that this doesn't get interpreted as a weird `Drop` bound even for non-const usages.
Rollup of 5 pull requests
Successful merges:
- #94362 (Add well known values to `--check-cfg` implementation)
- #94577 (only disable SIMD for doctests in Miri (not for the stdlib build itself))
- #94595 (Fix invalid `unresolved imports` errors for a single-segment import)
- #94596 (Delay bug in expr adjustment when check_expr is called multiple times)
- #94618 (Don't round stack size up for created threads in Windows)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
only disable SIMD for doctests in Miri (not for the stdlib build itself)
Also we can enable library/core/tests/simd.rs now, Miri supports enough SIMD for that.
Miri/CTFE: properly treat overflow in (signed) division/rem as UB
To my surprise, it looks like LLVM treats overflow of signed div/rem as UB. From what I can tell, MIR `Div`/`Rem` directly lowers to the corresponding LLVM operation, so to make that correct we also have to consider these overflows UB in the CTFE/Miri interpreter engine.
r? `@oli-obk`
When CStr moves to core with an alias in std, this can link to
`crate::ffi::CStr`. However, linking in the reverse direction (from core
to std) requires a relative path, and that path can't work from both
core::ffi and std::os::raw (different number of `../` traversals
required).
The ability to interoperate with C code via FFI is not limited to crates
using std; this allows using these types without std.
The existing types in `std::os::raw` become type aliases for the ones in
`core::ffi`. This uses type aliases rather than re-exports, to allow the
std types to remain stable while the core types are unstable.
This also moves the currently unstable `NonZero_` variants and
`c_size_t`/`c_ssize_t`/`c_ptrdiff_t` types to `core::ffi`, while leaving
them unstable.
core can't depend on external crates the way std can. Rather than revert
usage of cfg_if, add a copy of it to core. This does not export our
copy, even unstably; such a change could occur in a later commit.
Add Atomic*::from_mut_slice
Tracking issue #76314 for `from_mut` has a question about the possibility of `from_mut_slice`, and I found a real case for it. A user in the forum had a parallelism problem that could be solved by open-indexing updates to a vector of atomics, but they didn't want to affect the other code using that vector. Using `from_mut_slice`, they could borrow that data as atomics just long enough for their parallel loop.
ref: https://users.rust-lang.org/t/sharing-vector-with-rayon-par-iter-correctly/72022
Rollup of 5 pull requests
Successful merges:
- #93603 (Populate liveness facts when calling `get_body_with_borrowck_facts` without `-Z polonius`)
- #93870 (Fix switch on discriminant detection in a presence of coverage counters)
- #94355 (Add one more case to avoid ICE)
- #94363 (Remove needless borrows from core::fmt)
- #94377 (`check_used` should only look at actual `used` attributes)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup