[diagnostics] Add mentions to `Copy` types being valid for `union` fields
This came up from some user on Discord which was using a `T : PrimitiveInt` generic type, and they wanted to use in a `union`. Rather than adding a `Copy` bound, they started pondering about the `ManuallyDrop<T>` road, and how to correctly use `unsafe` to perform the drops.
<img width="648" alt="Screen Shot 2022-02-15 at 22 28 34" src="https://user-images.githubusercontent.com/9920355/154152496-8f9be74b-ad59-4724-8f9e-48b446774e06.png">
- [Discord link](https://discord.com/channels/442252698964721669/443150878111694848/943092778534072320)
So, it seemed like the error message for types with potential drop glue on `union` fields could be improved to also mention the `Copy` alternative, since in many cases where `union`s are concerned, people are dealing with PODs / `Copy` types anyways 🙂
___
``@rustbot`` modify labels: +A-diagnostics +D-terse
Correctly mark the span of captured arguments in `format_args!()`
It should not include the braces, or misspelling suggestions will be wrong.
Fixes#94010.
Suggest deriving required supertraits
closes https://github.com/rust-lang/rust/issues/91550
I chose to just hardcode handling for PartialOrd and PartialEq because that should be robust enough and I dont know how to go about doing it generically
r? rust-lang/diagnostics
Destabilize cfg(target_has_atomic_load_store = ...)
This was not intended to be stabilized yet.
This keeps the cfg_target_has_atomic feature gate name since compiler-builtins otherwise depends on it and I'd rather not try to manage a bump across a crates.io published repository given the time-sensitivity here (we need to land this quickly to avoid a beta backport).
Closes https://github.com/rust-lang/rust/issues/32976
r? `@Amanieu`
Fix inconsistent symbol mangling with -Zverbose
Always skip arguments that are the defaults of their respective
parameters, to avoid generating inconsistent symbols for builds
with `-Zverbose` flag and without it.
Support pretty printing of invalid constants
Make it possible to pretty print invalid constants by introducing a
fallible variant of `destructure_const` and falling back to debug
formatting when it fails.
Closes#93688.
Resolve concern of `derive_default_enum`
This resolves the concern in favor of prohibiting multiple instances of
the attribute. This is similar to non-helper attributes as introduced in
#88681.
``@rustbot`` label +S-waiting-on-review +T-libs-api
Treat static refs as `mir::ConstantKind::Val`
With the upcoming introduction of Valtrees we want to treat more values as `mir::ConstantKind::Val` directly.
r? `@lcnr`
cc `@oli-obk`
Always skip arguments that are the defaults of their respective
parameters, to avoid generating inconsistent symbols for builds
with `-Zverbose` flag and without it.
Make it possible to pretty print invalid constants by introducing a
fallible variant of `destructure_const` and falling back to debug
formatting when it fails.
Add support for control-flow protection
This change adds a flag for configuring control-flow protection in the LLVM backend. In Clang, this flag is exposed as `-fcf-protection` with options `none|branch|return|full`. This convention is followed for `rustc`, though as a codegen option: `rustc -Z cf-protection=<none|branch|return|full>`. Tracking issue for future work is #93754.
Rework GAT `where` clause check
rework the GAT where check to use a fixed-point algorithm, and check all GATs in a trait at once
fixes#93278
r? `@jackh726`
cc `@nikomatsakis`
llvm: migrate to new parameter-bearing uwtable attr
In https://reviews.llvm.org/D114543 the uwtable attribute gained a flag
so that we can ask for sync uwtables instead of async, as the former are
much cheaper. The default is async, so that's what I've done here, but I
left a TODO that we might be able to do better.
While in here I went ahead and dropped support for removing uwtable
attributes in rustc: we never did it, so I didn't write the extra C++
bridge code to make it work. Maybe I should have done the same thing
with the `sync|async` parameter but we'll see.
suggest using raw strings when invalid escapes appear in literals
i'd guess about 70% of "bad escape" cases occur when someone meant to use a raw string literal because they're passing it directly to `Regex::new()`.
this emits an advisory (`Applicability::MaybeIncorrect`) `help:` suggestion to the user that they use an `r""` string, on top of the normal notes about looking at the string literal documentation/spec.
Overhaul interning.
A number of types are interned and `eq` and `hash` are implemented on
the pointer rather than the contents. But this is not well enforced
within the type system like you might expect.
This PR introduces a new type `Interned` which encapsulates this concept
more rigorously, and uses it to convert a couple of the less common
interned types.
r? `@fee1-dead`
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.
Specifically, rename the `Const` struct as `ConstS` and re-introduce `Const` as
this:
```
pub struct Const<'tcx>(&'tcx Interned<ConstS>);
```
This now matches `Ty` and `Predicate` more closely, including using
pointer-based `eq` and `hash`.
Notable changes:
- `mk_const` now takes a `ConstS`.
- `Const` was copy, despite being 48 bytes. Now `ConstS` is not, so need a
we need separate arena for it, because we can't use the `Dropless` one any
more.
- Many `&'tcx Const<'tcx>`/`&Const<'tcx>` to `Const<'tcx>` changes
- Many `ct.ty` to `ct.ty()` and `ct.val` to `ct.val()` changes.
- Lots of tedious sigil fiddling.
The variant names are exported, so we can use them directly (possibly
with a `ty::` qualifier). Lots of places already do this, this commit
just increases consistency.
Specifically, change `Region` from this:
```
pub type Region<'tcx> = &'tcx RegionKind;
```
to this:
```
pub struct Region<'tcx>(&'tcx Interned<RegionKind>);
```
This now matches `Ty` and `Predicate` more closely.
Things to note
- Regions have always been interned, but we haven't been using pointer-based
`Eq` and `Hash`. This is now happening.
- I chose to impl `Deref` for `Region` because it makes pattern matching a lot
nicer, and `Region` can be viewed as just a smart wrapper for `RegionKind`.
- Various methods are moved from `RegionKind` to `Region`.
- There is a lot of tedious sigil changes.
- A couple of types like `HighlightBuilder`, `RegionHighlightMode` now have a
`'tcx` lifetime because they hold a `Ty<'tcx>`, so they can call `mk_region`.
- A couple of test outputs change slightly, I'm not sure why, but the new
outputs are a little better.
Specifically, change `Ty` from this:
```
pub struct Predicate<'tcx> { inner: &'tcx PredicateInner<'tcx> }
```
to this:
```
pub struct Predicate<'tcx>(&'tcx Interned<PredicateS<'tcx>>)
```
where `PredicateInner` is renamed as `PredicateS`.
This (plus a few other minor changes) makes the parallels with `Ty` and
`TyS` much clearer, and makes the uniqueness more explicit.
Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
means we can move a lot of methods away from `TyS`, leaving `TyS` as a
barely-used type, which is appropriate given that it's not meant to
be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
than via `TyS`, which wasn't obvious at all.
Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs
Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
`Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
(pointer-based, for the `Equal` case) and partly on `TyS`
(contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
or `&`. They seem to be unavoidable.