Encode synthetic by-move coroutine body with a different `DefPathData`
See the included test. In the first revision rpass1, we have an async closure `{closure#0}` which has a coroutine as a child `{closure#0}::{closure#0}`. We synthesize a by-move coroutine body, which is `{closure#0}::{closure#1}` which depends on the mir_built query, which depends on the typeck query.
In the second revision rpass2, we've replaced the coroutine-closure by a closure with two children closure. Notably, the def path of the second child closure is the same as the synthetic def id from the last revision: `{closure#0}::{closure#1}`. When type-checking this closure, we end up trying to compute its def_span, which tries to fetch it from the incremental cache; this will try to force the dependencies from the last run, which ends up forcing the mir_built query, which ends up forcing the typeck query, which ends up with a query cycle.
The problem here is that we really should never have used the same `DefPathData` for the synthetic by-move coroutine body, since it's not a closure. Changing the `DefPathData` will mean that we can see that the def ids are distinct, which means we won't try to look up the closure's def span from the incremental cache, which will properly skip replaying the node's dependencies and avoid a query cycle.
Fixes#139142
Emit `unused_attributes` for `#[inline]` on exported functions
I saw someone post a code sample that contained these two attributes, which immediately made me suspicious.
My suspicions were confirmed when I did a small test and checked the compiler source code to confirm that in these cases, `#[inline]` is indeed ignored (because you can't exactly `LocalCopy`an unmangled symbol since that would lead to duplicate symbols, and doing a mix of an unmangled `GloballyShared` and mangled `LocalCopy` instantiation is too complicated for our current instatiation mode logic, which I don't want to change right now).
So instead, emit the usual unused attribute lint with a message saying that the attribute is ignored in this position.
I think this is not 100% true, since I expect LLVM `inlinehint` to still be applied to such a function, but that's not why people use this attribute, they use it for the `LocalCopy` instantiation mode, where it doesn't work.
r? saethlin as the instantiation guy
Procedurally, I think this should be fine to merge without any lang involvement, as this only does a very minor extension to an existing lint.
Fix closure recovery for missing block when return type is specified
Firstly, fix the `is_array_like_block` condition to make sure we're actually recovering a mistyped *block* rather than some other delimited expression. This fixes#138748.
Secondly, split out the recovery of missing braces on a closure body into a separate recovery. Right now, the suggestion `"you might have meant to write this as part of a block"` originates from `suggest_fixes_misparsed_for_loop_head`, which feels kinda brittle and coincidental since AFAICT that recovery wasn't ever really intended to fix this.
We also can make this `MachineApplicable` in this case.
Fixes#138748
r? `@fmease` or reassign if you're busy/don't wanna review this
Prefer built-in sized impls (and only sized impls) for rigid types always
This PR changes the confirmation of `Sized` obligations to unconditionally prefer the built-in impl, even if it has nested obligations. This also changes all other built-in impls (namely, `Copy`/`Clone`/`DiscriminantKind`/`Pointee`) to *not* prefer built-in impls over param-env impls. This aligns the old solver with the behavior of the new solver.
---
In the old solver, we register many builtin candidates with the `BuiltinCandidate { has_nested: bool }` candidate kind. The precedence this candidate takes over other candidates is based on the `has_nested` field. We only prefer builtin impls over param-env candidates if `has_nested` is `false`
2b4694a698/compiler/rustc_trait_selection/src/traits/select/mod.rs (L1804-L1866)
Preferring param-env candidates when the builtin candidate has nested obligations *still* ends up leading to detrimental inference guidance, like:
```rust
fn hello<T>() where (T,): Sized {
let x: (_,) = Default::default();
// ^^ The `Sized` obligation on the variable infers `_ = T`.
let x: (i32,) = x;
// We error here, both a type mismatch and also b/c `T: Default` doesn't hold.
}
```
Therefore this PR adjusts the candidate precedence of `Sized` obligations by making them a distinct candidate kind and unconditionally preferring them over all other candidate kinds.
Special-casing `Sized` this way is necessary as there are a lot of traits with a `Sized` super-trait bound, so a `&'a str: From<T>` where-bound results in an elaborated `&'a str: Sized` bound. People tend to not add explicit where-clauses which overlap with builtin impls, so this tends to not be an issue for other traits.
We don't know of any tests/crates which need preference for other builtin traits. As this causes builtin impls to diverge from user-written impls we would like to minimize the affected traits. Otherwise e.g. moving impls for tuples to std by using variadic generics would be a breaking change. For other builtin impls it's also easier for the preference of builtin impls over where-bounds to result in issues.
---
There are two ways preferring builtin impls over where-bounds can be incorrect and undesirable:
- applying the builtin impl results in undesirable region constraints. E.g. if only `MyType<'static>` implements `Copy` then a goal like `(MyType<'a>,): Copy` would require `'a == 'static` so we must not prefer it over a `(MyType<'a>,): Copy` where-bound
- this is mostly not an issue for `Sized` as all `Sized` impls are builtin and don't add any region constraints not already required for the type to be well-formed
- however, even with `Sized` this is still an issue if a nested goal also gets proven via a where-bound: [playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=30377da5b8a88f654884ab4ebc72f52b)
- if the builtin impl has associated types, we should not prefer it over where-bounds when normalizing that associated type. This can result in normalization adding more region constraints than just proving trait bounds. https://github.com/rust-lang/rust/issues/133044
- not an issue for `Sized` as it doesn't have associated types.
r? lcnr
hygiene: Rewrite `apply_mark_internal` to be more understandable
The previous implementation allocated new `SyntaxContext`s in the inverted order, and it was generally very hard to understand why its result matches what the `opaque` and `opaque_and_semitransparent` field docs promise.
```rust
/// This context, but with all transparent and semi-transparent expansions filtered away.
opaque: SyntaxContext,
/// This context, but with all transparent expansions filtered away.
opaque_and_semitransparent: SyntaxContext,
```
It also couldn't be easily reused for the case where the context id is pre-reserved like in #129827.
The new implementation tries to follow the docs in a more straightforward way.
I did the transformation in small steps, so it indeed matches the old implementation, not just the docs.
So I suggest reading only the new version.
Improve hir_pretty for struct expressions.
While working on https://github.com/rust-lang/rust/pull/139131 I noticed the hir pretty printer outputs an empty line between each field, and is also missing a space before the `{` and the `}`:
```rust
let a =
StructWithSomeFields{
field_1: 1,
field_2: 2,
field_3: 3,
field_4: 4,
field_5: 5,
field_6: 6,};
let a = StructWithSomeFields{ field_1: 1, field_2: 2, ..a};
```
This changes it to:
```rust
let a =
StructWithSomeFields {
field_1: 1,
field_2: 2,
field_3: 3,
field_4: 4,
field_5: 5,
field_6: 6 };
let a = StructWithSomeFields { field_1: 1, field_2: 2, ..a };
```
Remove attribute `#[rustc_error]`
It was an ancient way to write `check-pass` tests, but now it's no longer necessary (except for the `delayed_bug_from_inside_query` flavor, which is retained).
[AIX] Ignore linting on repr(C) structs with repr(packed) or repr(align(n))
This PR updates the lint added in 9b40bd7 to ignore repr(C) structs that also have repr(packed) or repr(align(n)).
As these representations can be modifiers on repr(C), it is assumed that users that add these should know what they are doing, and thus the the lint should not warn on the respective structs. For example, for the time being, using repr(packed) and manually padding a repr(C) struct can be done to correctly align struct members on AIX.
Set `target_vendor = "openwrt"` on `mips64-openwrt-linux-musl`
OpenWRT is a Linux distribution for embedded network devices. The target name contains `openwrt`, so we should set `cfg(target_vendor = "openwrt")`.
This is similar to what other Linux distributions do (the only one in-tree is `x86_64-unikraft-linux-musl`, but that sets `target_vendor = "unikraft"`).
Motivation: To make correctly [parsing target names](https://github.com/rust-lang/cc-rs/pull/1413) simpler.
Fixes https://github.com/rust-lang/rust/issues/131165.
CC target maintainer `@Itus-Shield`
compiletest: Support matching diagnostics on lines below
Using `//~vvv ERROR`.
This is not needed often, but it's easy to support, and it allows to eliminate a class of `error-pattern`s that cannot be eliminated in any other way.
See the diff for the examples of such patterns coming from parser.
Some of them can be matched by `//~ ERROR` or `//~^ ERROR` as well (when the final newline is allowed), but it changes the shape of reported spans, so I chose to keep the spans by using `//~v ERROR`.
Do not treat lifetimes from parent items as influencing child items
```rust
struct A;
impl Bar<'static> for A {
const STATIC: &str = "";
// ^ no future incompat warning
}
```
has no future incompat warning, because there is no ambiguity. But
```rust
struct C;
impl Bar<'_> for C {
// ^^ this lifeimte
const STATIC: &'static str = {
struct B;
impl Bar<'static> for B {
const STATIC: &str = "";
// causes ^ to emit a future incompat warning
}
""
};
}
```
had one before this PR, because the impl for `B` (which is just a copy of `A`) thought it was influenced by a lifetime on the impl for `C`.
I double checked all other `lifetime_ribs` iterations and all of them do check for `Item` boundaries. This feels very fragile tho, and ~~I think we should do not even be able to see ribs from parent items, but that's a different refactoring that I'd rather not do at the same time as a bugfix~~. EDIT: ah nevermind, this is needed for improving diagnostics like "use of undeclared lifetime" being "can't use generic parameters from outer item" instead.
r? `@compiler-errors`
Greatly simplify doctest parsing and information extraction
The original process was pretty terrible, as it tried to extract information such as attributes by performing matches over tokens like `#!`, which doesn't work very well considering you can have `# ! [`, which is valid.
Also, it now does it in one pass: if the parser is happy, then we try to extract information, otherwise we return early.
r? `@fmease`
Avoid wrapping constant allocations in packed structs when not necessary
This way LLVM will set the string merging flag if the alloc is a nul terminated string, reducing binary sizes.
try-job: armhf-gnu
Rollup of 6 pull requests
Successful merges:
- #138720 (Specify a concrete stack size in channel tests)
- #139010 (Improve `xcrun` error handling)
- #139021 (std: get rid of pre-Vista fallback code)
- #139025 (Do not trim paths in MIR validator)
- #139026 (Use `abs_diff` where applicable)
- #139030 (saethlin goes on vacation)
r? `@ghost`
`@rustbot` modify labels: rollup
Remove `kw::Empty` uses from `hir::Lifetime::ident`
`hir::Lifetime::ident` is sometimes set to `kw::Empty` and it's really confusing. This PR stops that. Helps with #137978.
r? `@lcnr`
Do not trim paths in MIR validator
From my inline comment:
```
// The type checker formats a bunch of strings with type names in it, but these strings
// are not always going to be encountered on the error path since the inliner also uses
// the validator, and there are certain kinds of inlining (even for valid code) that
// can cause validation errors (mostly around where clauses and rigid projections).
```
Fixes https://github.com/rust-lang/rust/issues/138979
r? `@jieyouxu`
Specify a concrete stack size in channel tests
The channel-stack-overflow-issue-102246 regression test fails on platforms with a small default stack size (e.g. Fuchsia, with a default of 256KiB). Update the test to specify an exact stack size for both the sender and receiver operations, to ensure it is platform agnostic.
Set the stack size to less than the total allocation size of the mpsc channel, to continue to prove that the allocation is on the heap.
`hir::Lifetime::ident` currently sometimes uses `kw::Empty` for elided
lifetimes and sometimes uses `kw::UnderscoreLifetime`, and the
distinction is used when creating some error suggestions, e.g. in
`Lifetime::suggestion` and `ImplicitLifetimeFinder::visit_ty`. I found
this *really* confusing, and it took me a while to understand what was
going on.
This commit replaces all uses of `kw::Empty` in `hir::Lifetime::ident`
with `kw::UnderscoreLifetime`. It adds a new field
`hir::Lifetime::is_path_anon` that mostly replaces the old
empty/underscore distinction and makes things much clearer.
Some other notable changes:
- Adds a big comment to `Lifetime` talking about permissable field
values.
- Adds some assertions in `new_named_lifetime` about what ident values
are permissible for the different `LifetimeRes` values.
- Adds a `Lifetime::new` constructor that does some checking to make
sure the `is_elided` and `is_anonymous` states are valid.
- `add_static_impl_trait_suggestion` now looks at `Lifetime::res`
instead of the ident when creating the suggestion. This is the one
case where `is_path_anon` doesn't replace the old empty/underscore
distinction.
- A couple of minor pretty-printing improvements.
HIR printing currently gets very little testing. This increases coverage
a bit, with a focus on lifetimes.
There are some FIXME comments for cases that are printed in a dubious
fashion. This PR won't address those; the point of adding this test is
to ensure that the subsequent commits don't hurt pretty-printing.
Improve suggest construct with literal syntax instead of calling
Closing #138931
When constructing a structure through a format similar to calling a constructor, we can use verbose suggestions to hint at using literal syntax for clearer advice. The case of multiple fields is also considered here, provided that the field has the same number of arguments as CallExpr.
r? compiler
expand: Leave traces when expanding `cfg` attributes
This is the same as https://github.com/rust-lang/rust/pull/138515, but for `cfg(true)` instead of `cfg_attr`.
The difference is that `cfg(true)`s already left "traces" after themselves - the `cfg` attributes themselves, with `expanded_inert_attrs` set to true, with full tokens, available to proc macros.
This is not a reasonably expected behavior, but it could not be removed without a replacement, because a [major rustdoc feature](https://github.com/rust-lang/rfcs/pull/3631) and a number of clippy lints rely on it. This PR implements a replacement.
This needs a crater run, because it changes observable behavior (in an intended way) - proc macros can no longer see expanded `cfg(true)` attributes.
(Some minor unnecessary special casing for `sym::cfg_attr` is also removed in this PR.)
r? `@nnethercote`