Make `ty::Error` implement all auto traits
I have no idea what's up with the crashes test I fixed--I really don't want to look into it since it has to do something with borrowck and multiple layers of opaques. I think the underlying idea of allowing error types to implement all auto traits is justified though.
Fixes#134796Fixes#131050
r? lcnr
(Re-)Implement `impl_trait_in_bindings`
This reimplements the `impl_trait_in_bindings` feature for local bindings.
"`impl Trait` in bindings" serve as a form of *trait* ascription, where the type basically functions as an infer var but additionally registering the `impl Trait`'s trait bounds for the infer type. These trait bounds can be used to enforce that predicates hold, and can guide inference (e.g. for closure signature inference):
```rust
let _: impl Fn(&u8) -> &u8 = |x| x;
```
They are implemented as an additional set of bounds that are registered when the type is lowered during typeck, and then these bounds are tied to a given `CanonicalUserTypeAscription` for borrowck. We enforce these `CanonicalUserTypeAscription` bounds during borrowck to make sure that the `impl Trait` types are sensitive to lifetimes:
```rust
trait Static: 'static {}
impl<T> Static for T where T: 'static {}
let local = 1;
let x: impl Static = &local;
//~^ ERROR `local` does not live long enough
```
r? oli-obk
cc #63065
---
Why can't we just use TAIT inference or something? Well, TAITs in bodies have the problem that they cannot reference lifetimes local to a body. For example:
```rust
type TAIT = impl Display;
let local = 0;
let x: TAIT = &local;
//~^ ERROR `local` does not live long enough
```
That's because TAITs requires us to do *opaque type inference* which is pretty strict, since we need to remap all of the lifetimes of the hidden type to universal regions. This is simply not possible here.
---
I consider this part of the "impl trait everywhere" experiment. I'm not certain if this needs yet another lang team experiment.
Tweak multispan rendering to reduce output length
Consider comments and bare delimiters the same as an "empty line" for purposes of hiding rendered code output of long multispans. This results in more aggressive shortening of rendered output without losing too much context, specially in `*.stderr` tests that have "hidden" comments. We do that check not only on the first 4 lines of the multispan, but now also on the previous to last line as well.
Consider comments and bare delimiters the same as an "empty line" for purposes of hiding rendered code output of long multispans. This results in more aggressive shortening of rendered output without losing too much context, specially in `*.stderr` tests that have "hidden" comments.
Add unpolished, experimental support for AFIDT (async fn in dyn trait)
This allows us to begin messing around `async fn` in `dyn Trait`. Calling an async fn from a trait object always returns a `dyn* Future<Output = ...>`.
To make it work, Implementations are currently required to return something that can be coerced to a `dyn* Future` (see the example in `tests/ui/async-await/dyn/works.rs`). If it's not the right size, then it'll raise an error at the coercion site (see the example in `tests/ui/async-await/dyn/wrong-size.rs`). Currently the only practical way of doing this is wrapping the body in `Box::pin(async move { .. })`.
This PR does not implement a helper type like a "`Boxing`"[^boxing] adapter, and I'll probably follow-up with another PR to improve the error message for the `PointerLike` trait (something that explains in just normal prose what is happening here, rather than a trait error).
[^boxing]: https://rust-lang.github.io/async-fundamentals-initiative/explainer/user_guide_future.html#the-boxing-adapter
This PR also does not implement new trait solver support for AFIDT; I'll need to think how best to integrate it into candidate assembly, and that's a bit of a matter of taste, but I don't think it will be difficult to do.
This could also be generalized:
* To work on functions that are `-> impl Future` (soon).
* To work on functions that are `-> impl Iterator` and other "dyn rpitit safe" traits. We still need to nail down exactly what is needed for this to be okay (not soon).
Tracking:
* https://github.com/rust-lang/rust/issues/133119
Rudimentary heuristic to insert parentheses when needed for RPIT overcaptures lint
We don't have basically any preexisting machinery to detect when parentheses are needed for *types*. AFAICT, all of the diagnostics we have for opaques just... fail when they suggest `+ 'a` when that's ambiguous.
Fixes#132853
Gate async fn trait bound modifier on `async_trait_bounds`
This PR moves `async Fn()` trait bounds into a new feature gate: `feature(async_trait_bounds)`. The general vibe is that we will most likely stabilize the `feature(async_closure)` *without* the `async Fn()` trait bound modifier, so we need to gate that separately.
We're trying to work on the general vision of `async` trait bound modifier general in: https://github.com/rust-lang/rfcs/pull/3710, however that RFC still needs more time for consensus to converge, and we've decided that the value that users get from calling the bound `async Fn()` is *not really* worth blocking landing async closures in general.
I was surprised to find that running with `-Zparse-only` only parses the
crate root file. Other files aren't parsed because that happens later
during expansion.
This commit renames the option and updates the help message to make this
clearer.
Compiletest: add proc-macro header
This adds a `proc-macro` header to simplify using proc-macros, and to reduce boilerplate. This header works similar to the `aux-build` header where you pass a path for a proc-macro to be built.
This allows the `force-host`, `no-prefer-dynamic` headers, and `crate_type` attribute to be removed. Additionally it uses `--extern` like `aux_crate` (allows implicit `extern crate` in 2018) and `--extern proc_macro` (to place in the prelude in 2018).
~~This also includes a secondary change which defaults the edition of proc-macros to 2024. This further reduces boilerplate (removing `extern crate proc_macro;`), and allows using modern Rust syntax. I was a little on the fence including this. I personally prefer it, but I can imagine it might be confusing to others.~~ EDIT: Removed
Some tests were changed so that when there is a chain of dependencies A→B→C, that the `@ proc-macro` is placed in `B` instead of `A` so that the `--extern` flag works correctly (previously it depended on `-L` to find `C`). I think this is better to make the dependencies more explicit. None of these tests looked like the were actually testing this behavior.
There is one test that had an unexplained output change: `tests/ui/macros/same-sequence-span.rs`. I do not know why it changed, but it didn't look like it was particularly important. Perhaps there was a normalization issue?
This is currently not compatible with the rustdoc `build-aux-docs` header. It can probably be fixed, I'm just not feeling motivated to do that right now.
### Implementation steps
- [x] Document this new behavior in rustc-dev-guide once we figure out the specifics. https://github.com/rust-lang/rustc-dev-guide/pull/2149
Rollup of 12 pull requests
Successful merges:
- #129409 (Expand std::os::unix::fs::chown() doc with a warning)
- #133320 (Add release notes for Rust 1.83.0)
- #133368 (Delay a bug when encountering an impl with unconstrained generics in `codegen_select`)
- #133428 (Actually use placeholder regions for trait method late bound regions in `collect_return_position_impl_trait_in_trait_tys`)
- #133512 (Add `as_array` and `as_mut_array` conversion methods to slices.)
- #133519 (Check `xform_ret_ty` for WF in the new solver to improve method winnowing)
- #133520 (Structurally resolve before applying projection in borrowck)
- #133534 (extend group-forbid-always-trumps-cli test)
- #133537 ([rustdoc] Fix new clippy lints)
- #133543 ([AIX] create shim for lgammaf_r)
- #133547 (rustc_span: Replace a `HashMap<_, ()>` with `HashSet`)
- #133550 (print generated doc paths)
r? `@ghost`
`@rustbot` modify labels: rollup
Actually use placeholder regions for trait method late bound regions in `collect_return_position_impl_trait_in_trait_tys`
So in https://github.com/rust-lang/rust/pull/113182, I introduced a "diagnostics improvement" in the form of 473c88dfb6, which changes which signature we end up instantiating with placeholder regions and which signature we end up instantiating with fresh region vars so that we have placeholders corresponding to the names of the late-bound regions coming from the *impl*.
However, this is not sound, since now we're essentially no longer proving that *all* instantiations of the trait method are compatible with an instantiation of the impl method, but vice versa (which is weaker). Let's look at the example `tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.rs`:
```rust
trait MkStatic {
fn mk_static(self) -> &'static str;
}
impl MkStatic for &'static str {
fn mk_static(self) -> &'static str { self }
}
trait Foo {
fn foo<'a: 'static, 'late>(&'late self) -> impl MkStatic;
}
impl Foo for str {
fn foo<'a: 'static>(&'a self) -> impl MkStatic + 'static {
self
}
}
fn call_foo<T: Foo + ?Sized>(t: &T) -> &'static str {
t.foo().mk_static()
}
fn main() {
let s = call_foo(String::from("hello, world").as_str());
println!("> {s}");
}
```
To collect RPITITs, we were previously instantiating the trait signature with infer vars (`fn(&'?0 str) -> ?1t` where `?1t` is the variable we use to infer the RPITIT) and the impl signature with placeholders (there are no late-bound regions in that signature, so we just have `fn(&'a str) -> Opaque`).
Equating the signatures works, since all we do is unify `?1t` with `Opaque` and `'?0` with `'a`. However, conceptually it *shouldn't* hold, since this definition is not valid for *all* instantiations of the trait method but just the one where `'0` (i.e. `'late`) is equal to `'a` :(
## So what
This PR effectively reverts 473c88dfb6 to fix the unsoundness.
Fixes#133427
Also fixes#133425, which is actually coincidentally another instance of this bug (but not one that is weaponized into UB, just one that causes an ICE in refinement checking).
do not constrain infer vars in `find_best_leaf_obligation`
This ended up causing an ICE by making the following code path reachable by incorrectly constraining an inference variable while computing the best obligation for a preceding ambiguity. Closes#129444.
f2abf827c1/compiler/rustc_trait_selection/src/solve/fulfill.rs (L312-L314)
I have to be honest, I don't fully understand how that change removes all the additional diagnostics :3
r? `@compiler-errors`
Rollup of 8 pull requests
Successful merges:
- #132090 (Stop being so bail-y in candidate assembly)
- #132658 (Detect const in pattern with typo)
- #132911 (Pretty print async fn sugar in opaques and trait bounds)
- #133102 (aarch64 softfloat target: always pass floats in int registers)
- #133159 (Don't allow `-Zunstable-options` to take a value )
- #133208 (generate-copyright: Now generates a library file too.)
- #133215 (Fix missing submodule in `./x vendor`)
- #133264 (implement OsString::truncate)
r? `@ghost`
`@rustbot` modify labels: rollup
Implement `~const Destruct` effect goal in the new solver
This also fixed a subtle bug/limitation of the `NeedsConstDrop` check. Specifically, the "`Qualif`" API basically treats const drops as totally structural, even though dropping something that has an explicit `Drop` implementation cannot be structurally decomposed. For example:
```rust
#![feature(const_trait_impl)]
#[const_trait] trait Foo {
fn foo();
}
struct Conditional<T: Foo>(T);
impl Foo for () {
fn foo() {
println!("uh oh");
}
}
impl<T> const Drop for Conditional<T> where T: ~const Foo {
fn drop(&mut self) {
T::foo();
}
}
const FOO: () = {
let _ = Conditional(());
//~^ This should error.
};
fn main() {}
```
In this example, when checking if the `Conditional(())` rvalue is const-drop, since `Conditional` has a const destructor, we would previously recurse into the `()` value and determine it has nothing to drop, which means that it is considered to *not* need a const drop -- even though dropping `Conditional(())` would mean evaluating the destructor which relies on that `T: const Foo` bound to hold!
This could be fixed alternatively by banning any const conditions on `const Drop` impls, but that really sucks -- that means that basically no *interesting* const drop impls could be written. We have the capability to totally and intuitively support the right behavior, which I've implemented here.