Add a stack-`pin!`-ning macro to `core::pin`.
- https://github.com/rust-lang/rust/issues/93178
`pin!` allows pinning a value to the stack. Thanks to being implemented in the stdlib, which gives access to `macro` macros, and to the private `.pointer` field of the `Pin` wrapper, [it was recently discovered](https://rust-lang.zulipchat.com/#narrow/stream/187312-wg-async-foundations/topic/pin!.20.E2.80.94.20the.20.22definitive.22.20edition.20.28a.20rhs-compatible.20pin-nin.2E.2E.2E/near/268731241) ([archive link](https://zulip-archive.rust-lang.org/stream/187312-wg-async-foundations/topic/A.20rhs-compatible.20pin-ning.20macro.html#268731241)), contrary to popular belief, that it is actually possible to implement and feature such a macro:
```rust
let foo: Pin<&mut PhantomPinned> = pin!(PhantomPinned);
stuff(foo);
```
or, directly:
```rust
stuff(pin!(PhantomPinned));
```
- For context, historically, this used to require one of the two following syntaxes:
- ```rust
let foo = PhantomPinned;
pin!(foo);
stuff(foo);
```
- ```rust
pin! {
let foo = PhantomPinned;
}
stuff(foo);
```
This macro thus allows, for instance, doing things like:
```diff
fn block_on<T>(fut: impl Future<Output = T>) -> T {
// Pin the future so it can be polled.
- let mut fut = Box::pin(fut);
+ let mut fut = pin!(fut);
// Create a new context to be passed to the future.
let t = thread::current();
let waker = Arc::new(ThreadWaker(t)).into();
let mut cx = Context::from_waker(&waker);
// Run the future to completion.
loop {
match fut.as_mut().poll(&mut cx) {
Poll::Ready(res) => return res,
Poll::Pending => thread::park(),
}
}
}
```
- _c.f._, https://doc.rust-lang.org/1.58.1/alloc/task/trait.Wake.html
And so on, and so forth.
I don't think such an API can get better than that, barring full featured language support (`&pin` references or something), so I see no reason not to start experimenting with featuring this in the stdlib already 🙂
- cc `@rust-lang/wg-async-foundations` \[EDIT: this doesn't seem to have pinged anybody 😩, thanks `@yoshuawuyts` for the real ping\]
r? `@joshtriplett`
___
# Docs preview
https://user-images.githubusercontent.com/9920355/150605731-1f45c2eb-c9b0-4ce3-b17f-2784fb75786e.mp4
___
# Implementation
The implementation ends up being dead simple (so much it's embarrassing):
```rust
pub macro pin($value:expr $(,)?) {
Pin { pointer: &mut { $value } }
}
```
_and voilà_!
- The key for it working lies in [the rules governing the scope of anonymous temporaries](https://doc.rust-lang.org/1.58.1/reference/destructors.html#temporary-lifetime-extension).
<details><summary>Comments and context</summary>
This is `Pin::new_unchecked(&mut { $value })`, so, for starters, let's
review such a hypothetical macro (that any user-code could define):
```rust
macro_rules! pin {( $value:expr ) => (
match &mut { $value } { at_value => unsafe { // Do not wrap `$value` in an `unsafe` block.
$crate::pin::Pin::<&mut _>::new_unchecked(at_value)
}}
)}
```
Safety:
- `type P = &mut _`. There are thus no pathological `Deref{,Mut}` impls that would break `Pin`'s invariants.
- `{ $value }` is braced, making it a _block expression_, thus **moving** the given `$value`, and making it _become an **anonymous** temporary_.
By virtue of being anonynomous, it can no longer be accessed, thus preventing any attemps to `mem::replace` it or `mem::forget` it, _etc._
This gives us a `pin!` definition that is sound, and which works, but only in certain scenarios:
- If the `pin!(value)` expression is _directly_ fed to a function call:
`let poll = pin!(fut).poll(cx);`
- If the `pin!(value)` expression is part of a scrutinee:
```rust
match pin!(fut) { pinned_fut => {
pinned_fut.as_mut().poll(...);
pinned_fut.as_mut().poll(...);
}} // <- `fut` is dropped here.
```
Alas, it doesn't work for the more straight-forward use-case: `let` bindings.
```rust
let pinned_fut = pin!(fut); // <- temporary value is freed at the end of this statement
pinned_fut.poll(...) // error[E0716]: temporary value dropped while borrowed
// note: consider using a `let` binding to create a longer lived value
```
- Issues such as this one are the ones motivating https://github.com/rust-lang/rfcs/pull/66
This makes such a macro incredibly unergonomic in practice, and the reason most macros out there had to take the path of being a statement/binding macro (_e.g._, `pin!(future);`) instead of featuring the more intuitive ergonomics of an expression macro.
Luckily, there is a way to avoid the problem. Indeed, the problem stems from the fact that a temporary is dropped at the end of its enclosing statement when it is part of the parameters given to function call, which has precisely been the case with our `Pin::new_unchecked()`!
For instance,
```rust
let p = Pin::new_unchecked(&mut <temporary>);
```
becomes:
```rust
let p = { let mut anon = <temporary>; &mut anon };
```
However, when using a literal braced struct to construct the value, references to temporaries can then be taken. This makes Rust change the lifespan of such temporaries so that they are, instead, dropped _at the end of the enscoping block_.
For instance,
```rust
let p = Pin { pointer: &mut <temporary> };
```
becomes:
```rust
let mut anon = <temporary>;
let p = Pin { pointer: &mut anon };
```
which is *exactly* what we want.
Finally, we don't hit problems _w.r.t._ the privacy of the `pointer` field, or the unqualified `Pin` name, thanks to `decl_macro`s being _fully_ hygienic (`def_site` hygiene).
</details>
___
# TODO
- [x] Add compile-fail tests with attempts to break the `Pin` invariants thanks to the macro (_e.g._, try to access the private `.pointer` field, or see what happens if such a pin is used outside its enscoping scope (borrow error));
- [ ] Follow-up stuff:
- [ ] Try to experiment with adding `pin!` to the prelude: this may require to be handled with some extra care, as it may lead to issues reminiscent of those of `assert_matches!`: https://github.com/rust-lang/rust/issues/82913
- [x] Create the tracking issue.
bootstrap: tidy up flag handling for llvm build
This tidies up the logic in `src/bootstrap/native.rs` such that:
- `CMAKE_*_LINKER_FLAGS` is not overridden if we add to it twice.
- `CMAKE_*_FLAGS` also include the standard `*FLAGS` environment
variables, which CMake respects when we _don't_ set `CMAKE_*_FLAGS`.
- `llvm.ldflags` from `config.toml` appends to the ldflags Rust's
bootstrap logic adds, rather than replacing them.
It also takes a second stab at #89983 by moving `-static-libstdc++` to just be passed as a linker flag, since that's what it is.
Fixes#93880. Fixes#70468. Closes#89983.
Generator drop tracking: improve break and continue handling
This PR fixes two related issues.
One, sometimes break or continue have a block target instead of an expression target. This seems to mainly happen with try blocks. Since the drop tracking analysis only works on expressions, if we see a block target for break or continue, we substitute the last expression of the block as the target instead.
Two, break and continue were incorrectly being treated as the same, so continue would also show up as an exit from the loop or block. This patch corrects the way continue is handled by keeping a stack of loop entry points and uses those to find the target of the continue.
Fixes#93197
r? `@nikomatsakis`
This thus still makes it technically possible to enable the feature, and thus
to trigger UB without `unsafe`, but this is fine since incomplete features are
known to be potentially unsound (labelled "may not be safe").
This follows from the discussion at https://github.com/rust-lang/rust/pull/93176#discussion_r799413561
make `find_similar_impl_candidates` even fuzzier
continues the good work of `@BGR360` in #92223. I might have overshot a bit and we're now slightly too fuzzy 😅
with this we can now also simplify `simplify_type`, which is nice :3
Make `Res::SelfTy` a struct variant and update docs
I found pattern matching on a `(Option<DefId>, Option<(DefId, bool)>)` to not be super readable, additionally the doc comments on the types in a tuple variant aren't visible anywhere at use sites as far as I can tell (using rust analyzer + vscode)
The docs incorrectly assumed that the `DefId` in `Option<(DefId, bool)>` would only ever be for an impl item and I also found the code examples to be somewhat unclear about which `DefId` was being talked about.
r? `@lcnr` since you reviewed the last PR changing these docs
Remove Config::stderr
1. It captured stdout and not stderr
2. It isn't used anywhere
3. All error messages should go to the DiagnosticOutput instead
4. It modifies thread local state
Marking as blocked as it will conflict a bit with https://github.com/rust-lang/rust/pull/93936.
Update dist-(arm|armv7|armhf)-linux to Ubuntu 20.04
I believe this should be safe, as actual artifacts will be produced by a cross toolchain. The build ran through cleanly locally.
This came up in https://github.com/rust-lang/rust/pull/93577, where the host GCC ICEd during the LLD build. (Though I wonder why we build LLD for the host at all...)
r? `@Mark-Simulacrum`
Drop time dependency from bootstrap
This was only used for the inclusion of 'current' dates into our manpages, but
it is not clear that this is practically necessary. The manpage is essentially
never updated, and so we can likely afford to keep a manual date in these files.
It also seems possible to just omit it, but that may cause other tools trouble,
so avoid doing that for now.
This is largely done to reduce bootstrap complexity; the time crate is not particularly
small and in #92480 would have started pulling in num-threads, which does runtime
thread count detection. I would prefer to avoid that, so filing this to just drop the nearly
unused dependency entirely.
r? `@pietroalbini`
1. It captured stdout and not stderr
2. It isn't used anywhere
3. All error messages should go to the DiagnosticOutput instead
4. It modifies thread local state
Rollup of 9 pull requests
Successful merges:
- #89926 (make `Instant::{duration_since, elapsed, sub}` saturating and remove workarounds)
- #90532 (More informative error message for E0015)
- #93810 (Improve chalk integration)
- #93851 (More practical examples for `Option::and_then` & `Result::and_then`)
- #93885 (bootstrap.py: Suggest disabling download-ci-llvm option if url fails to download)
- #93886 (Stabilise inherent_ascii_escape (FCP in #77174))
- #93930 (add link to format_args! when mention it in docs)
- #93936 (Couple of driver cleanups)
- #93944 (Don't relabel to a team if there is already a team label)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Couple of driver cleanups
* Remove the `RustcDefaultCalls` struct, which hasn't been necessary since the introduction of `rustc_interface`.
* Move the `setup_callbacks` call around for a tiny code deduplication.
* Remove the `SPAN_DEBUG` global as it isn't actually necessary.
bootstrap.py: Suggest disabling download-ci-llvm option if url fails to download
I got an error when trying to build the compiler using an old commit, and it turns out it was because the option `download-ci-llvm` was implicitly set to true. So this pull request tries to add a help message for other people that may run into the same problem.
To reproduce my error:
```
git checkout 8d7707f3c4
./x.py test
[...]
spurious failure, trying again
downloading https://ci-artifacts.rust-lang.org/rustc-builds/db002a06ae9154a35d410550bc5132df883d7baa/rust-dev-nightly-x86_64-unknown-linux-gnu.tar.xz
curl: (22) The requested URL returned error: 404
failed to run: curl -# -y 30 -Y 10 --connect-timeout 30 --retry 3 -Sf -o /tmp/tmp8g13rb4n https://ci-artifacts.rust-lang.org/rustc-builds/db002a06ae9154a35d410550bc5132df883d7baa/rust-dev-nightly-x86_64-unknown-linux-gnu.tar.xz
Build completed unsuccessfully in 0:00:46
```
This is my `config.toml`:
```
# Includes one of the default files in src/bootstrap/defaults
profile = "compiler"
changelog-seen = 2
[rust]
debug = true
```
To reproduce an error with this branch:
Change line 618 of bootstrap.py to
```
url = "rustc-builds-error404/{}".format(llvm_sha)
```
Delete llvm and cached tarball, and set `llvm.download-ci-llvm=true` in config.toml.
```
./x.py test
[...]
spurious failure, trying again
downloading https://ci-artifacts.rust-lang.org/rustc-builds-error404/719b04ca99be0c78e09a8ec5e2eda082a5d8ccae/rust-dev-nightly-x86_64-unknown-linux-gnu.tar.xz
curl: (22) The requested URL returned error: 404
failed to run: curl -# -y 30 -Y 10 --connect-timeout 30 --retry 3 -Sf -o /tmp/tmpesl1ydvo https://ci-artifacts.rust-lang.org/rustc-builds-error404/719b04ca99be0c78e09a8ec5e2eda082a5d8ccae/rust-dev-nightly-x86_64-unknown-linux-gnu.tar.xz
error: failed to download llvm from ci
help: old builds get deleted after a certain time
help: if trying to compile an old commit of rustc, disable `download-ci-llvm` in config.toml:
[llvm]
download-ci-llvm = false
Build completed unsuccessfully in 0:00:01
```
Regarding the implementation, I expected to be able to use a try/catch block in `_download_ci_llvm`, but the `run` function calls `sys.exit` instead of raising an exception so that's not possible. Also, suggestions for better wording of the help message are welcome.
Improve chalk integration
- Support subtype bounds in chalk lowering
- Handle universes in canonicalization
- Handle type parameters in chalk responses
- Use `chalk_ir::LifetimeData::Empty` for `ty::ReEmpty`
- Remove `ignore-compare-mode-chalk` for tests that no longer hang (they may still fail or ICE)
This is enough to get a hello world program to compile with `-Zchalk` now. Some of the remaining issues that are needed to get Chalk integration working on larger programs are:
- rust-lang/chalk#234
- rust-lang/chalk#548
- rust-lang/chalk#734
- Generators are handled differently in chalk and rustc
r? `@jackh726`
Apply noundef attribute to &T, &mut T, Box<T>, bool
This doesn't handle `char` because it's a bit awkward to distinguish it from `u32` at this point in codegen.
Note that this _does not_ change whether or not it is UB for `&`, `&mut`, or `Box` to point to undef. It only applies to the pointer itself, not the pointed-to memory.
Fixes (partially) #74378.
r? `@nikic` cc `@RalfJung`
Inherit lifetimes for async fn instead of duplicating them.
The current desugaring of `async fn foo<'a>(&usize) -> &u8` is equivalent to
```rust
fn foo<'a, '0>(&'0 usize) -> foo<'static, 'static>::Opaque<'a, '0, '_>;
type foo<'_a, '_0>::Opaque<'a, '0, '1> = impl Future<Output = &'1 u8>;
```
following the RPIT model.
Duplicating all the inherited lifetime parameters and setting the inherited version to `'static` makes lowering more complex and causes issues like #61949. This PR removes the duplication of inherited lifetimes to directly use
```rust
fn foo<'a, '0>(&'0 usize) -> foo<'a, '0>::Opaque<'_>;
type foo<'a, '0>::Opaque<'1> = impl Future<Output = &'1 u8>;
```
following the TAIT model.
Fixes https://github.com/rust-lang/rust/issues/61949
Fix hashing for windows paths containing a CurDir component
* the logic only checked for / but not for \
* verbatim paths shouldn't skip items at all since they don't get normalized
* the extra branches get optimized out on unix since is_sep_byte is a trivial comparison and is_verbatim is always-false
* tests lacked windows coverage for these cases
That lead to equal paths not having equal hashes and to unnecessary collisions.
A fix applied to std::Path::hash triggers a miscompilation/assert in LLVM in this test on wasm32.
The miscompilation appears to pre-existing. Reverting some previous changes done std::Path also trigger it
and slight modifications such as changing the test path from "a" to "ccccccccccc" also make it pass, indicating
it's very flaky.
Since the fix is for a higher-tier platform than wasm it takes precedence.
This ensures that it is called even when run_in_thread_pool_with_globals
is avoided and reduces code duplication between the parallel and
non-parallel version of run_in_thread_pool_with_globals
tidy: Extend error code check
We discovered in https://github.com/rust-lang/rust/pull/93845 that the error code tidy check didn't check everything: if you remove an error code from the listing even if it has an explanation, then it should error.
It also allowed me to put back `E0192` in that listing as well.
r? ```@Mark-Simulacrum```
linkchecker: fix panic on directory symlinks
In Debian and Ubuntu, there are some patches that change the rustc/fonts
directory to a symlink to the system fonts. This triggers a latent bug
in linkchecker, as the DirEntry filetype isn't a dir but later on the
file itself, when opened, is one, triggering an unreachable!() clause.
This patch fixes the situation by using std::fs::metadata, which goes
through symlinks.
I'd have added a test case but `tidy` doesn't seem to like symlinks, and
moreover I'm not sure how Git deals with symlinks on Windows.
Signed-off-by: Simon Chopin <simon.chopin@canonical.com>
Add some known GAT bugs as tests
In the spirit of rust-lang/compiler-team#476
These tests are marked as "check-fail", but also commented with "this should pass". This many of the open GAT issues that are accepted bugs.
r? ``@nikomatsakis``
fix ICE when parsing lifetime as function argument
I don't really like this, but we basically need to emit an error instead of just delaying an bug, because there are too many places in the AST that aren't covered by my previous PRs...
cc: https://github.com/rust-lang/rust/issues/93282#issuecomment-1028052945