Don't print "private fields" on empty tuple structs
Closes#118180.
While working on this I also noticed that empty struct variants are also rendered rather awkwardly. I'll make another issue for that, since I don't know what the correct rendering would be.
Rework supertrait lint once again
I accidentally pushed the wrong commits because I totally didn't check I was on the right computer when updating #118026.
Sorry, this should address all the nits in #118026.
r? lcnr
improve tool-only help for multiple `#[default]` variants
When defining an enum with multiple `#[default]` variants, we emit a tool-only suggestion for every `#[default]`ed variant to remove all other `#[default]`s. This PR improves the suggestion to correctly handle the cases where one variant has multiple `#[default]`s and where different `#[default]`s have the same span due to macro expansions.
fixes https://github.com/rust-lang/rust/issues/118119
Rollup of 6 pull requests
Successful merges:
- #118012 (Add support for global allocation in smir)
- #118013 (Enable Rust to use the EHCont security feature of Windows)
- #118100 (Enable profiler in dist-powerpc64-linux)
- #118142 (Tighten up link attributes for llvm-wrapper bindings)
- #118147 (Fix some unnecessary casts)
- #118161 (Allow defining opaques in `check_coroutine_obligations`)
r? `@ghost`
`@rustbot` modify labels: rollup
Allow defining opaques in `check_coroutine_obligations`
In the new trait solver, when an obligation stalls on an unresolved coroutine witness, we will stash away the *root* obligation, even if the stalled obligation is only a distant descendent of the root obligation, since the new solver is purely recursive.
This means that we may need to reprocess alias-relate obligations (and others) which may define opaque types in the new solver. Currently, we use the coroutine's def id as the defining anchor in `check_coroutine_obligations`, which will allow defining no opaque types, resulting in errors like:
```
error[E0271]: type mismatch resolving `{coroutine@<source>:6:5: 6:17} <: impl Clone`
--> <source>:6:5
|
6 | / move |_: ()| {
7 | | let () = yield ();
8 | | }
| |_____^ types differ
```
So this PR fixes the defining anchor and does the same trick as `check_opaque_well_formed`, where we manually compare opaques that were defined against their hidden types to make sure they weren't defined differently when processing these stalled coroutine obligations.
r? `@lcnr` cc `@cjgillot`
Enable Rust to use the EHCont security feature of Windows
In the future Windows will enable Control-flow Enforcement Technology (CET aka Shadow Stacks). To protect the path where the context is updated during exception handling, the binary is required to enumerate valid unwind entrypoints in a dedicated section which is validated when the context is being set during exception handling.
The required support for EHCONT Guard has already been merged into LLVM, long ago. This change simply adds the Rust codegen option to enable it.
Relevant LLVM change: https://reviews.llvm.org/D40223
This also adds a new `ehcont-guard` option to the bootstrap config which enables EHCont Guard when building std.
We at Microsoft have been using this feature for a significant period of time; we are confident that the LLVM feature, when enabled, generates well-formed code.
We currently enable EHCONT using a codegen feature, but I'm certainly open to refactoring this to be a target feature instead, or to use any appropriate mechanism to enable it.
Add support for global allocation in smir
Add APIs to StableMir to support global allocation. Before this change, StableMir users had no API available to retrieve Allocation provenance information. They had to resource to internal APIs instead.
One example is retrieving the Allocation of an `&str`. See test for an example on how the API can be used.
Add allow-by-default lint for unit bindings
### Example
```rust
#![warn(unit_bindings)]
macro_rules! owo {
() => {
let whats_this = ();
}
}
fn main() {
// No warning if user explicitly wrote `()` on either side.
let expr = ();
let () = expr;
let _ = ();
let _ = expr; //~ WARN binding has unit type
let pat = expr; //~ WARN binding has unit type
let _pat = expr; //~ WARN binding has unit type
// No warning for let bindings with unit type in macro expansions.
owo!();
// No warning if user explicitly annotates the unit type on the binding.
let pat: () = expr;
}
```
outputs
```
warning: binding has unit type `()`
--> $DIR/unit-bindings.rs:17:5
|
LL | let _ = expr;
| ^^^^-^^^^^^^^
| |
| this pattern is inferred to be the unit type `()`
|
note: the lint level is defined here
--> $DIR/unit-bindings.rs:3:9
|
LL | #![warn(unit_bindings)]
| ^^^^^^^^^^^^^
warning: binding has unit type `()`
--> $DIR/unit-bindings.rs:18:5
|
LL | let pat = expr;
| ^^^^---^^^^^^^^
| |
| this pattern is inferred to be the unit type `()`
warning: binding has unit type `()`
--> $DIR/unit-bindings.rs:19:5
|
LL | let _pat = expr;
| ^^^^----^^^^^^^^
| |
| this pattern is inferred to be the unit type `()`
warning: 3 warnings emitted
```
This lint is not triggered if any of the following conditions are met:
- The user explicitly annotates the binding with the `()` type.
- The binding is from a macro expansion.
- The user explicitly wrote `let () = init;`
- The user explicitly wrote `let pat = ();`. This is allowed for local lifetimes.
### Known Issue
It is known that this lint can trigger on some proc-macro generated code whose span returns false for `Span::from_expansion` because e.g. the proc-macro simply forwards user code spans, and otherwise don't have distinguishing syntax context compared to non-macro-generated code. For those kind of proc-macros, I believe the correct way to fix them is to instead emit identifers with span like `Span::mixed_site().located_at(user_span)`.
Closes#71432.
Remove `feature` from the list of well known check-cfg name
This PR removes `feature` from the list of well known check-cfg.
This is done for multiple reasons:
- Cargo is the source of truth, rustc shouldn't have any knowledge of it
- It creates a conflict between Cargo and rustc when there are no features defined.
In this case Cargo won't pass any `--check-cfg` for `feature` since no feature will ever be passed, but rustc by having in it's list adds a implicit `cfg(feature, values(any()))` which is completely wrong. Having any cfg `feature` is unexpected not allow any `feature` value.
While doing this, I took the opportunity to specialise the diagnostic a bit for the case above.
r? `@petrochenkov`
Don't ICE when ambiguity is found when selecting `Index` implementation in typeck
Fixes#118111
The problem here is when we're manually "selecting" an impl for `base_ty: Index<?0>`, we don't consider placeholder region errors (leak check) or ambiguous predicates. Those can lead to us not actually emitting any fulfillment errors on line 3131.
In the future Windows will enable Control-flow Enforcement Technology
(CET aka Shadow Stacks). To protect the path where the context is
updated during exception handling, the binary is required to enumerate
valid unwind entrypoints in a dedicated section which is validated when
the context is being set during exception handling.
The required support for EHCONT has already been merged into LLVM,
long ago. This change adds the Rust codegen option to enable it.
Reference:
* https://reviews.llvm.org/D40223
This also adds a new `ehcont-guard` option to the bootstrap config which
enables EHCont Guard when building std.
The search sorting code already sorts by item type discriminant,
putting things with smaller discriminants first. There was
also a special case for sorting keywords and primitives earlier,
and this commit removes it by giving them lower discriminants.
The sorting code has another criteria where items with descriptions
appear earlier than items without, and that criteria has higher
priority than the item type. This shouldn't matter, though,
because primitives and keywords normally only appear in the
standard library, and it always gives them descriptions.
Fix early param lifetimes in generic_const_exprs
In cases like below, we never actually be able to capture region name for two reasons, first `'static` becomes anonymous lifetime and second we never capture region if it doesn't have a name so this results in ICE.
```
struct DataWrapper<'static> {
data: &'a [u8; Self::SIZE],
}
impl DataWrapper<'a> {
```
Fixes https://github.com/rust-lang/rust/issues/118021
Remove `--check-cfg` checking of command line `--cfg` args
Back in https://github.com/rust-lang/rust/pull/100574 we added to the `unexpected_cfgs` lint the checking of `--cfg` CLI arguments and emitted unexpected names and values for them.
The implementation works as expected, but it's usability in particular when using it in combination with Cargo+`RUSTFLAGS` as people who set `RUSTFLAGS=--cfg=tokio_unstable` (or whatever) have `unexpected_cfgs` warnings on all of their crates is debatable. ~~To fix this issue this PR proposes that we split the CLI argument checking into it's own separate allow-by-default lint: `unexpected_cli_cfgs`.~~
~~This has the advantage of letting people who want CLI warnings have them (although not by default anymore), while still linting on every unexpected cfg name and values in the code.~~
After some discussion with the Cargo team ([Zulip thread](https://rust-lang.zulipchat.com/#narrow/stream/246057-t-cargo/topic/check-cfg.20and.20RUSTFLAGS.20interaction)) and member of the compiler team (see below), I propose that we follow the suggestion from `@epage:` never check `--cfg` arguments, but still reserve us the possibility to do it later.
We would still lint on unexpected cfgs found in the source code no matter the `--cfg` args passed. This mean reverting https://github.com/rust-lang/rust/pull/100574 but NOT https://github.com/rust-lang/rust/pull/99519.
r? `@petrochenkov`
rustdoc-search: add support for traits and associated types
# Summary
Trait associated type queries work in rustdoc's type driven search. The data is included in the search-index.js file, and the queries are designed to "do what I mean" when users type them in, so, for example, `Iterator<Item=T> -> Option<T>` includes `Iterator::next` in the SERP[^SERP], and `Iterator<T> -> Option<T>` also includes `Iterator::next` in the SERP.
[^SERP]: search engine results page
## Sample searches
* [`iterator<Item=T>, fnmut -> T`][iterreduce]
* [`iterator<T>, fnmut -> T`][iterreduceterse]
[iterreduce]: http://notriddle.com/rustdoc-html-demo-5/associated-types/std/index.html?search=iterator%3CItem%3DT%3E%2C%20fnmut%20-%3E%20T&filter-crate=std
[iterreduceterse]: http://notriddle.com/rustdoc-html-demo-5/associated-types/std/index.html?search=iterator%3CT%3E%2C%20fnmut%20-%3E%20T&filter-crate=std
# Motivation
My primary motivation for working on search.js at all is to make it easier to use highly generic APIs, like the Iterator API. The type signature describes these functions pretty well, while the names are almost arbitrary.
Before this PR, type bindings were not consistently included in search-index.js at all (you couldn't find Iterator::next by typing in its function signature) and you couldn't explicitly search for them. This PR fixes both of these problems.
# Guide-level explanation
*Excerpt from [the Rustdoc book](http://notriddle.com/rustdoc-html-demo-5/associated-types/rustdoc/read-documentation/search.html), included in this PR.*
> Function signature searches can query generics, wrapped in angle brackets, and traits will be normalized like types in the search engine if no type parameters match them. For example, a function with the signature `fn my_function<I: Iterator<Item=u32>>(input: I) -> usize` can be matched with the following queries:
>
> * `Iterator<Item=u32> -> usize`
> * `Iterator<u32> -> usize` (you can leave out the `Item=` part)
> * `Iterator -> usize` (you can leave out iterator's generic entirely)
> * `T -> usize` (you can match with a generic parameter)
>
> Each of the above queries is progressively looser, except the last one would not match `dyn Iterator`, since that's not a type parameter.
# Reference-level explanation
Inside the angle brackets, you can choose whether to write a name before the parameter and the equal sign. This syntax is called [`GenericArgsBinding`](https://doc.rust-lang.org/reference/paths.html#paths-in-expressions) in the Rust Reference, and it allows you to constrain a trait's associated type.
As a convenience, you don't actually have to put the name in (Rust requires it, but Rustdoc Search doesn't). This works about the same way unboxing already works in Search: the terse `Iterator<u32>` is a match for `Iterator<Item=u32>`, but the opposite is not true, just like `u32` is a match for `Iterator<u32>`.
When converting a trait method for the search index, the trait is substituted for `Self`, and all associated types are bound to generics. This way, if you have the following trait definition:
```rust
pub trait MyTrait {
type Output;
fn method(self) -> Self::Output;
}
```
The following queries will match its method:
* `MyTrait<Output=T> -> T`
* `MyTrait<T> -> T`
* `MyTrait -> T`
But these queries will not match it:
* <i>`MyTrait<Output=u32> -> u32`</i>
* <i>`MyTrait<Output> -> Output`</i>
* <i>`MyTrait -> MyTrait::Output`</i>
# Drawbacks
It's a little bit bigger:
```console
$ du before/search-index1.74.0.js after/search-index1.74.0.js
4020 before/search-index1.74.0.js
4068 after/search-index1.74.0.js
```
# Rationale and alternatives
I don't want to just not do this. On it's own, it's not terribly useful, but in addition to searching by normal traits, this is also intended as a desugaring target for closures. That's why it needs to actually distinguish the two: it allows the future desugaring to distinguish function output and input.
The other alternative would be to not allow users to leave out the name, so `iterator<u32>` doesn't work. That would be unfortunate, because mixing up which ones have out params and which ones are plain generics is an easy enough mistake that the Rust compiler itself helps people out with it.
# Prior art
* <http://neilmitchell.blogspot.com/2020/06/hoogle-searching-overview.html>
The current Rustdoc algorithm, both before this PR and after it, has a fairly expensive matching algorithm over a fairly simple file format. Luckily, we aren't trying to scale to all of crates.io, so it's usable, but it's not great when I throw it at docs.servo.org
# Unresolved questions
Okay, but *how do we want to handle closures?* I know the system will desugar `FnOnce(T) -> U` into `trait:FnOnce<Output=U, primitive:tuple<T>>`, but what if I don't know what trait I'm looking for? This PR can merge with nothing, but it'd be nice to have a plan.
Specifically, how should the special form used to handle all varieties of basic callable: primitive:fn (function pointers), and trait:Fn, trait:FnOnce, and trait:FnMut should all be searchable using a single syntax, because I'm always forgetting which one is used in the function I'm looking for.
The essential question is how closely we want to copy Rust's own syntax. The tersest way to expression Option::map might be:
Option<T>, (T -> U) -> Option<U>
That's the approach I would prefer, but nobody's going to attempt it without being told, so maybe this would be better?
Option<T>, (fn(T) -> U) -> Option<U>
It does require double parens, but at least it's mostly unambiguous. Unfortunately, it looks like the syntax you'd use for function pointers, implying that if you specifically wanted to limit your search to function pointers, you'd need to use `primitive:fn(T) -> U`. Then again, searching is normally case-insensitive, so you'd want that anyway to disambiguate from `trait:Fn(T) -> U`.
# Future possibilities
## This thing really needs a ranking algorithm
That is, this PR increases the number of matches for some type-based queries. They're usually pretty good matches, but there's still more of them, and it's evident that if you have two functions, `foo(MyTrait<u8>)` and `bar(MyTrait<Item=u8>)`, if the user typed `MyTrait<u8>` then `foo` should show up first.
A design choice that these PRs have followed is that adding more stuff to the search query always reduces the number of functions that get matched. The advantage of doing it that way is that you can rank them by just counting how many atoms are in the function's signature (lowest score goes on top). Since it's impossible for a matching function to have fewer atoms than the search query, if there's a function with exactly the same set of atoms in it, then that'll be on top.
More complicated ranking algos tend to penalize long documents anyway, if the [distance metrics](https://www.benfrederickson.com/distance-metrics/?utm_source=flipboard&utm_content=other) I found through [Flipboard](https://flipboard.com/`@arnie0426/building-recommender-systems-nvue3iqtgrn10t45)` (and postgresql's `ts_rank_cd`) are anything to go by. Real-world data sets tend to have weird outliers, like they have God Functions with zillions of arguments of all sorts of types, and Rustdoc ought to put such a function at the bottom.
The other natural choice would be interleaving with `unifyFunctionTypes` to count the number of unboxings and reorderings. This would compute a distance function, and would do a fine job of ranking the results, as [described here](https://ndmitchell.com/downloads/slides-hoogle_finding_functions_from_types-16_may_2011.pdf) by the Hoogle dev, but is more complicated than it sounds. The current algorithm returns when it finds a result that *exists at all*, but a distance function should find an *optimal solution* to find the smallest sequence of edits.
## This could also use a benchmark suite and some optimization
This approach also lends itself to layering a bloom filter in front of the backtracking unification engine.
* At load time, hash the typeNameIdMap ID for each atom and set the matching entry in a fixed-size byte array for each function to 1. Call it `fnType.bloomFilter`
* At search time, do the same for the atoms in the query (excluding special forms like `[]` that can match more than one thing). Call it `parsedQuery.bloomFilter`
* For each function, `if (fnType.bloomFilter | (~parsedQuery.bloomFilter) !== ~0) { return false; }`
There's also room to optimize the unification engine itself, by using stacks and persistent data structures instead of copying arrays around, or by using hashing instead of linear scans (the current algorithm was rewritten from one that tried to do that, but was too much to fit in my head and had a bunch of bugs). The advantage of Just Backtracking Better over the bloom filter is that it doesn't require the engine to retain any special algebraic properties.
But, first, we need a set of benchmarks to be able to judge if such a thing will actually help.
## Referring to associated types by path
*I don't want to implement this one, but if I did, this is how I'd do it.*
In Rust, this is represented by a structure called a qualified path, or QPath. They look like this:
<Self as Iterator>::Item
<F as FnOnce>::Output
They can also, if it's unambiguous, use a plain path and just let the system figure it out:
Self::Item
F::Output
In Rustdoc Type-Driven Search, we don't want to force people to be unambiguous. Instead, we should try *all reasonable interpretations*, return results whenever any of them match, and let users make their query more specific if too many results are matches.
To enable associated type path searches in Rustdoc, we need to:
1. When lowering a trait method to a search-index.js function signature, Self should be explicitly represented as a generic argument. It should always be assigned `-1`, so that if the user uses `Self` in their search query, we can ensure it always matches the real Self and not something else. Any functions that don't *have* a Self should drop a `0` into the first position of the where clause, to express that there isn't one and reserve the `-1` position.
* Reminder: generics are negative, concrete types are positive, and zero is a reserved sentinel.
* Right now, `Iterator::next` is lowered as if it were `fn next<T>(self: Iterator<Item=T>) -> Option<T>`.
It should become `fn next<Self, T>(self: Self) -> Option<T> where Self: Iterator<Item=T>` instead.
3. Add another backtracking edge to the unification engine, so that when the user writes something like `some::thing`, the interpretation where `some` is a module and `thing` is a standalone item becomes one possible match candidate, while the interpretation where `some` is a trait and `thing` is an associated type is a separate match candidate. The backtracking engine is basically powerful enough to do this already, since unboxing generic type parameters into their traits already requires the ability to do this kind of thing.
* When interpreting `some::thing` where `some` is a trait and `thing` is an associated type, it should be treated equivalently to `<self as some>::thing`. If you want to bind it to some generic parameter other than `Self`, you need to explicitly say so.
* If no trait called `some` actually exists, treat it as a generic type parameter instead. Track every trait mentioned in the current working function signature, and add a match candidate for each one.
* A user that explicitly wants the trait-associated-type interpretation could write a qpath (like `<self as trait>::type`), and a user that explicitly wants the module-item interpretation should use an item type filter (like `struct:module::type`).
4. To actually do the matching, maintain a `Map<(QueryGenericParamId, TraitId), FnGenericParamId>` alongside the existing `Map<QueryGenericParamId, FnGenericParamId>` that is already used to handle plain generic parameters. This works, because, when a trait function signature is lowered to search-index.js, the `rustdoc` backend always generates an FnGenericParamId for every trait associated type it sees mentioned in the function's signature.
5. Parse QPaths. Specifically,
* QueryElem adds three new fields. `isQPath` is a boolean flag, and `traitNameId` contains an entry for `typeNameIdMap` corresponding to the trait part of a qpath, and `parentId` may contain either a concrete type ID or a negative number referring to a generic type parameter. The actual `id` of the query elem will always be a negative number, because this is essentially a funny way to add a generic type constraint.
* If it's a QPath, then both of those IDs get filled in with the respective parts of the map. The unification engine will check the where clause to ensure the trait actually applies to the generic parameter in question, will check the type parameter constraint, and will add a mapping to `mgens` recording this as a solution.
* If it's just a regular path, then `isQPath` is false, and the parser will fill in both `traitNameId` and `parentId` based on the same path. The unification engine, seeing isQPath is false and that these IDs were filled in, will try all three solutions: the path might be part of a concrete type name, or it might be referring to a trait, or it might be referring to a generic type parameter.
### Why not implement QPath searches?
I'm not sure if anybody really wants to write such complicated queries. You can do a pretty good job of describing the generic functions in the standard library without resorting to FQPs.
These two queries, for example, would both match the Iterator::map function if we added support for higher order function queries and a rule that allows a type to match its *notable traits*.
// I like this version, because it's identical to how `Option::map` would be written.
// There's a reason why Iterator::map and Option::map have the same name.
Iterator<T>, (T -> U) -> Iterator<U>
// This version explicitly uses the type parameter constraints.
Iterator<Item=T>, (T -> U) -> Iterator<Item=U>
If I try to write this one using FQP, however, the results seem worse:
// This one is less expressive than the versions that don't use associated type paths.
// It matches `Iterator::filter`, while the above two example queries don't.
Iterator, (Iterator::Item -> Iterator::Item) -> Iterator
// This doesn't work, because the return type of `Iterator::map` is not a generic
// parameter with an `Iterator` trait bound. It's a concrete type that
// implements `Iterator`. Return-Position-Impl-Trait is the same way.
//
// There's a difference between something like `map`, whose return value
// implements Iterator, and something like `collect`, where the caller
// gets to decide what the concrete type is going to be.
//Self, (Self::Item -> I::Item) -> I where Self: Iterator, I: Iterator
// This works, but it seems subjectively ugly, complex, and counterintuitive to me.
Self, (<Self as Iterator>::Item -> T) -> Iterator<Item=T>
Add `$message_type` field to distinguish json diagnostic outputs
Currently the json-formatted outputs have no way to unambiguously determine which kind of message is being output. A consumer can look for specific fields in the json object (eg "message"), but there's no guarantee that in future some other kind of output will have a field of the same name.
This PR adds a `"type"` field to add json outputs which can be used to unambiguously determine which kind of output it is. The mapping is:
`diagnostic`: regular compiler diagnostics
`artifact`: artifact notifications
`future_incompat`: Future incompatibility report
`unused_extern`: Unused crate warnings/errors
This matches the "internally tagged" representation for serde enums.
Add place.ty() and Ty build from a kind to smir
Add a method to retrieve the type of a place and a few utility functions needed to build the projection type. I decided to return a result to avoid panicking if the user passes invalid inputs, such as wrong list of locals.
r? `@spastorino`
Don't consider regions in `deref_into_dyn_supertrait` lint
I actually wonder if we should just warn on *any* deref impl with a target type that matches a supertrait by *def-id*.
cc #89460
r? types
Typeck break expr even if break is illegal
Fixes#117821
We were returning immediately when encountering an illegal break. However, this caused problems later when the expr that the break was returning was evaluated during writeback. So now we don't return and instead simply set tainted by error. This lets typeck of break expr to occur even though we've encountered an illegal break.
Don't require intercrate mode for negative coherence
Negative coherence needs to be *sound*, but does not need to be *complete*, since it's looking for the *existence* of a negative goal, not the non-existence of a positive goal.
This removes some trivial and annoying ambiguities when a negative impl has region constraints.
r? lcnr idk if this needs an fcp but if it does, pls kick it off
Note about object lifetime defaults in does not live long enough error
This is a aspect of Rust that frequently trips up people who are not aware of it yet. This diagnostic attempts to explain what's happening and why the lifetime constraint, that was never mentioned in the source, arose.
The implementation feels a bit questionable, I'm not sure whether there are better ways to do this. There probably are.
fixes#117835
r? types
Add a test to ensure issue #89699 does not show up again. This test
emits an `async move` closure in a proc macro, which is used in a
test program compiled with edition 2015. We make sure the error message
is nice and shows up properly.
Rollup of 8 pull requests
Successful merges:
- #117828 (Avoid iterating over hashmaps in astconv)
- #117832 (interpret: simplify handling of shifts by no longer trying to handle signed and unsigned shift amounts in the same branch)
- #117891 (Recover `dyn` and `impl` after `for<...>`)
- #117957 (if available use a Child's pidfd for kill/wait)
- #117988 (Handle attempts to have multiple `cfg`d tail expressions)
- #117994 (Ignore but do not assume region obligations from unifying headers in negative coherence)
- #118000 (Make regionck care about placeholders in outlives components)
- #118068 (subtree update cg_gcc 2023/11/17)
r? `@ghost`
`@rustbot` modify labels: rollup
We were earlier returning immediately when encountering an illegal break. However, this caused problems later
when the expr that the break was returning was evaluated during writeback. So now we don't return and instead
simply set tainted by error. This lets typeck of break expr to occur even though we've encountered an illegal break.
Fix insertion of statements to be executed along return edge in inlining
Inlining creates additional statements to be executed along the return
edge: an assignment to the destination, storage end for temporaries.
Previously those statements where inserted directly into a call target,
but this is incorrect when the target has other predecessors.
Avoid the issue by creating a new dedicated block for those statements.
When the block happens to be redundant it will be removed by CFG
simplification that follows inlining.
Fixes#117355
Inlining creates additional statements to be executed along the return
edge: an assignment to the destination, storage end for temporaries.
Previously those statements where inserted directly into a call target,
but this is incorrect when the target has other predecessors.
Avoid the issue by creating a new dedicated block for those statements.
When the block happens to be redundant it will be removed by CFG
simplification that follows inlining.
Fixes#117355
This lint is not triggered if any of the following conditions are met:
- The user explicitly annotates the binding with the `()` type.
- The binding is from a macro expansion.
- The user explicitly wrote `let () = init;`
- The user explicitly wrote `let pat = ();`. This is allowed for local
lifetimes.
Make regionck care about placeholders in outlives components
Currently, we don't consider a placeholder type `!T` to be a type component when it comes to processing type-outlives obligations. This means that they are essentially treated like unit values with no sub-components, and always outlive any region. This is problematic for `non_lifetime_binders`, and even more problematic for `with_negative_coherence`, since negative coherence uses placeholders as universals.
This PR adds `Component::Placeholder` which acts much like `Component::Param`. This currently causes a regression in some non-lifetime-binders tests because `for<T> T: 'static` doesn't imply itself when processing outlives obligations, so code like this will fail:
```
fn foo() where for<T> T: 'static {
foo() //~ fails
}
```
Since the where clause doesn't imply itself. This requires making the `MatchAgainstHigherRankedOutlives` relation smarter when it comes to binders.
r? types
Ignore but do not assume region obligations from unifying headers in negative coherence
Partly addresses a FIXME that was added in #112875. Just as we can throw away the nested trait/projection obligations from unifying two impl headers, we can also just throw away the region obligations too.
I removed part of the FIXME that was incorrect, namely:
> Given that the only region constraints we get are involving inference regions in the root, it shouldn't matter, but still sus.
This is not true when unifying `fn(A)` and `for<'b> fn(&'b B)` which ends up with placeholder region outlives from non-root universes. I'm pretty sure this is okay, though it would be nice if we were to use them as assumptions. See the `explicit` revision of the test I committed, which still fails.
Fixes#117986
r? lcnr, feel free to reassign tho.
Recover `dyn` and `impl` after `for<...>`
Recover `dyn` and `impl` after `for<...>` in types. Reuses the logic for parsing bare trait objects, so it doesn't fix cases like `for<'a> dyn Trait + dyn Trait` or anything, but that seems somewhat of a different issue.
Parsing recovery logic is a bit involved, but I couldn't find a way to simplify it.
Fixes#117882
interpret: simplify handling of shifts by no longer trying to handle signed and unsigned shift amounts in the same branch
While we're at it, also update comments in codegen and MIR building related to shifts, and fix the overflow error printed by Miri on negative shift amounts.
When encountering struct fn call literal with private fields, suggest all builders
When encountering code like `Box(42)`, suggest `Box::new(42)` and *all* other associated functions that return `-> Box<T>`.
Add a way to give pre-sorted suggestions.
Ensure sanity of all computed ABIs
This moves the ABI sanity assertions from the codegen backend to the ABI computation logic. Sadly, due to past mistakes, we [have to](https://github.com/rust-lang/rust/pull/117351#issuecomment-1788495503) be able to compute a sane ABI for nonsensical function types like `extern "C" fn(str) -> str`. So to make the sanity check pass we first need to make all ABI adjustment deal with unsized types... and we have no shared infrastructure for those adjustments, so that's a bunch of copy-paste. At least we have assertions failing loudly when one accidentally sets a different mode for an unsized argument.
To achieve this, this re-lands the parts of https://github.com/rust-lang/rust/pull/80594 that got reverted in https://github.com/rust-lang/rust/pull/81388. To avoid breaking wasm ABI again, that ABI now explicitly opts-in to the (wrong, broken) ABI that we currently keep for backwards compatibility. That's still better than having *every* ABI use the wrong broken default!
Cc `@bjorn3`
Fixes https://github.com/rust-lang/rust/issues/115845
rustdoc-search: optimize unifyFunctionTypes
Final profile output:
https://notriddle.com/rustdoc-html-demo-5/profile-4/index.html
This PR contains three commits that improve performance of this hot inner loop: reduces the number of allocations, a fast path for the 1-element basic query case, and reconstructing the multi-element query case to use recursion instead of an explicit `backtracking` array. It also adds new test cases that I found while working on this.
r? `@GuillaumeGomez`
Lint pinned `#[must_use]` pointers (in particular, `Box<T>` where `T` is `#[must_use]`) in `unused_must_use`.
Fixes: #111458
This is motivated by a common async/await pattern:
```rs
fn foo() -> Pin<Box<dyn Future<Output = i32>>> {
Box::pin(async { 42 })
}
// call `foo`, but forget to await the result
foo();
```
Unlike with `async fn` or return position `impl Future`, this does not currently warn the user that the `Future` is unused.
To fix this, I've extended the `unused_must_use` lint to catch `Pin<P>`, where `P` must be used. In particular, this applies to `Pin<Box<T>>`, where `T` must be used. I'm not sure if there are other pointers where this applies, but I can't think of any situation the user wouldn't want to be warned.
Suggest field typo through derefs
Take into account implicit dereferences when suggesting fields.
```
error[E0609]: no field `longname` on type `Arc<S>`
--> $DIR/suggest-field-through-deref.rs:10:15
|
LL | let _ = x.longname;
| ^^^^^^^^ help: a field with a similar name exists: `long_name`
```
CC https://github.com/rust-lang/rust/issues/78374#issuecomment-719564114
Remove option_payload_ptr; redundant to offset_of
The `option_payload_ptr` intrinsic is no longer required as `offset_of` supports traversing enums (#114208). This PR removes it in order to dogfood offset_of (as suggested at https://github.com/rust-lang/rust/issues/106655#issuecomment-1790907626). However, it will not build until those changes reach beta (which I think is within the next 8 days?) so I've opened it as a draft.
When a local binding shadows a fn, point at fn def in call failure
When a local binding shadows a function that is then called, this local binding will cause an E0618 error. We now point not only at the binding definition, but also at the locally defined function of the same name.
```
error[E0618]: expected function, found `&str`
--> $DIR/issue-22468.rs:3:13
|
LL | let foo = "bar";
| --- `foo` has type `&str`
LL | let x = foo("baz");
| ^^^-------
| |
| call expression requires function
...
LL | fn foo(file: &str) -> bool {
| -------------------------- this function of the same name is available here, but it shadowed by the local binding of the same name
```
Fix#53841
Reenable effects in libcore
With #116670, #117531, and #117171, I think we would be comfortable with re-enabling the effects feature for more testing in libcore.
r? `@oli-obk`
cc `@fmease`
cc #110395
Add some additional warnings for duplicated diagnostic items
This commit adds warnings if a user supplies several diagnostic options where we can only apply one of them. We explicitly warn about ignored options here. In addition a small test for these warnings is added.
r? `@compiler-errors`
For now that's the last PR to improve the warnings generated by misused `#[diagnostic::on_unimplemented]` attributes. I'm not sure what needs to be done next to move this closer to stabilization.
When a local binding shadows a function that is then called, this local
binding will cause an E0618 error. We now point not only at the binding
definition, but also at the locally defined function of the same name.
```
error[E0618]: expected function, found `&str`
--> $DIR/issue-22468.rs:3:13
|
LL | let foo = "bar";
| --- `foo` has type `&str`
LL | let x = foo("baz");
| ^^^-------
| |
| call expression requires function
...
LL | fn foo(file: &str) -> bool {
| -------------------------- this function of the same name is avalable here, but it shadowed by the local binding of the same name
```
Fix#53841
When using existing fn as module, don't claim it doesn't exist
Tweak wording of module not found in resolve, when the name exists but belongs to a non-`mod` item.
Fix#81232.
Remove asmjs
Fulfills [MCP 668](https://github.com/rust-lang/compiler-team/issues/668).
`asmjs-unknown-emscripten` does not work as-specified, and lacks essential upstream support for generating asm.js, so it should not exist at all.
More detail when expecting expression but encountering bad macro argument
On nested macro invocations where the same macro fragment changes fragment type from one to the next, point at the chain of invocations and at the macro fragment definition place, explaining that the change has occurred.
Fix#71039.
```
error: expected expression, found pattern `1 + 1`
--> $DIR/trace_faulty_macros.rs:49:37
|
LL | (let $p:pat = $e:expr) => {test!(($p,$e))};
| ------- -- this is interpreted as expression, but it is expected to be pattern
| |
| this macro fragment matcher is expression
...
LL | (($p:pat, $e:pat)) => {let $p = $e;};
| ------ ^^ expected expression
| |
| this macro fragment matcher is pattern
...
LL | test!(let x = 1+1);
| ------------------
| | |
| | this is expected to be expression
| in this macro invocation
|
= note: when forwarding a matched fragment to another macro-by-example, matchers in the second macro will see an opaque AST of the fragment type, not the underlying tokens
= note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
```
ignore implied bounds with placeholders
given the following code:
```rust
trait Trait {
type Ty<'a> where Self: 'a;
}
impl<T> Trait for T {
type Ty<'a> = () where Self: 'a;
}
struct Foo<T: Trait>(T)
where
for<'x> T::Ty<'x>: Sized;
```
when computing the implied bounds from `Foo<X>` we incorrectly get the bound `X: !x` from the normalization of ` for<'x> <X as Trait>::Ty::<'x>: Sized`. This is a a known bug! we shouldn't use the constraints that arise from normalization as implied bounds. See #109628.
Ignore these bounds for now. This should prevent later ICEs.
Fixes#112250Fixes#107409
new solver normalization improvements
cool beans
At the core of this PR is a `try_normalize_ty` which stops for rigid aliases by using `commit_if_ok`.
Reworks alias-relate to fully normalize both the lhs and rhs and then equate the resulting rigid (or inference) types. This fixes https://github.com/rust-lang/trait-system-refactor-initiative/issues/68 by avoiding the exponential blowup. Also supersedes #116369 by only defining opaque types if the hidden type is rigid.
I removed the stability check in `EvalCtxt::evaluate_goal` due to https://github.com/rust-lang/trait-system-refactor-initiative/issues/75. While I personally have opinions on how to fix it, that still requires further t-types/`@nikomatsakis` buy-in, so I removed that for now. Once we've decided on our approach there, we can revert this commit.
r? `@compiler-errors`
On resolve error of `[rest..]`, suggest `[rest @ ..]`
When writing a pattern to collect multiple entries of a slice in a single binding, it is easy to misremember or typo the appropriate syntax to do so, instead writing the experimental `X..` pattern syntax. When we encounter a resolve error because `X` isn't available, we suggest `X @ ..` as an alternative.
```
error[E0425]: cannot find value `rest` in this scope
--> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:3:13
|
LL | [1, rest..] => println!("{rest:?}"),
| ^^^^ not found in this scope
|
help: if you meant to collect the rest of the slice in `rest`, use the at operator
|
LL | [1, rest @ ..] => println!("{rest:?}"),
| +
```
Fix#88404.
Misc changes to StableMIR required to Kani use case.
First, I wanted to say that I can split this review into multiple if it makes reviewing easier. I bundled them up, since I've been testing them together (See https://github.com/rust-lang/project-stable-mir/pull/51 for the set of more thorough checks).
So far, this review includes 3 commits:
1. Add more APIs and fix `Instance::body`
- Add more APIs to retrieve information about types.
- Add a few more instance resolution options. For the drop shim, we return None if the drop body is empty. Not sure it will be enough.
- Make `Instance::body()` return an Option<Body>, since not every instance might have an available body. For example, foreign instances, virtual instances, dependencies.
2. Fix a bug on MIRVisitor
- We were not iterating over all local variables due to a typo.
3. Add more SMIR internal impl and callback return value
- In cases like Kani, we will invoke the rustc_internal run command directly for now. It would be handly to be able to have a callback that can return a value.
- We also need extra methods to convert stable constructs into internal ones, so we can break down the transition into finer grain commits.
- For the internal implementation of Region, we're always returning `ReErased` for now.
document ABI compatibility
I don't think we have any central place where we document our ABI compatibility rules, so let's create one. The `fn()` pointer type seems like a good place since ABI questions can only become relevant when invoking a function through a function pointer.
This will likely need T-lang FCP.
This commit adds warnings if a user supplies several diagnostic options
where we can only apply one of them. We explicitly warn about ignored
options here. In addition a small test for these warnings is added.
When writing a pattern to collect multiple entries of a slice in a
single binding, it is easy to misremember or typo the appropriate syntax
to do so, instead writing the experimental `X..` pattern syntax. When we
encounter a resolve error because `X` isn't available, we suggest
`X @ ..` as an alternative.
```
error[E0425]: cannot find value `rest` in this scope
--> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:3:13
|
LL | [1, rest..] => println!("{rest:?}"),
| ^^^^ not found in this scope
|
help: if you meant to collect the rest of the slice in `rest`, use the at operator
|
LL | [1, rest @ ..] => println!("{rest:?}"),
| +
```
Fix#88404.
Better handle type errors involving `Self` literals
When encountering a type error involving a `Self` literal, point at the self type of the enclosing `impl` and suggest using the actual type name instead.
```
error[E0308]: mismatched types
--> $DIR/struct-path-self-type-mismatch.rs:13:9
|
LL | impl<T> Foo<T> {
| - ------ this is the type of the `Self` literal
| |
| found type parameter
LL | fn new<U>(u: U) -> Foo<U> {
| - ------ expected `Foo<U>` because of return type
| |
| expected type parameter
LL | / Self {
LL | |
LL | | inner: u
LL | |
LL | | }
| |_________^ expected `Foo<U>`, found `Foo<T>`
|
= note: expected struct `Foo<U>`
found struct `Foo<T>`
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
help: use the type name directly
|
LL | Foo::<U> {
| ~~~~~~~~
```
Fix#76086.
Add more APIs to retrieve information about types, and add more instance
resolution options.
Make `Instance::body()` return an Option<Body>, since not every instance
might have an available body. For example, foreign instances, virtual
instances, dependencies.
Take into account implicit dereferences when suggesting fields.
```
error[E0609]: no field `longname` on type `Arc<S>`
--> $DIR/suggest-field-through-deref.rs:10:15
|
LL | let _ = x.longname;
| ^^^^^^^^ help: a field with a similar name exists: `long_name`
```
CC https://github.com/rust-lang/rust/issues/78374#issuecomment-719564114
When encountering a type error caused by the use of `Self`, suggest
using the actual type name instead.
```
error[E0308]: mismatched types
--> $DIR/struct-path-self-type-mismatch.rs:13:9
|
LL | impl<T> Foo<T> {
| - ------ this is the type of the `Self` literal
| |
| found type parameter
LL | fn new<U>(u: U) -> Foo<U> {
| - ------ expected `Foo<U>` because of return type
| |
| expected type parameter
LL | / Self {
LL | |
LL | | inner: u
LL | |
LL | | }
| |_________^ expected `Foo<U>`, found `Foo<T>`
|
= note: expected struct `Foo<U>`
found struct `Foo<T>`
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
help: use the type name directly
|
LL | Foo::<U> {
| ~~~~~~~~
```
Fix#76086.
Fix depth check in ProofTreeVisitor.
The hack to cutoff overflows and cycles in the new trait solver was incorrect. We want to inspect everything with depth [0..10].
This fix exposed a previously unseen bug, which caused the compiler to ICE when invoking `trait_ref` on a non-assoc type projection. I simply added the guard in the `AmbiguityCausesVisitor`, and updated the expected output for the `auto-trait-coherence` test which now includes the extra note:
```text
|
= note: upstream crates may add a new impl of trait `std::marker::Send` for type `OpaqueType` in future versions
```
r? `@lcnr`
Add -Z llvm_module_flag
Allow adding values to the `!llvm.module.flags` metadata for a generated module. The syntax is
`-Z llvm_module_flag=<name>:<type>:<value>:<behavior>`
Currently only u32 values are supported but the type is required to be specified for forward compatibility. The `behavior` element must match one of the named LLVM metadata behaviors.viors.
This flag is expected to be perma-unstable.
finish `RegionKind` renaming
second step of https://github.com/rust-lang/types-team/issues/95
continues the work from #117876. While working on this and I encountered a bunch of further cleanup which I'll either open a tracking issue for or will do in a separate PR:
- rewrite the `RegionKind` docs, they still talk about `ReEmpty` and are generally out of date
- rename `DescriptionCtx` to `DescriptionCtxt`
- what is `CheckRegions::Bound`?
- `collect_late_bound_regions` et al
- `erase_late_bound_regions` -> `instantiate_bound_regions_with_erased`?
- `EraseEarlyRegions` visitor should be removed, feels duplicate
r? `@BoxyUwU`
Don't expect a rcvr in `print_disambiguation_help`
We don't necessarily have a receiver when we are both accidentally using the `.` operator *AND* we have more than one ambiguous method candidate.
Fixes#117728
Add richer structure for Stable MIR Projections
Resolves https://github.com/rust-lang/project-stable-mir/issues/49.
Projections in Stable MIR are currently just strings. This PR replaces that representation with a richer structure, namely projections become vectors of `ProjectionElem`s, just as in MIR. The `ProjectionElem` enum is heavily based off of the MIR `ProjectionElem`.
This PR is a draft since there are several outstanding issues to resolve, including:
- How should `UserTypeProjection`s be represented in Stable MIR? In MIR, the projections are just a vector of `ProjectionElem<(),()>`, meaning `ProjectionElem`s that don't have Local or Type arguments (for `Index`, `Field`, etc. objects). Should `UserTypeProjection`s be represented this way in Stable MIR as well? Or is there a more user-friendly representation that wouldn't drag along all the `ProjectionElem` variants that presumably can't appear?
- What is the expected behavior of a `Place`'s `ty` function? Should it resolve down the chain of projections so that something like `*_1.f` would return the type referenced by field `f`?
- Tests should be added for `UserTypeProjection`
Build pre-coroutine-transform coroutine body on error
I was accidentally building the post-transform coroutine body, rather than the pre-transform coroutine body. There's no pinning expected here yet, and the return type isn't yet transformed into `CoroutineState`.
Fixes#117670
Custom MIR: Support cleanup blocks
Cleanup blocks are declared with `bb (cleanup) = { ... }`.
`Call` and `Drop` terminators take an additional argument describing the unwind action, which is one of the following:
* `UnwindContinue()`
* `UnwindUnreachable()`
* `UnwindTerminate(reason)`, where reason is `ReasonAbi` or `ReasonInCleanup`
* `UnwindCleanup(block)`
Also support unwind resume and unwind terminate terminators:
* `UnwindResume()`
* `UnwindTerminate(reason)`
Cleanup blocks are declared with `bb (cleanup) = { ... }`.
`Call` and `Drop` terminators take an additional argument describing the
unwind action, which is one of the following:
* `UnwindContinue()`
* `UnwindUnreachable()`
* `UnwindTerminate(reason)`, where reason is `ReasonAbi` or `ReasonInCleanup`
* `UnwindCleanup(block)`
Also support unwind resume and unwind terminate terminators:
* `UnwindResume()`
* `UnwindTerminate(reason)`
Always point at index span on index obligation failure
Use more targetted span for index obligation failures by rewriting the obligation cause span.
CC #66023
tests: update check for inferred nneg on zext
This was broken by upstream
llvm/llvm-project@dc6d077396. It's easy enough to use a regex match to support both, so we do that.
r? `@nikic`
`@rustbot` label: +llvm-main
Compute layout with spans for better cycle errors in coroutines
Split out from #117703, this PR at least gives us a nicer span to point at when we hit a cycle error in coroutine layout cycles.
This was broken by upstream
llvm/llvm-project@dc6d077396. It's easy
enough to use a regex match to support both, so we do that.
r? @nikic
@rustbot label: +llvm-main
`ReLateBound` -> `ReBound`
first step of https://github.com/rust-lang/types-team/issues/95
already fairly large xx
there's some future work here I intentionally did not contribute as part of this PR, from my notes:
- `DescriptionCtx` to `DescriptionCtxt`
- what is `CheckRegions::Bound`?
- `collect_late_bound_regions` et al
- `erase_late_bound_regions` -> `instantiate_bound_regions_with_erased`?
- `EraseEarlyRegions` should be removed, feels duplicate
r? `@BoxyUwU`
coverage: Avoid creating malformed macro name spans
This is a workaround for #117788. It detects a particular scenario where we would create malformed coverage spans that might cause `llvm-cov` to immediately exit with an error, preventing the user from processing coverage reports.
The patch has been kept as simple as possible so that it's trivial to backport to beta (or stable) if desired.
---
The `maybe_push_macro_name_span` method is trying to detect macro invocations, so that it can split a span into two parts just after the `!` of the invocation.
Under some circumstances (probably involving nested macros), it gets confused and produces a span that is larger than the original span, and possibly extends outside its enclosing function and even into an adjacent file.
In extreme cases, that can result in malformed coverage mappings that cause `llvm-cov` to fail. For now, we at least want to detect these egregious cases and avoid them, so that coverage reports can still be produced.
Without the workaround applied, this test will produce malformed mappings that
cause `llvm-cov` to fail.
(And if it does emit well-formed mappings, they should be obviously incorrect.)
This is a aspect of Rust that frequently trips up people who are not
aware of it yet. This diagnostic attempts to explain what's happening
and why the lifetime constraint, that was never mentioned in the source,
arose.
Deny more `~const` trait bounds
thereby fixing a family of ICEs (delayed bugs) for `feature(const_trait_impl, effects)` code.
As discussed
r? `@fee1-dead`
Allow adding values to the `!llvm.module.flags` metadata for a generated
module. The syntax is
`-Z llvm_module_flag=<name>:<type>:<value>:<behavior>`
Currently only u32 values are supported but the type is required to be
specified for forward compatibility. The `behavior` element must match
one of the named LLVM metadata behaviors.viors.
This flag is expected to be perma-unstable.
Add `std:#️⃣:{DefaultHasher, RandomState}` exports (needs FCP)
This implements rust-lang/libs-team#267 to move the libstd hasher types to `std::hash` where they belong, instead of `std::collections::hash_map`.
<details><summary>The below no longer applies, but is kept for clarity.</summary>
This is a small refactor for #27242, which moves the definitions of `RandomState` and `DefaultHasher` into `std::hash`, but in a way that won't be noticed in the public API.
I've opened rust-lang/libs-team#267 as a formal ACP to move these directly into the root of `std::hash`, but for now, they're at least separated out from the collections code in a way that will make moving that around easier.
I decided to simply copy the rustdoc for `std::hash` from `core::hash` since I think it would be ideal for the two to diverge longer-term, especially if the ACP is accepted. However, I would be willing to factor them out into a common markdown document if that's preferred.
</details>
It's not clear to me (klinvill) that UserTypeProjections are produced
anymore with the removal of type ascriptions as per
https://github.com/rust-lang/rfcs/pull/3307. Furthermore, it's not clear
to me which variants of ProjectionElem could appear in such projections.
For these reasons, I'm reverting projections in UserTypeProjections to
simple strings until I can get more clarity on UserTypeProjections.
This commit includes richer projections for both Places and
UserTypeProjections. However, the tests only touch on Places. There are
also outstanding TODOs regarding how projections should be resolved to
produce Place types, and regarding if UserTypeProjections should just
contain ProjectionElem<(),()> objects as in MIR.
rustdoc-json: Fix test so it actually checks things
After #111427, no item has a `kind` field, so these assertions could never fail. Instead, assert that those two items arn't present.
r? `@GuillaumeGomez`