Trait predicates for types which have errors may still
evaluate to OK leading to downstream ICEs. Now we return
a selection error for such types in candidate assembly and
thereby prevent such issues
Remove `TypeVariableOriginKind` and `ConstVariableOriginKind`
It's annoying to have to import `TypeVariableOriginKind` just to fill it with `MiscVariable` for almost every use. Every other usage other than `TypeParameterDefinition` wasn't even used -- I can see how it may have been useful once for debugging, but I do quite a lot of typeck debugging and I've never really needed it.
So let's just remove it, and keep around the only useful thing which is the `DefId` of the param for `var_for_def`.
This is based on #123006, which removed the special use of `TypeVariableOriginKind::OpaqueInference`, which I'm pretty sure I was the one that added.
r? lcnr or re-roll to types
Fix various bugs in `ty_kind_suggestion`
Consolidates two implementations of `ty_kind_suggestion`
Fixes some misuse of the empty param-env
Fixes a problem where we suggested `(42)` instead of `(42,)` for tuple suggestions
Suggest a value when `return;`, making it consistent with `break;`
Fixes#123906
Discard overflow obligations in `impl_may_apply`
Hacky fix for #123493. Throws away obligations that are overflowing in `impl_may_apply` when we recompute if an impl applies, since those will lead to fatal overflow if processed during fulfillment.
Something about #114811 (I think it's the predicate reordering) caused us to evaluate predicates differently in error reporting leading to fatal overflow, though I believe the underlying overflow is possible to hit since this code was rewritten to use fulfillment.
Fixes#123493
Don't rely on upvars being assigned just because coroutine-closure kind is assigned
Previously, code relied on the implicit assumption that if a coroutine-closure's kind variable was constrained, then its upvars were also constrained. This is because we assign all of them at once at the end up upvar analysis.
However, there's another way that a coroutine-closure's kind can be constrained: from a signature hint in closure signature deduction. After #123350, we use these hints, which means the implicit assumption above no longer holds.
This PR adds the necessary checks so that we don't ICE.
r? oli-obk
Pass list of defineable opaque types into canonical queries
This eliminates `DefiningAnchor::Bubble` for good and brings the old solver closer to the new one wrt cycles and nested obligations. At that point the difference between `DefiningAnchor::Bind([])` and `DefiningAnchor::Error` was academic. We only used the difference for some sanity checks, which actually had to be worked around in places, so I just removed `DefiningAnchor` entirely and just stored the list of opaques that may be defined.
fixes#108498
fixes https://github.com/rust-lang/rust/issues/116877
* [x] run crater
- https://github.com/rust-lang/rust/pull/122077#issuecomment-2013293931
Safe Transmute: Compute transmutability from `rustc_target::abi::Layout`
In its first step of computing transmutability, `rustc_transmutability` constructs a byte-level representation of type layout (`Tree`). Previously, this representation was computed for ADTs by inspecting the ADT definition and performing our own layout computations. This process was error-prone, verbose, and limited our ability to analyze many types (particularly default-repr types).
In this PR, we instead construct `Tree`s from `rustc_target::abi::Layout`s. This helps ensure that layout optimizations are reflected our analyses, and increases the kinds of types we can now analyze, including:
- default repr ADTs
- transparent unions
- `UnsafeCell`-containing types
Overall, this PR expands the expressvity of `rustc_transmutability` to be much closer to the transmutability analysis performed by miri. Future PRs will work to close the remaining gaps (e.g., support for `Box`, raw pointers, `NonZero*`, coroutines, etc.).
r? `@compiler-errors`
In its first step of computing transmutability, `rustc_transmutability`
constructs a byte-level representation of type layout (`Tree`). Previously, this
representation was computed for ADTs by inspecting the ADT definition and
performing our own layout computations. This process was error-prone, verbose,
and limited our ability to analyze many types (particularly default-repr types).
In this PR, we instead construct `Tree`s from `rustc_target::abi::Layout`s. This
helps ensure that layout optimizations are reflected our analyses, and increases
the kinds of types we can now analyze, including:
- default repr ADTs
- transparent unions
- `UnsafeCell`-containing types
Overall, this PR expands the expressvity of `rustc_transmutability` to be much
closer to the transmutability analysis performed by miri. Future PRs will work
to close the remaining gaps (e.g., support for `Box`, raw pointers, `NonZero*`,
coroutines, etc.).
Check def id before calling `match_projection_projections`
When I "inlined" `assemble_candidates_from_predicates` into `for_each_item_bound` in #120584, I forgot to copy over the check that actually made sure the def id of the candidate was equal to the def id of the obligation. This means that we normalize goal a bit too often even if it's not productive to do so.
This PR adds that def id check back.
Fixes#123448
do not ICE in `fn forced_ambiguity` if we get an error
see the comment. currently causing an ICE in typenum which we've been unable to minimize.
r? `@compiler-errors`
Cleanup: Rename `HAS_PROJECTIONS` to `HAS_ALIASES` etc.
The name of the bitflag `HAS_PROJECTIONS` and of its corresponding method `has_projections` is quite historical dating back to a time when projections were the only kind of alias type.
I think it's time to update it to clear up any potential confusion for newcomers and to reduce unnecessary friction during contributor onboarding.
r? types
change `NormalizesTo` to fully structurally normalize
notes in https://hackmd.io/wZ016dE4QKGIhrOnHLlThQ
need to also update the dev-guide once this PR lands. in short, the setup is now as follows:
`normalizes-to` internally implements one step normalization, applying that normalization to the `goal.predicate.term` causes the projected term to get recursively normalized. With this `normalizes-to` normalizes until the projected term is rigid, meaning that we normalize as many steps necessary, but at least 1.
To handle rigid aliases, we add another candidate only if the 1 to inf step normalization failed. With this `normalizes-to` is now full structural normalization. We can now change `AliasRelate` to simply emit `normalizes-to` goals for the rhs and lhs.
This avoids the concerns from https://github.com/rust-lang/trait-system-refactor-initiative/issues/103 and generally feels cleaner
some smaller DefiningOpaqueTypes::No -> Yes switches
r? `@compiler-errors`
These are some easy cases, so let's get them out of the way first.
I added tests exercising the specialization code paths that I believe weren't tested so far.
follow-up to https://github.com/rust-lang/rust/pull/117348
The reason is that in specialization graph computation we use `DefiningAnchor::Error`, so there's no difference anyway. And in the other use cases, we
* already errored in the specialization_graph computation, or
* already errored in coherence, or
* are comparing opaque types with inference variables already, or
* there are no opaque types involved
check `FnDef` return type for WF
better version of #106807, fixes#84533 (mostly). It's not perfect given that we still ignore WF requirements involving bound regions but I wasn't able to quickly write an example, so even if theoretically exploitable, it should be far harder to trigger.
This is strictly more restrictive than checking the return type for WF as part of the builtin `FnDef: FnOnce` impl (#106807) and moving to this approach in the future will not break any code.
~~It also agrees with my theoretical view of how this should behave~~
r? types
instantiate higher ranked goals outside of candidate selection
This PR modifies `evaluate` to more eagerly instantiate higher-ranked goals, preventing the `leak_check` during candidate selection from detecting placeholder errors involving that binder.
For a general background regarding higher-ranked region solving and the leak check, see https://hackmd.io/qd9Wp03cQVy06yOLnro2Kg.
> The first is something called the **leak check**. You can think of it as a "quick and dirty" approximation for the region check, which will come later. The leak check detects some kinds of errors early, essentially deciding between "this set of outlives constraints are guaranteed to result in an error eventually" or "this set of outlives constraints may be solvable".
## The ideal future
We would like to end up with the following idealized design to handle universal binders:
```rust
fn enter_forall<'tcx, T, R>(
forall: Binder<'tcx, T>,
f: impl FnOnce(T) -> R,
) -> R {
let new_universe = infcx.increment_universe_index();
let value = instantiate_binder_with_placeholders_in(new_universe, forall);
let result = f(value);
eagerly_handle_higher_ranked_region_constraints_in(new_universe);
infcx.decrement_universe_index();
assert!(!result.has_placeholders_in_or_above(new_universe));
result
}
```
That is, when universally instantiating a binder, anything using the placeholders has to happen inside of a limited scope (the closure `f`). After this closure has completed, all constraints involving placeholders are known.
We then handle any *external constraints* which name these placeholders. We destructure `TypeOutlives` constraints involving placeholders and eagerly handle any region constraints involving these placeholders. We do not return anything mentioning the placeholders created inside of this function to the caller.
Being able to eagerly handle *all* region constraints involving placeholders will be difficult due to complex `TypeOutlives` constraints, involving inference variables or alias types, and higher ranked implied bounds. The exact issues and possible solutions are out of scope of this FCP.
#### How does the leak check fit into this
The `leak_check` is an underapproximation of `eagerly_handle_higher_ranked_region_constraints_in`. It detects some kinds of errors involving placeholders from `new_universe`, but not all of them.
It only looks at region outlives constraints, ignoring `TypeOutlives`, and checks whether one of the following two conditions are met for **placeholders in or above `new_universe`**, in which case it results in an error:
- `'!p1: '!p2` a placeholder `'!p2` outlives a different placeholder `'!p1`
- `'!p1: '?2` an inference variable `'?2` outlives a placeholder `'!p1` *which it cannot name*
It does not handle all higher ranked region constraints, so we still return constraints involving placeholders from `new_universe` which are then (re)checked by `lexical_region_resolve` or MIR borrowck.
As we check higher ranked constraints in the full regionck anyways, the `leak_check` is not soundness critical. It's current only purpose is to move some higher ranked region errors earlier, enabling it to guide type inference and trait solving. Adding additional uses of the `leak_check` in the future would only strengthen inference and is therefore not breaking.
## Where do we use currently use the leak check
The `leak_check` is currently used in two places:
Coherence does not use a proper regionck, only relying on the `leak_check` called [at the end of the implicit negative overlap check](8b94152af6/compiler/rustc_trait_selection/src/traits/coherence.rs (L235-L238)). During coherence all parameters are instantiated with inference variables, so the only possible region errors are higher-ranked. We currently also sometimes make guesses when destructuring `TypeOutlives` constraints which can theoretically result in incorrect errors. This could result in overlapping impls.
We also use the `leak_check` [at the end of `fn evaluation_probe`](8b94152af6/compiler/rustc_trait_selection/src/traits/select/mod.rs (L607-L610)). This function is used during candidate assembly for `Trait` goals. Most notably we use [inside of `evaluate_candidate` during winnowing](0e4243538b/compiler/rustc_trait_selection/src/traits/select/mod.rs (L491-L502)). Conceptionally, it is as if we compute each candidate in a separate `enter_forall`.
## The current use in `fn evaluation_probe` is undesirable
Because we only instantiate a higher-ranked goal once inside of `fn evaluation_probe`, errors involving placeholders from that binder can impact selection. This results in inconsistent behavior ([playground](
*[playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=dac60ebdd517201788899ffa77364831)*)):
```rust
trait Leak<'a> {}
impl Leak<'_> for Box<u32> {}
impl Leak<'static> for Box<u16> {}
fn impls_leak<T: for<'a> Leak<'a>>() {}
trait IndirectLeak<'a> {}
impl<'a, T: Leak<'a>> IndirectLeak<'a> for T {}
fn impls_indirect_leak<T: for<'a> IndirectLeak<'a>>() {}
fn main() {
// ok
//
// The `Box<u16>` impls fails the leak check,
// meaning that we apply the `Box<u32>` impl.
impls_leak::<Box<_>>();
// error: type annotations needed
//
// While the `Box<u16>` impl would fail the leak check
// we have already instantiated the binder while applying
// the generic `IndirectLeak` impl, so during candidate
// selection of `Leak` we do not detect the placeholder error.
// Evaluation of `Box<_>: Leak<'!a>` is therefore ambiguous,
// resulting in `for<'a> Box<_>: Leak<'a>` also being ambiguous.
impls_indirect_leak::<Box<_>>();
}
```
We generally prefer `where`-bounds over implementations during candidate selection, both for [trait goals](11f32b73e0/compiler/rustc_trait_selection/src/traits/select/mod.rs (L1863-L1887)) and during [normalization](11f32b73e0/compiler/rustc_trait_selection/src/traits/project.rs (L184-L198)). However, we currently **do not** use the `leak_check` during candidate assembly in normalizing. This can result in inconsistent behavior:
```rust
trait Trait<'a> {
type Assoc;
}
impl<'a, T> Trait<'a> for T {
type Assoc = usize;
}
fn trait_bound<T: for<'a> Trait<'a>>() {}
fn projection_bound<T: for<'a> Trait<'a, Assoc = usize>>() {}
// A function with a trivial where-bound which is more
// restrictive than the impl.
fn function<T: Trait<'static, Assoc = usize>>() {
// ok
//
// Proving `for<'a> T: Trait<'a>` using the where-bound results
// in a leak check failure, so we use the more general impl,
// causing this to succeed.
trait_bound::<T>();
// error
//
// Proving the `Projection` goal `for<'a> T: Trait<'a, Assoc = usize>`
// does not use the leak check when trying the where-bound, causing us
// to prefer it over the impl, resulting in a placeholder error.
projection_bound::<T>();
// error
//
// Trying to normalize the type `for<'a> fn(<T as Trait<'a>>::Assoc)`
// only gets to `<T as Trait<'a>>::Assoc` once `'a` has been already
// instantiated, causing us to prefer the where-bound over the impl
// resulting in a placeholder error. Even if were were to also use the
// leak check during candidate selection for normalization, this
// case would still not compile.
let _higher_ranked_norm: for<'a> fn(<T as Trait<'a>>::Assoc) = |_| ();
}
```
This is also likely to be more performant. It enables more caching in the new trait solver by simply [recursively calling the canonical query][new solver] after instantiating the higher-ranked goal.
It is also unclear how to add the leak check to normalization in the new solver. To handle https://github.com/rust-lang/trait-system-refactor-initiative/issues/1 `Projection` goals are implemented via `AliasRelate`. This again means that we instantiate the binder before ever normalizing any alias. Even if we were to avoid this, we lose the ability to [cache normalization by itself, ignoring the expected `term`](5bd5d214ef/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs (L34-L49)). We cannot replace the `term` with an inference variable before instantiating the binder, as otherwise `for<'a> T: Trait<Assoc<'a> = &'a ()>` breaks. If we only replace the term after instantiating the binder, we cannot easily evaluate the goal in a separate context, as [we'd then lose the information necessary for the leak check](11f32b73e0/compiler/rustc_next_trait_solver/src/canonicalizer.rs (L230-L232)). Adding this information to the canonical input also seems non-trivial.
## Proposed solution
I propose to instantiate the binder outside of candidate assembly, causing placeholders from higher-ranked goals to get ignored while selecting their candidate. This mostly[^1] matches the [current behavior of the new solver][new solver]. The impact of this change is therefore as follows:
```rust
trait Leak<'a> {}
impl Leak<'_> for Box<u32> {}
impl Leak<'static> for Box<u16> {}
fn impls_leak<T: for<'a> Leak<'a>>() {}
trait IndirectLeak<'a> {}
impl<'a, T: Leak<'a>> IndirectLeak<'a> for T {}
fn impls_indirect_leak<T: for<'a> IndirectLeak<'a>>() {}
fn guide_selection() {
// ok -> ambiguous
impls_leak::<Box<_>>();
// ambiguous
impls_indirect_leak::<Box<_>>();
}
trait Trait<'a> {
type Assoc;
}
impl<'a, T> Trait<'a> for T {
type Assoc = usize;
}
fn trait_bound<T: for<'a> Trait<'a>>() {}
fn projection_bound<T: for<'a> Trait<'a, Assoc = usize>>() {}
// A function which a trivial where-bound which is more
// restrictive than the impl.
fn function<T: Trait<'static, Assoc = usize>>() {
// ok -> error
trait_bound::<T>();
// error
projection_bound::<T>();
// error
let _higher_ranked_norm: for<'a> fn(<T as Trait<'a>>::Assoc) = |_| ();
}
```
This does not change the behavior if candidates have higher ranked nested goals, as in this case the `leak_check` causes the nested goal to result in an error ([playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=a74c25300b23db9022226de99d8a2fa6)):
```rust
trait LeakCheckFailure<'a> {}
impl LeakCheckFailure<'static> for () {}
trait Trait<T> {}
impl Trait<u32> for () where for<'a> (): LeakCheckFailure<'a> {}
impl Trait<u16> for () {}
fn impls_trait<T: Trait<U>, U>() {}
fn main() {
// ok
//
// It does not matter whether candidate assembly
// considers the placeholders from higher-ranked goal.
//
// Either `for<'a> (): LeakCheckFailure<'a>` has no
// applicable candidate or it has a single applicable candidate
// when then later results in an error. This allows us to
// infer `U` to `u16`.
impls_trait::<(), _>()
}
```
## Impact on existing crates
This is a **breaking change**. [A crater run](https://github.com/rust-lang/rust/pull/119820#issuecomment-1926862174) found 17 regressed crates with 7 root causes.
For a full analysis of all affected crates, see https://gist.github.com/lcnr/7c1c652f30567048ea240554a36ed95c.
---
I believe this breakage to be acceptable and would merge this change. I am confident that the new position of the leak check matches our idealized future and cannot envision any other consistent alternative. Where possible, I intend to open PRs fixing/avoiding the regressions before landing this PR.
I originally intended to remove the `coherence_leak_check` lint in the same PR. However, while I am confident in the *position* of the leak check, deciding on its exact behavior is left as future work, cc #112999. This PR therefore only moves the leak check while keeping the lint when relying on it in coherence.
[new solver]: https://github.com/rust-lang/rust/blob/master/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs#L479-L484
[^1]: the new solver has a separate cause of inconsistent behavior rn https://github.com/rust-lang/trait-system-refactor-initiative/issues/53#issuecomment-1914310171
r? `@nikomatsakis`
Check `x86_64` size assertions on `aarch64`, too
(Context: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/Checking.20size.20assertions.20on.20aarch64.3F)
Currently the compiler has around 30 sets of `static_assert_size!` for various size-critical data structures (e.g. various IR nodes), guarded by `#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]`.
(Presumably this cfg avoids having to maintain separate size values for 32-bit targets and unusual 64-bit targets. Apparently it may have been necessary before the i128/u128 alignment changes, too.)
This is slightly incovenient for people on aarch64 workstations (e.g. Macs), because the assertions normally aren't checked until we push to a PR. So this PR adds `aarch64` to the `#[cfg(..)]` guarding all of those assertions in the compiler.
---
Implemented with a simple find/replace. Verified by manually inspecting each `static_assert_size!` in `compiler/`, and checking that either the replacement succeeded, or adding aarch64 wouldn't have been appropriate.
Assert that args are actually compatible with their generics, rather than just their count
Right now we just check that the number of args is right, rather than actually checking the kinds. Uplift a helper fn that I wrote from trait selection to do just that. Found a couple bugs along the way.
r? `@lcnr` or `@fmease` (or anyone really lol)
Make inductive cycles always ambiguous
This makes inductive cycles always result in ambiguity rather than be treated like a stack-dependent error.
This has some interactions with specialization, and so breaks a few UI tests that I don't agree should've ever worked in the first place, and also breaks a handful of crates in a way that I don't believe is a problem.
On the bright side, it puts us in a better spot when it comes to eventually enabling coinduction everywhere.
## Results
This was cratered in https://github.com/rust-lang/rust/pull/116494#issuecomment-2008657494, which boils down to two regressions:
* `lu_packets` - This code should have never compiled in the first place. More below.
* **ALL** other regressions are due to `commit_verify@0.11.0-beta.1` (edit: and `commit_verify@0.10.x`) - This actually seems to be fixed in version `0.11.0-beta.5`, which is the *most* up to date version, but it's still prerelease on crates.io so I don't think cargo ends up picking `beta.5` when building dependent crates.
### `lu_packets`
Firstly, this crate uses specialization, so I think it's automatically worth breaking. However, I've minimized [the regression](https://crater-reports.s3.amazonaws.com/pr-116494-3/try%23d614ed876e31a5f3ad1d0fbf848fcdab3a29d1d8/gh/lcdr.lu_packets/log.txt) to:
```rust
// Upstream crate
pub trait Serialize {}
impl Serialize for &() {}
impl<S> Serialize for &[S] where for<'a> &'a S: Serialize {}
// ----------------------------------------------------------------------- //
// Downstream crate
#![feature(specialization)]
#![allow(incomplete_features, unused)]
use upstream::Serialize;
trait Replica {
fn serialize();
}
impl<T> Replica for T {
default fn serialize() {}
}
impl<T> Replica for Option<T>
where
for<'a> &'a T: Serialize,
{
fn serialize() {}
}
```
Specifically this fails when computing the specialization graph for the `downstream` crate.
The code ends up cycling on `&[?0]: Serialize` when we equate `&?0 = &[?1]` during impl matching, which ends up needing to prove `&[?1]: Serialize`, which since cycles are treated like ambiguity, ends up in a **fatal overflow**. For some reason this requires two crates, squashing them into one crate doesn't work.
Side-note: This code is subtly order dependent. When minimizing, I ended up having the code start failing on `nightly` very easily after removing and reordering impls. This seems to me all the more reason to remove this behavior altogether.
## Side-note: Item Bounds (edit: this was fixed independently in #121123)
Due to the changes in #120584 where we now consider an alias's item bounds *and* all the item bounds of the alias's nested self type aliases, I've had to add e6b64c6194 which is a hack to make sure we're not eagerly normalizing bounds that have nothing to do with the predicate we're trying to solve, and which result in.
This is fixed in a more principled way in #121123.
---
r? lcnr for an initial review
rustdoc: heavily simplify the synthesis of auto trait impls
`gd --numstat HEAD~2 HEAD src/librustdoc/clean/auto_trait.rs`
**+315 -705** 🟩🟥🟥🟥⬛
---
As outlined in issue #113015, there are currently 3[^1] large separate routines that “clean” `rustc_middle::ty` data types related to generics & predicates to rustdoc data types. Every single one has their own kinds of bugs. While I've patched a lot of bugs in each of the routines in the past, it's about time to unify them. This PR is only the first in a series. It completely **yanks** the custom “bounds cleaning” of mod `auto_trait` and reuses the routines found in mod `simplify`. As alluded to, `simplify` is also flawed but it's still more complete than `auto_trait`'s routines. [See also my review comment over at `tests/rustdoc/synthetic_auto/bounds.rs`](https://github.com/rust-lang/rust/pull/123340#discussion_r1546900539).
This is preparatory work for rewriting “bounds cleaning” from scratch in follow-up PRs in order to finally [fix] #113015.
Apart from that, I've eliminated all potential sources of *instability* in the rendered output.
See also #119597. I'm pretty sure this fixes#119597.
This PR does not attempt to fix [any other issues related to synthetic auto trait impls](https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+label%3AA-synthetic-impls%20label%3AA-auto-traits).
However, it's definitely meant to be a *stepping stone* by making `auto_trait` more contributor-friendly.
---
* Replace `FxHash{Map,Set}` with `FxIndex{Map,Set}` to guarantee a stable iteration order
* Or as a perf opt, `UnordSet` (a thin wrapper around `FxHashSet`) in cases where we never iterate over the set.
* Yes, we do make use of `swap_remove` but that shouldn't matter since all the callers are deterministic. It does make the output less “predictable” but it's still better than before. Ofc, I rely on `rustc_infer` being deterministic. I hope that holds.
* Utilizing `clean::simplify` over the custom “bounds cleaning” routines wipes out the last reference to `collect_referenced_late_bound_regions` in rustdoc (`simplify` uses `bound_vars`) which was a source of instability / unpredictability (cc #116388)
* Remove the types `RegionTarget` and `RegionDeps` from `librustdoc`. They were duplicates of the identical types found in `rustc`. Just import them from `rustc`. For some reason, they were duplicated when splitting `auto_trait` in two in #49711.
* Get rid of the useless “type namespace” `AutoTraitFinder` in `librustdoc`
* The struct only held a `DocContext`, it was over-engineered
* Turn the associated functions into free ones
* Eliminates rightward drift; increases legibility
* `rustc` also contains a useless `AutoTraitFinder` struct but I plan on removing that in a follow-up PR
* Rename a bunch of methods to be way more descriptive
* Eliminate `use super::*;`
* Lead to `clean/mod.rs` accumulating a lot of unnecessary imports
* Made `auto_traits` less modular
* Eliminate a custom `TypeFolder`: We can just use the rustc helper `fold_regions` which does that for us
I plan on adding extensive documentation to `librustdoc`'s `auto_trait` in follow-up PRs.
I don't want to do that in this PR because further refactoring & bug fix PRs may alter the overall structure of `librustdoc`'s & `rustc`'s `auto_trait` modules to a great degree. I'm slowly digging into the dark details of `rustc`'s `auto_trait` module again and once I have the full picture I will be able to provide proper docs.
---
While this PR does indeed touch `rustc`'s `auto_trait` — mostly tiny refactorings — I argue this PR doesn't need any compiler reviewers next to rustdoc ones since that module falls under the purview of rustdoc — it used to be part of `librustdoc` after all (#49711).
Sorry for not having split this into more commits. If you'd like me to I can try to split it into more atomic commits retroactively. However, I don't know if that would actually make reviewing easier. I think the best way to review this might just be to place the master version of `auto_trait` on the left of your screen and the patched one on the right, not joking.
r? `@GuillaumeGomez`
[^1]: Or even 4 depending on the way you're counting.
compiler: fix few unused_peekable and needless_pass_by_ref_mut clippy lints
This fixes few instances of `unused_peekable` and `needless_pass_by_ref_mut`. While i expected to fix more warnings, `needless_pass_by_ref_mut` produced too much for one PR, so i stopped here.
Better reviewed commit by commit, as fixes splitted by chunks.
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_trait_selection\src\traits\project.rs:511:12
|
511 | selcx: &mut SelectionContext<'a, 'tcx>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&SelectionContext<'a, 'tcx>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_trait_selection\src\traits\specialize\specialization_graph.rs:201:28
|
201 | fn iter_children(children: &mut Children) -> impl Iterator<Item = DefId> + '_ {
| ^^^^^^^^^^^^^ help: consider changing to: `&Children`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: `peek` never called on `Peekable` iterator
--> compiler\rustc_session\src\utils.rs:130:13
|
130 | let mut args = std::env::args_os().map(|arg| arg.to_string_lossy().to_string()).peekable();
| ^^^^
|
= help: consider removing the call to `peekable`
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unused_peekable
warning: `peek` never called on `Peekable` iterator
--> compiler\rustc_trait_selection\src\traits\error_reporting\suggestions.rs:4934:17
|
4934 | let mut bounds = pred.bounds.iter().peekable();
| ^^^^^^
|
= help: consider removing the call to `peekable`
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unused_peekable
Rename `hir::Local` into `hir::LetStmt`
Follow-up of #122776.
As discussed on [zulip](https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/Improve.20naming.20of.20.60ExprKind.3A.3ALet.60.3F).
I made this change into a separate PR because I'm less sure about this change as is. For example, we have `visit_local` and `LocalSource` items. Is it fine to keep these two as is (I supposed it is but I prefer to ask) or not? Having `Node::Local(LetStmt)` makes things more explicit but is it going too far?
r? ```@oli-obk```
Rollup of 8 pull requests
Successful merges:
- #114009 (compiler: allow transmute of ZST arrays with generics)
- #122195 (Note that the caller chooses a type for type param)
- #122651 (Suggest `_` for missing generic arguments in turbofish)
- #122784 (Add `tag_for_variant` query)
- #122839 (Split out `PredicatePolarity` from `ImplPolarity`)
- #122873 (Merge my contributor emails into one using mailmap)
- #122885 (Adjust better spastorino membership to triagebot's adhoc_groups)
- #122888 (add a couple more tests)
r? `@ghost`
`@rustbot` modify labels: rollup
Most of the tracing calls didn't fully leverage the power of `tracing`.
For example, several of them used to hard-code method names / tracing spans
as well as variable names. Use `#[instrument]` and `?var` / `%var` (etc.) instead.
In my opinion, this is the proper way to migrate them from the old
AstConv nomenclature to the new HIR ty lowering one.
Several (doc) comments were super outdated or didn't provide enough context.
Some doc comments shoved everything in a single paragraph without respecting
the fact that the first paragraph should be a single sentence because rustdoc
treats these as item descriptions / synopses on module pages.
Make `#[diagnostic::on_unimplemented]` format string parsing more robust
This commit fixes several issues with the format string parsing of the `#[diagnostic::on_unimplemented]` attribute that were pointed out by `@ehuss.`
In detail it fixes:
* Appearing format specifiers (display, etc). For these we generate a warning that the specifier is unsupported. Otherwise we ignore them
* Positional arguments. For these we generate a warning that positional arguments are unsupported in that location and replace them with the format string equivalent (so `{}` or `{n}` where n is the index of the positional argument)
* Broken format strings with enclosed }. For these we generate a warning about the broken format string and set the emitted message literally to the provided unformatted string
* Unknown format specifiers. For these we generate an additional warning about the unknown specifier. Otherwise we emit the literal string as message.
This essentially makes those strings behave like `format!` with the minor difference that we do not generate hard errors but only warnings. After that we continue trying to do something unsuprising (mostly either ignoring the broken parts or falling back to just giving back the literal string as provided).
Fix#122391
r? `@compiler-errors`
Don't ICE when encountering bound regions in generator interior type
I'm pretty sure this meant to say "`has_free_regions`", probably just a typo in 4a4fc3bb5b. We can have bound regions (because we only convert non-bound regions into existential regions in generator interiors), but we can't have (non-ReErased) free regions.
r? lcnr
This commit fixes several issues with the format string parsing of the
`#[diagnostic::on_unimplemented]` attribute that were pointed out by
@ehuss.
In detail it fixes:
* Appearing format specifiers (display, etc). For these we generate a
warning that the specifier is unsupported. Otherwise we ignore them
* Positional arguments. For these we generate a warning that positional
arguments are unsupported in that location and replace them with the
format string equivalent (so `{}` or `{n}` where n is the index of the
positional argument)
* Broken format strings with enclosed }. For these we generate a warning
about the broken format string and set the emitted message literally to
the provided unformatted string
* Unknown format specifiers. For these we generate an additional warning
about the unknown specifier. Otherwise we emit the literal string as
message.
This essentially makes those strings behave like `format!` with the
minor difference that we do not generate hard errors but only warnings.
After that we continue trying to do something unsuprising (mostly either
ignoring the broken parts or falling back to just giving back the
literal string as provided).
Fix#122391
For async closures, cap closure kind, get rid of `by_mut_body`
Right now we have three `AsyncFn*` traits, and three corresponding futures that are returned by the `call_*` functions for them. This is fine, but it is a bit excessive, since the future returned by `AsyncFn` and `AsyncFnMut` are identical. Really, the only distinction we need to make with these bodies is "by ref" and "by move".
This PR removes `AsyncFn::CallFuture` and renames `AsyncFnMut::CallMutFuture` to `AsyncFnMut::CallRefFuture`. This simplifies MIR building for async closures, since we don't need to build an extra "by mut" body, but just a "by move" body which is materially different.
We need to do a bit of delicate handling of the ClosureKind for async closures, since we need to "cap" it to `AsyncFnMut` in some cases when we only care about what body we're looking for.
This also fixes a bug where `<{async closure} as Fn>::call` was returning a body that takes the async-closure receiver *by move*.
This also helps align the `AsyncFn` traits to the `LendingFn` traits' eventual designs.
Remove redundant coroutine captures note
This note is redundant, since we'll always be printing this "captures the following types..." between *more* descriptive `BuiltinDerivedObligationCause`s.
Please review with whitespace disabled, since I also removed an unnecessary labeled break.
Silence unecessary !Sized binding error
When gathering locals, we introduce a `Sized` obligation for each
binding in the pattern. *After* doing so, we typecheck the init
expression. If this has a type failure, we store `{type error}`, for
both the expression and the pattern. But later we store an inference
variable for the pattern.
We now avoid any override of an existing type on a hir node when they've
already been marked as `{type error}`, and on E0277, when it comes from
`VariableType` we silence the error in support of the type error.
Fix https://github.com/rust-lang/rust/issues/117846
When gathering locals, we introduce a `Sized` obligation for each
binding in the pattern. *After* doing so, we typecheck the init
expression. If this has a type failure, we store `{type error}`, for
both the expression and the pattern. But later we store an inference
variable for the pattern.
We now avoid any override of an existing type on a hir node when they've
already been marked as `{type error}`, and on E0277, when it comes from
`VariableType` we silence the error in support of the type error.
Fix#117846.
clean up `Sized` checking
This PR cleans up `sized_constraint` and related functions to make them simpler and faster. This should not make more or less code compile, but it can change error output in some rare cases.
## enums and unions are `Sized`, even if they are not WF
The previous code has some special handling for enums, which made them sized if and only if the last field of each variant is sized. For example given this definition (which is not WF)
```rust
enum E<T1: ?Sized, T2: ?Sized, U1: ?Sized, U2: ?Sized> {
A(T1, T2),
B(U1, U2),
}
```
the enum was sized if and only if `T2` and `U2` are sized, while `T1` and `T2` were ignored for `Sized` checking. After this PR this enum will always be sized.
Unsized enums are not a thing in Rust and removing this special case allows us to return an `Option<Ty>` from `sized_constraint`, rather than a `List<Ty>`.
Similarly, the old code made an union defined like this
```rust
union Union<T: ?Sized, U: ?Sized> {
head: T,
tail: U,
}
```
sized if and only if `U` is sized, completely ignoring `T`. This just makes no sense at all and now this union is always sized.
## apply the "perf hack" to all (non-error) types, instead of just type parameters
This "perf hack" skips evaluating `sized_constraint(adt): Sized` if `sized_constraint(adt): Sized` exactly matches a predicate defined on `adt`, for example:
```rust
// `Foo<T>: Sized` iff `T: Sized`, but we know `T: Sized` from a predicate of `Foo`
struct Foo<T /*: Sized */>(T);
```
Previously this was only applied to type parameters and now it is applied to every type. This means that for example this type is now always sized:
```rust
// Note that this definition is WF, but the type `S<T>` not WF in the global/empty ParamEnv
struct S<T>([T]) where [T]: Sized;
```
I don't anticipate this to affect compile time of any real-world program, but it makes the code a bit nicer and it also makes error messages a bit more consistent if someone does write such a cursed type.
## tuples are sized if the last type is sized
The old solver already has this behavior and this PR also implements it for the new solver and `is_trivially_sized`. This makes it so that tuples work more like a struct defined like this:
```rust
struct TupleN<T1, T2, /* ... */ Tn: ?Sized>(T1, T2, /* ... */ Tn);
```
This might improve the compile time of programs with large tuples a little, but is mostly also a consistency fix.
## `is_trivially_sized` for more types
This function is used post-typeck code (borrowck, const eval, codegen) to skip evaluating `T: Sized` in some cases. It will now return `true` in more cases, most notably `UnsafeCell<T>` and `ManuallyDrop<T>` where `T.is_trivially_sized`.
I'm anticipating that this change will improve compile time for some real world programs.
Stabilize associated type bounds (RFC 2289)
This PR stabilizes associated type bounds, which were laid out in [RFC 2289]. This gives us a shorthand to express nested type bounds that would otherwise need to be expressed with nested `impl Trait` or broken into several `where` clauses.
### What are we stabilizing?
We're stabilizing the associated item bounds syntax, which allows us to put bounds in associated type position within other bounds, i.e. `T: Trait<Assoc: Bounds...>`. See [RFC 2289] for motivation.
In all position, the associated type bound syntax expands into a set of two (or more) bounds, and never anything else (see "How does this differ[...]" section for more info).
Associated type bounds are stabilized in four positions:
* **`where` clauses (and APIT)** - This is equivalent to breaking up the bound into two (or more) `where` clauses. For example, `where T: Trait<Assoc: Bound>` is equivalent to `where T: Trait, <T as Trait>::Assoc: Bound`.
* **Supertraits** - Similar to above, `trait CopyIterator: Iterator<Item: Copy> {}`. This is almost equivalent to breaking up the bound into two (or more) `where` clauses; however, the bound on the associated item is implied whenever the trait is used. See #112573/#112629.
* **Associated type item bounds** - This allows constraining the *nested* rigid projections that are associated with a trait's associated types. e.g. `trait Trait { type Assoc: Trait2<Assoc2: Copy>; }`.
* **opaque item bounds (RPIT, TAIT)** - This allows constraining associated types that are associated with the opaque without having to *name* the opaque. For example, `impl Iterator<Item: Copy>` defines an iterator whose item is `Copy` without having to actually name that item bound.
The latter three are not expressible in surface Rust (though for associated type item bounds, this will change in #120752, which I don't believe should block this PR), so this does represent a slight expansion of what can be expressed in trait bounds.
### How does this differ from the RFC?
Compared to the RFC, the current implementation *always* desugars associated type bounds to sets of `ty::Clause`s internally. Specifically, it does *not* introduce a position-dependent desugaring as laid out in [RFC 2289], and in particular:
* It does *not* desugar to anonymous associated items in associated type item bounds.
* It does *not* desugar to nested RPITs in RPIT bounds, nor nested TAITs in TAIT bounds.
This position-dependent desugaring laid out in the RFC existed simply to side-step limitations of the trait solver, which have mostly been fixed in #120584. The desugaring laid out in the RFC also added unnecessary complication to the design of the feature, and introduces its own limitations to, for example:
* Conditionally lowering to nested `impl Trait` in certain positions such as RPIT and TAIT means that we inherit the limitations of RPIT/TAIT, namely lack of support for higher-ranked opaque inference. See this code example: https://github.com/rust-lang/rust/pull/120752#issuecomment-1979412531.
* Introducing anonymous associated types makes traits no longer object safe, since anonymous associated types are not nameable, and all associated types must be named in `dyn` types.
This last point motivates why this PR is *not* stabilizing support for associated type bounds in `dyn` types, e.g, `dyn Assoc<Item: Bound>`. Why? Because `dyn` types need to have *concrete* types for all associated items, this would necessitate a distinct lowering for associated type bounds, which seems both complicated and unnecessary compared to just requiring the user to write `impl Trait` themselves. See #120719.
### Implementation history:
Limited to the significant behavioral changes and fixes and relevant PRs, ping me if I left something out--
* #57428
* #108063
* #110512
* #112629
* #120719
* #120584Closes#52662
[RFC 2289]: https://rust-lang.github.io/rfcs/2289-associated-type-bounds.html
`NormalizesTo`: return nested goals to caller
Fixes the regression of `paperclip-core`. see https://hackmd.io/IsVAafiOTAaPIFcUxRJufw for more details.
r? ```@compiler-errors```
Provide structured suggestion for `#![feature(foo)]`
```
error: `S2<'_>` is forbidden as the type of a const generic parameter
--> $DIR/lifetime-in-const-param.rs:5:23
|
LL | struct S<'a, const N: S2>(&'a ());
| ^^
|
= note: the only supported types are integers, `bool` and `char`
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
```
Fix#55941.
```
error: `S2<'_>` is forbidden as the type of a const generic parameter
--> $DIR/lifetime-in-const-param.rs:5:23
|
LL | struct S<'a, const N: S2>(&'a ());
| ^^
|
= note: the only supported types are integers, `bool` and `char`
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
```
Fix#55941.
Safe Transmute: Use 'not yet supported', not 'unspecified' in errors
We can (and will) support analyzing the transmutability of types whose layouts aren't completely specified by its repr. This change ensures that the error messages remain sensible after this support lands.
r? ``@compiler-errors``
Consolidate WF for aliases
Make RPITs/TAITs/weak (type) aliases/projections all enforce:
1. their nominal predicates
2. their args are WF
This possibly does extra work, but is also nice for consistency sake.
r? lcnr
We can (and will) support analyzing the transmutability of types
whose layouts aren't completely specified by its repr. This change
ensures that the error messages remain sensible after this support
lands.
hir: Remove `opt_local_def_id_to_hir_id` and `opt_hir_node_by_def_id`
Also replace a few `hir_node()` calls with `hir_node_by_def_id()`.
Follow up to https://github.com/rust-lang/rust/pull/120943.
Rollup of 10 pull requests
Successful merges:
- #117118 ([AIX] Remove AixLinker's debuginfo() implementation)
- #121650 (change std::process to drop supplementary groups based on CAP_SETGID)
- #121764 (Make incremental sessions identity no longer depend on the crate names provided by source code)
- #122212 (Copy byval argument to alloca if alignment is insufficient)
- #122322 (coverage: Initial support for branch coverage instrumentation)
- #122373 (Fix the conflict problem between the diagnostics fixes of lint `unnecessary_qualification` and `unused_imports`)
- #122479 (Implement `Duration::as_millis_{f64,f32}`)
- #122487 (Rename `StmtKind::Local` variant into `StmtKind::Let`)
- #122498 (Update version of cc crate)
- #122503 (Make `SubdiagMessageOp` well-formed)
r? `@ghost`
`@rustbot` modify labels: rollup
more eagerly instantiate binders
The old solver sometimes incorrectly used `sub`, change it to explicitly instantiate binders and use `eq` instead. While doing so I also moved the instantiation before the normalize calls. This caused some observable changes, will explain these inline. This PR therefore requires a crater run and an FCP.
r? types
Document some builtin impls in the next solver
This does not cover all builtin impls, but ones that I were able to go over within a cycle.
r? `@lcnr`
Let me know if the place isn't correct for these, or if you'd like me to change how the impls are presented ^^
Safe Transmute: Require that source referent is smaller than destination
`BikeshedIntrinsicFrom` currently models transmute-via-union; i.e., it attempts to provide a `where` bound for this function:
```rust
pub unsafe fn transmute_via_union<Src, Dst>(src: Src) -> Dst {
use core::mem::*;
#[repr(C)]
union Transmute<T, U> {
src: ManuallyDrop<T>,
dst: ManuallyDrop<U>,
}
let transmute = Transmute { src: ManuallyDrop::new(src) };
// SAFETY: The caller must guarantee that the transmutation is safe.
let dst = transmute.dst;
ManuallyDrop::into_inner(dst)
}
```
A quirk of this model is that it admits padding extensions in value-to-value transmutation: The destination type can be bigger than the source type, so long as the excess consists of uninitialized bytes. However, this isn't permissible for reference-to-reference transmutations (introduced in #110662) — extra referent bytes cannot come from thin air.
This PR patches our analysis for reference-to-reference transmutations to require that the destination referent is no larger than the source referent.
r? `@compiler-errors`
The source referent absolutely must be smaller than the destination
referent of a ref-to-ref transmute; the excess bytes referenced
cannot arise from thin air, even if those bytes are uninitialized.
Don't Create `ParamCandidate` When Obligation Contains Errors
Fixes#121941
I'm not sure if I understand this correctly but this bug was caused by an error type incorrectly matching against `ParamCandidate`. This was introduced by the changes made in #72621 (figured using cargo-bisect-rustc).
This PR fixes it by skipping `ParamCandidate` generation when an error type is involved. Also, this is similar to #73005 but addresses `ParamCandidate` instead of `ImplCandidate`.
Use `ControlFlow` in visitors.
Follow up to #121256
This does have a few small behaviour changes in some diagnostic output where the visitor will now find the first match rather than the last match. The change in `find_anon_types.rs` has the only affected test. I don't see this being an issue as the last occurrence isn't any better of a choice than the first.
Don't require specifying unrelated assoc types when trait alias is in `dyn` type
Object types must specify the associated types for all of the principal trait ref's supertraits. However, we weren't doing elaboration properly, so we incorrectly errored with erroneous suggestions to specify associated types that were unrelated to that principal trait ref. To fix this, use proper supertrait elaboration when expanding trait aliases in `conv_object_ty_poly_trait_ref`.
**NOTE**: Please use the ignore-whitespace option when reviewing. This only touches a handful of lines.
r? oli-obk or please feel free to reassign.
Fixes#122118
Apply `EarlyBinder` only to `TraitRef` in `ImplTraitHeader`
Resolves#121852
This PR
1. Moves `EarlyBinder` to `TraitRef` inside `ImplTraitHeader`,
2. Changes visibility of `coherence::builtin::check_trait` to `pub(super)` from `pub` as it seems not being re-exported from the `coherence` module.
silence mismatched types errors for implied projections
Currently, if a trait bound is not satisfied, then we suppress any errors for the trait's supertraits not being satisfied, but still report errors for super projections not being satisfied.
For example:
```rust
trait Super {
type Assoc;
}
trait Sub: Super<Assoc = ()> {}
```
Before this PR, if `T: Sub` is not satisfied, then errors for `T: Super` are suppressed, but errors for `<T as Super>::Assoc == ()` are still shown. This PR makes it so that errors about super projections not being satisfied are also suppressed.
The errors are only suppressed if the span of the trait obligation matches the span of the super predicate obligation to avoid silencing error that are not related. This PR removes some differences between the spans of supertraits and super projections to make the suppression work correctly.
This PR fixes the majority of the diagnostics fallout when making `Thin` a supertrait of `Sized` (in a future PR).
cc https://github.com/rust-lang/rust/pull/120354#issuecomment-1930585382
cc `@lcnr`
Rollup of 9 pull requests
Successful merges:
- #121065 (Add basic i18n guidance for `Display`)
- #121744 (Stop using Bubble in coherence and instead emulate it with an intercrate check)
- #121829 (Dummy tweaks (attempt 2))
- #121857 (Implement async closure signature deduction)
- #121894 (const_eval_select: make it safe but be careful with what we expose on stable for now)
- #122014 (Change some attributes to only_local.)
- #122016 (will_wake tests fail on Miri and that is expected)
- #122018 (only set noalias on Box with the global allocator)
- #122028 (Remove some dead code)
r? `@ghost`
`@rustbot` modify labels: rollup
Stop using Bubble in coherence and instead emulate it with an intercrate check
r? `````@compiler-errors`````
This change is kinda funny, because all I've done is reimplement `Bubble` behaviour for coherence without using `Bubble` explicitly.
Use root obligation on E0277 for some cases
When encountering trait bound errors that satisfy some heuristics that tell us that the relevant trait for the user comes from the root obligation and not the current obligation, we use the root predicate for the main message.
This allows to talk about "X doesn't implement Pattern<'_>" over the most specific case that just happened to fail, like "char doesn't implement Fn(&mut char)" in
`tests/ui/traits/suggest-dereferences/root-obligation.rs`
The heuristics are:
- the type of the leaf predicate is (roughly) the same as the type from the root predicate, as a proxy for "we care about the root"
- the leaf trait and the root trait are different, so as to avoid talking about `&mut T: Trait` and instead remain talking about `T: Trait` instead
- the root trait is not `Unsize`, as to avoid talking about it in `tests/ui/coercion/coerce-issue-49593-box-never.rs`.
```
error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied
--> $DIR/root-obligation.rs:6:38
|
LL | .filter(|c| "aeiou".contains(c))
| -------- ^ the trait `Fn<(char,)>` is not implemented for `&char`, which is required by `&char: Pattern<'_>`
| |
| required by a bound introduced by this call
|
= note: required for `&char` to implement `FnOnce<(char,)>`
= note: required for `&char` to implement `Pattern<'_>`
note: required by a bound in `core::str::<impl str>::contains`
--> $SRC_DIR/core/src/str/mod.rs:LL:COL
help: consider dereferencing here
|
LL | .filter(|c| "aeiou".contains(*c))
| +
```
Fix#79359, fix#119983, fix#118779, cc #118415 (the suggestion needs to change), cc #121398 (doesn't fix the underlying issue).
Properly deal with GATs when looking for method chains to point at
Fixes#121898.
~~While it prevents an ICE and the structured suggestion is correct, the method chain diagnostic notes are weird / useless / incorrect judging by a quick look. I guess I should improve that in this PR.~~ Sufficiently taken care of.
r? estebank or compiler-errors (#105332, #105674).
When encountering trait bound errors that satisfy some heuristics that
tell us that the relevant trait for the user comes from the root
obligation and not the current obligation, we use the root predicate for
the main message.
This allows to talk about "X doesn't implement Pattern<'_>" over the
most specific case that just happened to fail, like "char doesn't
implement Fn(&mut char)" in
`tests/ui/traits/suggest-dereferences/root-obligation.rs`
The heuristics are:
- the type of the leaf predicate is (roughly) the same as the type
from the root predicate, as a proxy for "we care about the root"
- the leaf trait and the root trait are different, so as to avoid
talking about `&mut T: Trait` and instead remain talking about
`T: Trait` instead
- the root trait is not `Unsize`, as to avoid talking about it in
`tests/ui/coercion/coerce-issue-49593-box-never.rs`.
```
error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied
--> $DIR/root-obligation.rs:6:38
|
LL | .filter(|c| "aeiou".contains(c))
| -------- ^ the trait `Fn<(char,)>` is not implemented for `&char`, which is required by `&char: Pattern<'_>`
| |
| required by a bound introduced by this call
|
= note: required for `&char` to implement `FnOnce<(char,)>`
= note: required for `&char` to implement `Pattern<'_>`
note: required by a bound in `core::str::<impl str>::contains`
--> $SRC_DIR/core/src/str/mod.rs:LL:COL
help: consider dereferencing here
|
LL | .filter(|c| "aeiou".contains(*c))
| +
```
Fix#79359, fix#119983, fix#118779, cc #118415 (the suggestion needs
to change).
Account for unmet T: !Copy in E0277 message
```
error[E0277]: the trait bound `T: !Copy` is not satisfied
--> $DIR/simple.rs:10:16
|
LL | not_copy::<T>();
| ^ the trait bound `T: !Copy` is not satisfied
```
instead of the current
```
error[E0277]: the trait bound `T: !Copy` is not satisfied
--> $DIR/simple.rs:10:16
|
LL | not_copy::<T>();
| ^ the trait `!Copy` is not implemented for `T`
```
Display short types for unimplemented trait
Shortens unimplemented trait diagnostics. Now shows:
```
error[E0277]: `Option<Option<Option<...>>>` doesn't implement `std::fmt::Display`
--> $DIR/on_unimplemented_long_types.rs:4:17
|
LL | pub fn foo() -> impl std::fmt::Display {
| ^^^^^^^^^^^^^^^^^^^^^^ `Option<Option<Option<...>>>` cannot be formatted with the default formatter
LL |
LL | / Some(Some(Some(Some(Some(Some(Some(Some(Some(S...
LL | | Some(Some(Some(Some(Some(Some(Some(Some(So...
LL | | Some(Some(Some(Some(Some(Some(Some(Som...
LL | | Some(Some(Some(Some(Some(Some(Some...
... |
LL | | ))))))))))),
LL | | )))))))))))
| |_______________- return type was inferred to be `Option<Option<Option<...>>>` here
|
= help: the trait `std::fmt::Display` is not implemented for `Option<Option<Option<...>>>`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.
```
I'm not 100% sure if this is desirable, or if we should just let the long types remain long. This is also kinda a short-term bandaid solution. The real long term solution is to properly migrate `rustc_trait_selection`'s error reporting to use translatable diagnostics and then properly handle type name printing.
Fixes#121687.
Never say "`Trait` is implemented for `{type error}`"
When a trait bound error occurs, we look for alternative types that would have made the bound succeed. For some reason `{type error}` sometimes would appear as a type that would do so.
We now remove `{type error}` from the list in every case to avoid nonsensical `note`s.
Combine `Sub` and `Equate`
Combine `Sub` and `Equate` into a new relation called `TypeRelating` (that name sounds familiar...)
Tracks the difference between `Sub` and `Equate` via `ambient_variance: ty::Variance` much like the `NllTypeRelating` relation, but implemented slightly jankier because it's a more general purpose relation.
r? lcnr
Add stubs in IR and ABI for `f16` and `f128`
This is the very first step toward the changes in https://github.com/rust-lang/rust/pull/114607 and the [`f16` and `f128` RFC](https://rust-lang.github.io/rfcs/3453-f16-and-f128.html). It adds the types to `rustc_type_ir::FloatTy` and `rustc_abi::Primitive`, and just propagates those out as `unimplemented!` stubs where necessary.
These types do not parse yet so there is no feature gate, and it should be okay to use `unimplemented!`.
The next steps will probably be AST support with parsing and the feature gate.
r? `@compiler-errors`
cc `@Nilstrieb` suggested breaking the PR up in https://github.com/rust-lang/rust/pull/120645#issuecomment-1925900572
When a trait bound error occurs, we look for alternative types that
would have made the bound succeed. For some reason `{type error}`
sometimes would appear as a type that would do so.
We now remove `{type error}` from the list in every case to avoid
nonsensical `note`s.
Safe Transmute: Revise safety analysis
This PR migrates `BikeshedIntrinsicFrom` to a simplified safety analysis (described [here](https://github.com/rust-lang/project-safe-transmute/issues/15)) that does not rely on analyzing the visibility of types and fields.
The revised analysis treats primitive types as safe, and user-defined types as potentially carrying safety invariants. If Rust gains explicit (un)safe fields, this PR is structured so that it will be fairly easy to thread support for those annotations into the analysis.
Notably, this PR removes the `Context` type parameter from `BikeshedIntrinsicFrom`. Most of the files changed by this PR are just UI tests tweaked to accommodate the removed parameter.
r? `@compiler-errors`
Count stashed errors again
Stashed diagnostics are such a pain. Their "might be emitted, might not" semantics messes with lots of things.
#120828 and #121206 made some big changes to how they work, improving some things, but still leaving some problems, as seen by the issues caused by #121206. This PR aims to fix all of them by restricting them in a way that eliminates the "might be emitted, might not" semantics while still allowing 98% of their benefit. Details in the individual commit logs.
r? `@oli-obk`
Fix `async Fn` confirmation for `FnDef`/`FnPtr`/`Closure` types
Fixes three issues:
1. The code in `extract_tupled_inputs_and_output_from_async_callable` was accidentally getting the *future* type and the *output* type (returned by the future) messed up for fnptr/fndef/closure types. :/
2. We have a (class of) bug(s) in the old solver where we don't really support higher ranked built-in `Future` goals for generators. This is not possible to hit on stable code, but [can be hit with `unboxed_closures`](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=e935de7181e37e13515ad01720bcb899) (#121653).
* I'm opting not to fix that in this PR. Instead, I just instantiate placeholders when confirming `async Fn` goals.
4. Fixed a bug when generating `FnPtr` shims for `async Fn` trait goals.
r? oli-obk
Deeply normalize obligations in `refining_impl_trait`
We somewhat awkwardly use semantic comparison when checking the `refining_impl_trait` lint. This relies on us being able to normalize bounds eagerly to avoid cases where an unnormalized alias is not considered equal to a normalized alias. Since `normalize` in the new solver is a noop, let's use `deeply_normalize` instead.
r? lcnr
cc ``@tmandry,`` this should fix your bug lol
Stashed errors used to be counted as errors, but could then be
cancelled, leading to `ErrorGuaranteed` soundness holes. #120828 changed
that, closing the soundness hole. But it introduced other difficulties
because you sometimes have to account for pending stashed errors when
making decisions about whether errors have occured/will occur and it's
easy to overlook these.
This commit aims for a middle ground.
- Stashed errors (not warnings) are counted immediately as emitted
errors, avoiding the possibility of forgetting to consider them.
- The ability to cancel (or downgrade) stashed errors is eliminated, by
disallowing the use of `steal_diagnostic` with errors, and introducing
the more restrictive methods `try_steal_{modify,replace}_and_emit_err`
that can be used instead.
Other things:
- `DiagnosticBuilder::stash` and `DiagCtxt::stash_diagnostic` now both
return `Option<ErrorGuaranteed>`, which enables the removal of two
`delayed_bug` calls and one `Ty::new_error_with_message` call. This is
possible because we store error guarantees in
`DiagCtxt::stashed_diagnostics`.
- Storing the guarantees also saves us having to maintain a counter.
- Calls to the `stashed_err_count` method are no longer necessary
alongside calls to `has_errors`, which is a nice simplification, and
eliminates two more `span_delayed_bug` calls and one FIXME comment.
- Tests are added for three of the four fixed PRs mentioned below.
- `issue-121108.rs`'s output improved slightly, omitting a non-useful
error message.
Fixes#121451.
Fixes#121477.
Fixes#121504.
Fixes#121508.
Add `StructurallyRelateAliases` to allow instantiating infer vars with rigid aliases.
Change `instantiate_query_response` to be infallible in the new solver. This requires canonicalization to not hide any information used by the query, so weaken
universe compression. It also modifies `term_is_fully_unconstrained` to allow
region inference variables in a higher universe.
Add newtypes for bool fields/params/return types
Fixed all the cases of this found with some simple searches for `*/ bool` and `bool /*`; probably many more
Rollup of 7 pull requests
Successful merges:
- #121435 (Account for RPITIT in E0310 explicit lifetime constraint suggestion)
- #121490 (Rustdoc: include crate name in links for local primitives)
- #121520 (delay cloning of iterator items)
- #121522 (check that simd_insert/extract indices are in-bounds)
- #121531 (Ignore less tests in debug builds)
- #121539 (compiler/rustc_target/src/spec/base/apple/tests.rs: Avoid unnecessary large move)
- #121542 (update stdarch)
r? `@ghost`
`@rustbot` modify labels: rollup
remove `sub_relations` from the `InferCtxt`
While doing so, I tried to remove the `delay_span_bug` in `rematch_impl` again, which lead me to discover another `freshen` bug, fixing that one in the second commit. See commit descriptions for the reasoning behind each change.
r? `@compiler-errors`
No need to `validate_alias_bound_self_from_param_env` in `assemble_alias_bound_candidates`
We already fully normalize the self type before we reach `assemble_alias_bound_candidates`, so there's no reason to double check that a projection is truly rigid by checking param-env bounds.
I think this is also blocked on us making sure to always normalize opaques: #120549.
r? lcnr
Without doing so we use the same candidate cache entry
for `?0: Trait<?1>` and `?0: Trait<?0>`. These goals are different
and we must not use the same entry for them.
we don't track them when canonicalizing or when freshening,
resulting in instable caching in the old solver, and issues when
instantiating query responses in the new one.
Make --verbose imply -Z write-long-types-to-disk=no
When shortening the type it is necessary to take into account the `--verbose` flag, if it is activated, we must always show the entire type and not write it in a file.
Fixes: https://github.com/rust-lang/rust/issues/119130
Convert `delayed_bug`s to `bug`s.
I have a suspicion that quite a few delayed bug paths are impossible to reach, so I did an experiment.
I converted every `delayed_bug` to a `bug`, ran the full test suite, then converted back every `bug` that was hit. A surprising number were never hit.
This is too dangerous to merge. Increased coverage (fuzzing or a crater run) would likely hit more cases. But it might be useful for people to look at and think about which paths are genuinely unreachable.
r? `@ghost`
I have a suspicion that quite a few delayed bug paths are impossible to
reach, so I did an experiment.
I converted every `delayed_bug` to a `bug`, ran the full test suite,
then converted back every `bug` that was hit. A surprising number were
never hit.
The next commit will convert some more back, based on human judgment.
Don't ICE when hitting overflow limit in fulfillment loop in next solver
As the title says, let's not ICE when hitting the overflow limit in fulfill. On the other hand, we don't want to treat these as true errors, since it means that whether something is considered a true error or an ambiguity is dependent on overflow handling in the solver, which seems not worth it.
Now that we use the presence of true errors in fulfillment for implicit negative coherence, we especially don't want to tie together coherence and overflow.
I guess I could also drain these errors out of fulfillment and put them into some `ambiguities` storage so we could return them in `select_all_or_error` without having to re-process them every time we call `select_where_possible`. Let me know if that's desired.
r? lcnr
Overhaul `Diagnostic` and `DiagnosticBuilder`
Implements the first part of https://github.com/rust-lang/compiler-team/issues/722, which moves functionality and use away from `Diagnostic`, onto `DiagnosticBuilder`.
Likely follow-ups:
- Move things around, because this PR was written to minimize diff size, so some things end up in sub-optimal places. E.g. `DiagnosticBuilder` has impls in both `diagnostic.rs` and `diagnostic_builder.rs`.
- Rename `Diagnostic` as `DiagInner` and `DiagnosticBuilder` as `Diag`.
r? `@davidtwco`
Drive-by `DUMMY_SP` -> `Span` and fmt changes
Noticed these while doing something else. There's no practical change, but it's preferable to use `DUMMY_SP` as little as possible, particularly when we have perfectlly useful `Span`s available.
Currently many diagnostic modifier methods are available on both
`Diagnostic` and `DiagnosticBuilder`. This commit removes most of them
from `Diagnostic`. To minimize the diff size, it keeps them within
`diagnostic.rs` but changes the surrounding `impl Diagnostic` block to
`impl DiagnosticBuilder`. (I intend to move things around later, to give
a more sensible code layout.)
`Diagnostic` keeps a few methods that it still needs, like `sub`,
`arg`, and `replace_args`.
The `forward!` macro, which defined two additional methods per call
(e.g. `note` and `with_note`), is replaced by the `with_fn!` macro,
which defines one additional method per call (e.g. `with_note`). It's
now also only used when necessary -- not all modifier methods currently
need a `with_*` form. (New ones can be easily added as necessary.)
All this also requires changing `trait AddToDiagnostic` so its methods
take `DiagnosticBuilder` instead of `Diagnostic`, which leads to many
mechanical changes. `SubdiagnosticMessageOp` gains a type parameter `G`.
There are three subdiagnostics -- `DelayedAtWithoutNewline`,
`DelayedAtWithNewline`, and `InvalidFlushedDelayedDiagnosticLevel` --
that are created within the diagnostics machinery and appended to
external diagnostics. These are handled at the `Diagnostic` level, which
means it's now hard to construct them via `derive(Diagnostic)`, so
instead we construct them by hand. This has no effect on what they look
like when printed.
There are lots of new `allow` markers for `untranslatable_diagnostics`
and `diagnostics_outside_of_impl`. This is because
`#[rustc_lint_diagnostics]` annotations were present on the `Diagnostic`
modifier methods, but missing from the `DiagnosticBuilder` modifier
methods. They're now present.
Noticed these while doing something else. There's no practical change, but it's preferable to use `DUMMY_SP` as little as possible, particularly when we have perfectlly useful `Span`s available.
There are lots of functions that modify a diagnostic. This can be via a
`&mut Diagnostic` or a `&mut DiagnosticBuilder`, because the latter type
wraps the former and impls `DerefMut`.
This commit converts all the `&mut Diagnostic` occurrences to `&mut
DiagnosticBuilder`. This is a step towards greatly simplifying
`Diagnostic`. Some of the relevant function are made generic, because
they deal with both errors and warnings. No function bodies are changed,
because all the modifier methods are available on both `Diagnostic` and
`DiagnosticBuilder`.
Use fulfillment in next trait solver coherence
Use fulfillment in the new trait solver's `impl_intersection_has_impossible_obligation` routine. This means that inference that falls out of processing other obligations can influence whether we can determine if an obligation is impossible to satisfy. See the committed test.
This should be completely sound, since evaluation and fulfillment both respect intercrate mode equally.
We run the risk of breaking coherence later if we were to change the rules of fulfillment and/or inference during coherence, but this is a problem which affects evaluation, as nested obligations from a trait goal are processed together and can influence each other in the same way.
r? lcnr
cc #114862
Also changed obligationctxt -> fulfillmentctxt because it feels kind of redundant to use an ocx here. I don't really care enough and can change it back if it really matters much.
errors: only eagerly translate subdiagnostics
Subdiagnostics don't need to be lazily translated, they can always be eagerly translated. Eager translation is slightly more complex as we need to have a `DiagCtxt` available to perform the translation, which involves slightly more threading of that context.
This slight increase in complexity should enable later simplifications - like passing `DiagCtxt` into `AddToDiagnostic` and moving Fluent messages into the diagnostic structs rather than having them in separate files (working on that was what led to this change).
r? ```@nnethercote```
Add and use a simple extension trait derive macro in the compiler
Adds `#[extension]` to `rustc_macros` for implementing an extension trait. This expands an impl (with an optional visibility) into two parallel trait + impl definitions.
before:
```rust
pub trait Extension {
fn a();
}
impl Extension for () {
fn a() {}
}
```
to:
```rust
#[extension]
pub impl Extension for () {
fn a() {}
}
```
Opted to just implement it by hand because I couldn't figure if there was a "canonical" choice of extension trait macro in the ecosystem. It's really lightweight anyways, and can always be changed.
I'm interested in adding this because I'd like to later split up the large `TypeErrCtxtExt` traits into several different files. This should make it one step easier.
Make `async Fn` trait kind errors better
1. Make it so that async closures with the wrong closurekind actually report a useful error
2. Explain why async closures can sometimes not implement `Fn`/`FnMut` (because they capture things)
r? oli-obk
Subdiagnostics don't need to be lazily translated, they can always be
eagerly translated. Eager translation is slightly more complex as we need
to have a `DiagCtxt` available to perform the translation, which involves
slightly more threading of that context.
This slight increase in complexity should enable later simplifications -
like passing `DiagCtxt` into `AddToDiagnostic` and moving Fluent messages
into the diagnostic structs rather than having them in separate files
(working on that was what led to this change).
Signed-off-by: David Wood <david@davidtw.co>
Do not report overflow errors on ConstArgHasType goals
This is 10% of a fix for #121090, since it at least means that we no longer mention the `ConstArgHasType` goal as the cause for the overflow. Instead, now we mention:
```
overflow evaluating the requirement `{closure@$DIR/overflow-during-mono.rs:13:41: 13:44}: Sized`
```
which is not much better, but slightly.
r? oli-obk
Continue compilation after check_mod_type_wf errors
The ICEs fixed here were probably reachable through const eval gymnastics before, but now they are easily reachable without that, too.
The new errors are often bugfixes, where useful errors were missing, because they were reported after the early abort. In other cases sometimes they are just duplication of already emitted errors, which won't be user-visible due to deduplication.
fixes https://github.com/rust-lang/rust/issues/120860
Use fewer delayed bugs.
For some cases where it's clear that an error has already occurred, e.g.:
- there's a comment stating exactly that, or
- things like HIR lowering, where we are lowering an error kind
The commit also tweaks some comments around delayed bug sites.
r? `@oli-obk`
Fix suggestion span for `?Sized` when param type has default
Fixes#120878
Diagnostic suggests adding `: ?Sized` in an incorrect place if a type parameter default is present
r? `@fmease`
For some cases where it's clear that an error has already occurred,
e.g.:
- there's a comment stating exactly that, or
- things like HIR lowering, where we are lowering an error kind
The commit also tweaks some comments around delayed bug sites.
`cargo update`
Run `cargo update`, with some pinning and fixes necessitated by that. This *should* unblock #112865
There's a couple of places where I only pinned a dependency in one location - this seems like a bit of a hack, but better than duplicating the FIXME across all `Cargo.toml` where a dependency is introduced.
cc `@Nilstrieb`
Ignore own item bounds in parent alias types in `for_each_item_bound`
Fixes#120912
I want to get a vibe check on this approach, which is very obviously a hack, but I believe something that is forwards-compatible with a more thorough solution and "good enough for now".
The problem here is that for a really deep rigid associated type, we are now repeatedly considering unrelated item bounds from the parent alias types, meaning we're doing a *lot* of extra work in the MIR inliner for deeply substituted rigid projections.
This feels intimately related to #107614. In that PR, we split *supertrait* bounds (bound which share the same `Self` type as the predicate which is being elaborated) and *implied* bounds (anything that is implied by elaborating the predicate).
The problem here is related to the fact that we don't maintain the split between these two for `item_bounds`. If we did, then when recursing into a parent alias type, we'd want to consider only the bounds that are given by [`PredicateFilter::All`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/astconv/enum.PredicateFilter.html#variant.SelfOnly) **except** those given by [`PredicateFilter::SelfOnly`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/astconv/enum.PredicateFilter.html#variant.SelfOnly).
Do not assemble candidates for default impls
There is no reason (as far as I can tell?) that we should assemble an impl candidate for a default impl. This candidate itself does not prove that the impl holds, and any time that it *does* hold, there will be a more specializing non-default impl that also is assembled.
This is because `default impl<T> Foo for T {}` actually expands to `impl<T> Foo for T where T: Foo {}`. The only way to satisfy that where clause (without coinduction) is via *another* implementation that does hold -- precisely an impl that specializes it.
This should fix the specialization related regressions for #116494. That should lead to one root crate regression that doesn't have to do with specialization, which I think we can regress.
r? lcnr cc ``@rust-lang/types``
cc #31844
modify alias-relate to also normalize ambiguous opaques
allows a bunch of further cleanups and generally simplifies the type system. To handle https://github.com/rust-lang/trait-system-refactor-initiative/issues/8 we'll have to add a some additional complexity to the `(Alias, Infer)` branches in alias-relate, so removing the opaque type special case here is really valuable.
It does worsen `deduce_closure_signature` and friends even more as they now receive an inference variable which is only constrained via an `AliasRelate` goal. These probably have to look into alias relate goals somehow. Leaving that for a future PR as this is something we'll have to tackle regardless.
r? `@compiler-errors`
Merge `impl_polarity` and `impl_trait_ref` queries
Hopefully this is perf neutral. I want to finish https://github.com/rust-lang/rust/pull/120835 and stop using the HIR in `coherent_trait`, which should then give us a perf improvement.