Accurately refer to assoc fn without receiver as assoc fn instead of methods.
Add `AssocItem::descr` method to centralize where we call methods and associated functions.
turn `invalid_type_param_default` into a `FutureReleaseErrorReportInDeps`
`````@rust-lang/types````` I assume the plan is still to disallow this? It has been a future-compat lint for a long time, seems ripe to go for hard error.
However, turns out that outright removing it right now would lead to [tons of crater regressions](https://github.com/rust-lang/rust/pull/127655#issuecomment-2228285460), so for now this PR just makes this future-compat lint show up in cargo's reports, so people are warned when they use a dependency that is affected by this.
Fixes https://github.com/rust-lang/rust/issues/27336 by removing the feature gate (so there's no way to silence the lint even on nightly)
CC https://github.com/rust-lang/rust/issues/36887
Reorder trait bound modifiers *after* `for<...>` binder in trait bounds
This PR suggests changing the grammar of trait bounds from:
```
[CONSTNESS] [ASYNCNESS] [?] [BINDER] [TRAIT_PATH]
const async ? for<'a> Sized
```
to
```
([BINDER] [CONSTNESS] [ASYNCNESS] | [?]) [TRAIT_PATH]
```
i.e., either
```
? Sized
```
or
```
for<'a> const async Sized
```
(but not both)
### Why?
I think it's strange that the binder applies "more tightly" than the `?` trait polarity. This becomes even weirder when considering that we (or at least, I) want to have `async` trait bounds expressed like:
```
where T: for<'a> async Fn(&'a ()) -> i32,
```
and not:
```
where T: async for<'a> Fn(&'a ()) -> i32,
```
### Fallout
No crates on crater use this syntax, presumably because it's literally useless. This will require modifying the reference grammar, though.
### Alternatives
If this is not desirable, then we can alternatively keep parsing `for<'a>` after the `?` but deprecate it with either an FCW (or an immediate hard error), and begin parsing `for<'a>` *before* the `?`.
Do not try to reveal hidden types when trying to prove auto-traits in the defining scope
fixes#99793
this avoids the cycle error by just causing a selection error, which is not fatal. We pessimistically assume that freeze does not hold, which is always a safe assumption.
Forbid borrows and unsized types from being used as the type of a const generic under `adt_const_params`
Fixes#112219Fixes#112124Fixes#112125
### Motivation
Currently the `adt_const_params` feature allows writing `Foo<const N: [u8]>` this is entirely useless as it is not possible to write an expression which evaluates to a type that is not `Sized`. In order to actually use unsized types in const generics they are typically written as `const N: &[u8]` which *is* possible to provide a value of.
Unfortunately allowing the types of const parameters to contain references is non trivial (#120961) as it introduces a number of difficult questions about how equality of references in the type system should behave. References in the types of const generics is largely only useful for using unsized types in const generics.
This PR introduces a new feature gate `unsized_const_parameters` and moves support for `const N: [u8]` and `const N: &...` from `adt_const_params` into it. The goal here hopefully is to experiment with allowing `const N: [u8]` to work without references and then eventually completely forbid references in const generics.
Splitting this out into a new feature gate means that stabilization of `adt_const_params` does not have to resolve#120961 which is the only remaining "big" blocker for the feature. Remaining issues after this are a few ICEs and naming bikeshed for `ConstParamTy`.
### Implementation
The implementation is slightly subtle here as we would like to ensure that a stabilization of `adt_const_params` is forwards compatible with any outcome of `unsized_const_parameters`. This is inherently tricky as we do not support unstable trait implementations and we determine whether a type is valid as the type of a const parameter via a trait bound.
There are a few constraints here:
- We would like to *allow for the possibility* of adding a `Sized` supertrait to `ConstParamTy` in the event that we wind up opting to not support unsized types and instead requiring people to write the 'sized version', e.g. `const N: [u8; M]` instead of `const N: [u8]`.
- Crates should be able to enable `unsized_const_parameters` and write trait implementations of `ConstParamTy` for `!Sized` types without downstream crates that only enable `adt_const_params` being able to observe this (required for std to be able to `impl<T> ConstParamTy for [T]`
Ultimately the way this is accomplished is via having two traits (sad), `ConstParamTy` and `UnsizedConstParamTy`. Depending on whether `unsized_const_parameters` is enabled or not we change which trait is used to check whether a type is allowed to be a const parameter.
Long term (when stabilizing `UnsizedConstParamTy`) it should be possible to completely merge these traits (and derive macros), only having a single `trait ConstParamTy` and `macro ConstParamTy`.
Under `adt_const_params` it is now illegal to directly refer to `ConstParamTy` it is only used as an internal impl detail by `derive(ConstParamTy)` and checking const parameters are well formed. This is necessary in order to ensure forwards compatibility with all possible future directions for `feature(unsized_const_parameters)`.
Generally the intuition here should be that `ConstParamTy` is the stable trait that everything uses, and `UnsizedConstParamTy` is that plus unstable implementations (well, I suppose `ConstParamTy` isn't stable yet :P).
When encountering `-> Trait`, suggest `-> Box<dyn Trait>` (instead of `-> Box<Trait>`.
If there's a single returned type within the `fn`, suggest `-> impl Trait`.
Fix precise capturing suggestion for hidden regions when we have APITs
Suggests to turn APITs into type parameters so they can be named in precise capturing syntax for hidden type lifetime errors. We also note that it may change the API.
This is currently done via a note *and* a suggestion, which feels a bit redundant, but I wasn't totally sure of a better alternative for the presentation.
Code is kind of a mess but there's a lot of cases to consider. Happy to iterate on this if you think the approach is too messy.
Based on #127619, only the last commit is relevant.
r? oli-obk
Tracking:
- https://github.com/rust-lang/rust/issues/123432
Make parse error suggestions verbose and fix spans
Go over all structured parser suggestions and make them verbose style.
When suggesting to add or remove delimiters, turn them into multiple suggestion parts.
Suggest using precise capturing for hidden type that captures region
Adjusts the "add `+ '_`" suggestion for opaques to instead suggest adding or reusing the `+ use<>` in the opaque.
r? oli-obk or please re-roll if you're busy!
Go over all structured parser suggestions and make them verbose style.
When suggesting to add or remove delimiters, turn them into multiple suggestion parts.
Avoid follow-up errors and ICEs after missing lifetime errors on data structures
Tuple struct constructors are functions, so when we call them typeck will use the signature tuple struct constructor function to provide type hints. Since typeck mostly ignores and erases lifetimes, we end up never seeing the error lifetime in writeback, thus not tainting the typeck result.
Now, we eagerly taint typeck results by tainting from `resolve_vars_if_possible`, which is called all over the place.
I did not carry over all the `crashes` test suite tests, as they are really all the same cause (missing or unknown lifetime names in tuple struct definitions or generic arg lists).
fixes#124262fixes#124083fixes#125155fixes#125888fixes#125992fixes#126666fixes#126648fixes#127268fixes#127266fixes#127304
Make `can_eq` process obligations (almost) everywhere
Move `can_eq` to an extension trait on `InferCtxt` in `rustc_trait_selection`, and change it so that it processes obligations. This should strengthen it to be more accurate in some cases, but is most important for the new trait solver which delays relating aliases to `AliasRelate` goals. Without this, we always basically just return true when passing aliases to `can_eq`, which can lead to weird errors, for example #127149.
I'm not actually certain if we should *have* `can_eq` be called on the good path. In cases where we need `can_eq`, we probably should just be using a regular probe.
Fixes#127149
r? lcnr
Don't try to label `ObligationCauseCode::CompareImplItem` for an RPITIT, since it has no name
The old (current) trait solver has a limitation that when a where clause in param-env must be normalized using the same where clause, then we get spurious errors in `normalize_param_env_or_error`. I don't think there's an issue tracking it, but it's the root cause for many of the "fixed-by-next-solver" labeled issues.
Specifically, these errors may occur when checking predicate entailment of the GAT that comes out of desugaring RPITITs. Since we use `ObligationCauseCode::CompareImplItem` for these predicates, we try calling `item_name` on an RPITIT which fails, since the RPITIT has no name.
We simply suppress this logic when we're reporting a predicate entailment error for an RPITIT. RPITITs should never have predicate entailment errors, *by construction*, but they may due to this bug in the old solver.
Addresses the ICE in #127331, though doesn't fix the underlying issue (which is fundamental to the old solver).
r? types
Improve dead code analysis
Fixes#120770
1. check impl items later if self ty is private although the trait method is public, cause we must use the ty firstly if it's private
2. mark the adt live if it appears in pattern, like generic argument, this implies the use of the adt
3. based on the above, we can handle the case that private adts impl Default, so that we don't need adding rustc_trivial_field_reads on Default, and the logic in should_ignore_item
r? ``@pnkfelix``
Automatically taint InferCtxt when errors are emitted
r? `@nnethercote`
Basically `InferCtxt::dcx` now returns a `DiagCtxt` that refers back to the `Cell<Option<ErrorGuaranteed>>` of the `InferCtxt` and thus when invoking `Diag::emit`, and the diagnostic is an error, we taint the `InferCtxt` directly.
That change on its own has no effect at all, because `InferCtxt` already tracks whether errors have been emitted by recording the global error count when it gets opened, and checking at the end whether the count changed. So I removed that error count check, which had a bit of fallout that I immediately fixed by invoking `InferCtxt::dcx` instead of `TyCtxt::dcx` in a bunch of places.
The remaining new errors are because an error was reported in another query, and never bubbled up. I think they are minor enough for this to be ok, and sometimes it actually improves diagnostics, by not silencing useful diagnostics anymore.
fixes#126485 (cc `@olafes)`
There are more improvements we can do (like tainting in hir ty lowering), but I would rather do that in follow up PRs, because it requires some refactorings.
Move binder and polarity parsing into `parse_generic_ty_bound`
Let's pull out the parts of #127054 which just:
1. Make the parsing code less confusing
2. Fix `?use<>` (to correctly be denied)
3. Improve `T: for<'a> 'a` diagnostics
This should have no user-facing effects on stable parsing.
r? fmease
Don't ICE during RPITIT refinement checking for resolution errors after normalization
#126670 shows a case where resolution errors after normalization can happen during RPITIT refinement checking. Our tests didn't reach this path before, and we explicitly ICEd until we had a test. We can now delay a bug since we're sure it is reachable and have the test from the isue.
The comment I added likely still needs more expert wordsmithing.
r? ``@compiler-errors`` who's making me work during vacation (j/k).
Fixes#126670
Deny `use<>` for RPITITs
Precise capturing `use<>` syntax is currently a no-op on RPITITs, since GATs have no variance, so all captured lifetimes are captured invariantly.
We don't currently *need* to support `use<>` on RPITITs, since `use<>` is initially intended for migrating RPIT *overcaptures* from edition 2021->2024, but since RPITITs currently capture all in-scope lifetimes, we'll never need to write `use<>` on an RPITIT.
Eventually, though, it would be desirable to support precise capturing on RPITITs, since RPITITs overcapturing by default can be annoying to some folks. But let's separate that (which will likely require some delicate types team work for adding variances to GATs and adjusting the refinement rules) from the stabilization of the feature for edition 2024.
r? oli-obk cc ``@traviscross``
Tracking:
- https://github.com/rust-lang/rust/issues/123432
Allow constraining opaque types during various unsizing casts
allows unsizing of tuples, arrays and Adts to constraint opaque types in their generic parameters to concrete types on either side of the unsizing cast.
Also allows constraining opaque types during trait object casts that only differ in auto traits or lifetimes.
cc #116652
Actually taint InferCtxt when a fulfillment error is emitted
And avoid checking the global error counter
fixes#122044fixes#123255fixes#123276fixes#125799
Spell out other trait diagnostic
I recently saw somebody confused about the diagnostic thinking it was suggesting to add an `as` cast. This change is longer but I think it's clearer
Silence follow-up errors directly based on error types and regions
During type_of, we used to just return an error type if there were any errors encountered. This is problematic, because it means a struct declared as `struct Foo<'static>` will end up not finding any inherent or trait impls because those impl blocks' `Self` type will be `{type error}` instead of `Foo<'re_error>`. Now it's the latter, silencing nonsensical follow-up errors about `Foo` not having any methods.
Unfortunately that now allows for new follow-up errors, because borrowck treats `'re_error` as `'static`, causing nonsensical errors about non-error lifetimes not outliving `'static`. So what I also did was to just strip all outlives bounds that borrowck found, thus never letting it check them. There are probably more nuanced ways to do this, but I worried there would be other nonsensical errors if some outlives bounds were missing. Also from the test changes, it looked like an improvement everywhere.
Always use the `Fn(T) -> R` format when printing closure traits instead of `Fn<(T,), Output = R>`.
Fix#67100:
```
error[E0277]: expected a `Fn()` closure, found `F`
--> file.rs:6:13
|
6 | call_fn(f)
| ------- ^ expected an `Fn()` closure, found `F`
| |
| required by a bound introduced by this call
|
= note: wrap the `F` in a closure with no arguments: `|| { /* code */ }`
note: required by a bound in `call_fn`
--> file.rs:1:15
|
1 | fn call_fn<F: Fn() -> ()>(f: &F) {
| ^^^^^^^^^^ required by this bound in `call_fn`
help: consider further restricting this bound
|
5 | fn call_any<F: std::any::Any + Fn()>(f: &F) {
| ++++++
```
We already handle this case this way on the coherence side, and it matches the new solver's behaviour. While there is some breakage around type-alias-impl-trait (see new "type annotations needed" in tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs), no stable code breaks, and no new stable code is accepted.
Don't fatal when calling `expect_one_of` when recovering arg in `parse_seq`
In `parse_seq`, when parsing a sequence of token-separated items, if we don't see a separator, we try to parse another item eagerly in order to give a good diagnostic and recover from a missing separator:
d1a0fa5ed3/compiler/rustc_parse/src/parser/mod.rs (L900-L901)
If parsing the item itself calls `expect_one_of`, then we will fatal because of #58903:
d1a0fa5ed3/compiler/rustc_parse/src/parser/mod.rs (L513-L516)
For `precise_capturing` feature I implemented, we do end up calling `expected_one_of`:
d1a0fa5ed3/compiler/rustc_parse/src/parser/ty.rs (L712-L714)
This leads the compiler to fatal *before* having emitted the first error, leading to absolutely no useful information for the user about what happened in the parser.
This PR makes it so that we stop doing that.
Fixes#124195
fix normalizing in different `ParamEnv`s with the same `InferCtxt`
This PR changes the key of the projection cache from just `AliasTy` to `(AliasTy, ParamEnv)` to allow normalizing in different `ParamEnv`s without resetting caches. Previously, normalizing the same alias in different param envs would always reuse the cached result from the first normalization, which is incorrect if the projection clauses in the param env have changed.
Fixing this bug allows us to get rid of `InferCtxt::clear_caches`, which was only used by the `AutoTraitFinder`, because it requires normalizing in different param envs.
r? `@fmease`
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
Split an item bounds and an item's super predicates
This is the moral equivalent of #107614, but instead for predicates this applies to **item bounds**. This PR splits out the item bounds (i.e. *all* predicates that are assumed to hold for the alias) from the item *super predicates*, which are the subset of item bounds which share the same self type as the alias.
## Why?
Much like #107614, there are places in the compiler where we *only* care about super-predicates, and considering predicates that possibly don't have anything to do with the alias is problematic. This includes things like closure signature inference (which is at its core searching for `Self: Fn(..)` style bounds), but also lints like `#[must_use]`, error reporting for aliases, computing type outlives predicates.
Even in cases where considering all of the `item_bounds` doesn't lead to bugs, unnecessarily considering irrelevant bounds does lead to a regression (#121121) due to doing extra work in the solver.
## Example 1 - Trait Aliases
This is best explored via an example:
```
type TAIT<T> = impl TraitAlias<T>;
trait TraitAlias<T> = A + B where T: C;
```
The item bounds list for `Tait<T>` will include:
* `Tait<T>: A`
* `Tait<T>: B`
* `T: C`
While `item_super_predicates` query will include just the first two predicates.
Side-note: You may wonder why `T: C` is included in the item bounds for `TAIT`? This is because when we elaborate `TraitAlias<T>`, we will also elaborate all the predicates on the trait.
## Example 2 - Associated Type Bounds
```
type TAIT<T> = impl Iterator<Item: A>;
```
The `item_bounds` list for `TAIT<T>` will include:
* `Tait<T>: Iterator`
* `<Tait<T> as Iterator>::Item: A`
But the `item_super_predicates` will just include the first bound, since that's the only bound that is relevant to the *alias* itself.
## So what
This leads to some diagnostics duplication just like #107614, but none of it will be user-facing. We only see it in the UI test suite because we explicitly disable diagnostic deduplication.
Regarding naming, I went with `super_predicates` kind of arbitrarily; this can easily be changed, but I'd consider better names as long as we don't block this PR in perpetuity.
misc cleanups from debugging something
rename `instantiate_canonical_with_fresh_inference_vars` to `instantiate_canonical` the substs for the canonical are not solely infer vars as that would be wildly wrong and it is rather confusing to see this method called and think that the entire canonicalization setup is completely broken when it is not 👍
also update region debug printing to be more like the custom impls for Ty/Const, right now regions in debug output are horribly verbose and make it incredibly hard to read but with this atleast boundvars and placeholders when debugging the new solver do not take up excessive amounts of space.
r? `@lcnr`
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
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.
Split refining_impl_trait lint into _reachable, _internal variants
As discussed in https://github.com/rust-lang/rust/issues/119535#issuecomment-1909352040:
> We discussed this today in triage and developed a consensus to:
>
> * Add a separate lint against impls that refine a return type defined with RPITIT even when the trait is not crate public.
> * Place that in a lint group along with the analogous crate public lint.
> * Create an issue to solicit feedback on these lints (or perhaps two separate ones).
> * Have the warnings displayed with each lint reference this issue in a similar manner to how we do that today with the required `Self: '0'` bound on GATs.
> * Make a note to review this feedback on 2-3 release cycles.
This points users to https://github.com/rust-lang/rust/issues/121718 to leave feedback.
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
Make `DefiningAnchor::Bind` only store the opaque types that may be constrained, instead of the current infcx root item.
This makes `Bind` almost always be empty, so we can start forwarding it to queries, allowing us to remove `Bubble` entirely (not done in this PR)
The only behaviour change is in diagnostics.
r? `@lcnr` `@compiler-errors`
Don't ICE if we collect no RPITITs unless there are no unification errors
Move an assertion in `collect_return_position_impl_trait_in_trait_tys` to after the `ObligationCtxt::eq` calls, so that we only assert and ICE if we have unification errors.
Fixes#121468
Uplift some feeding out of `associated_type_for_impl_trait_in_impl` and into queries
This PR moves the `type_of` and `generics_of` query feeding out of `associated_type_for_impl_trait_in_impl`, since eagerly feeding results in query cycles due to a subtle interaction with `resolve_bound_vars`.
Fixes#122019
r? spastorino
stricter hidden type wf-check [based on #115008]
Original work by `@aliemjay` in #115008. A huge thanks to them for originally figuring out this approach ❤️
Fixes https://github.com/rust-lang/rust/issues/114728
Fixes https://github.com/rust-lang/rust/issues/114572
Instead of adding the `WellFormed` obligations when relating opaque types, we now always emit such an obligation when defining the hidden type.
This causes nested opaque types which aren't wf to error, see the comment below for the described impact. I believe this change to be desirable as it significantly reduces complexity by removing special-cases.
It also caused an issue with RPITIT: in defaulted trait methods, we add a `Projection(synthetic_assoc, rpit_of_trait_method)` clause to the `param_env`. This clause is not added to the `ParamEnv` of the nested coroutines. This caused a normalization failure in `fn check_coroutine_obligations` with the new solver. I fixed that by using the env of the typeck root instead.
r? `@oli-obk`
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).
Now that inlining, mir validation and const eval all use reveal-all, we won't be constraining hidden types here anymore
r? `@compiler-errors`
one bubble down, two more to go
the test is unrelated, just something I noticed would be good to test in both the old solver and the new.
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`
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.
Account for RPITIT in E0310 explicit lifetime constraint suggestion
When given
```rust
trait Original {
fn f() -> impl Fn();
}
trait Erased {
fn f(&self) -> Box<dyn Fn()>;
}
impl<T: Original> Erased for T {
fn f(&self) -> Box<dyn Fn()> {
Box::new(<T as Original>::f())
}
}
```
emit do not emit an invalid suggestion restricting the `Trait::{opaque}` type in a `where` clause:
```
error[E0310]: the associated type `<T as Original>::{opaque#0}` may not live long enough
--> $DIR/missing-static-bound-from-impl.rs:11:9
|
LL | Box::new(<T as Original>::f())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| the associated type `<T as Original>::{opaque#0}` must be valid for the static lifetime...
| ...so that the type `impl Fn()` will meet its required lifetime bounds
```
Partially address #119773. Ideally we'd suggest modifying `Erased::f` instead.
r? `@compiler-errors`
Fix more #121208 fallout
#121208 converted lots of delayed bugs to bugs. Unsurprisingly, there were a few invalid conversion found via fuzzing.
r? `@lcnr`
Provide suggestions through `rustc_confusables` annotations
Help with common API confusion, like asking for `push` when the data structure really has `append`.
```
error[E0599]: no method named `size` found for struct `Vec<{integer}>` in the current scope
--> $DIR/rustc_confusables_std_cases.rs:17:7
|
LL | x.size();
| ^^^^
|
help: you might have meant to use `len`
|
LL | x.len();
| ~~~
help: there is a method with a similar name
|
LL | x.resize();
| ~~~~~~
```
Fix#59450 (we can open subsequent tickets for specific cases).
Fix#108437:
```
error[E0599]: `Option<{integer}>` is not an iterator
--> f101.rs:3:9
|
3 | opt.flat_map(|val| Some(val));
| ^^^^^^^^ `Option<{integer}>` is not an iterator
|
::: /home/gh-estebank/rust/library/core/src/option.rs:571:1
|
571 | pub enum Option<T> {
| ------------------ doesn't satisfy `Option<{integer}>: Iterator`
|
= note: the following trait bounds were not satisfied:
`Option<{integer}>: Iterator`
which is required by `&mut Option<{integer}>: Iterator`
help: you might have meant to use `and_then`
|
3 | opt.and_then(|val| Some(val));
| ~~~~~~~~
```
On type error of method call arguments, look at confusables for suggestion. Fix#87212:
```
error[E0308]: mismatched types
--> f101.rs:8:18
|
8 | stuff.append(Thing);
| ------ ^^^^^ expected `&mut Vec<Thing>`, found `Thing`
| |
| arguments to this method are incorrect
|
= note: expected mutable reference `&mut Vec<Thing>`
found struct `Thing`
note: method defined here
--> /home/gh-estebank/rust/library/alloc/src/vec/mod.rs:2025:12
|
2025 | pub fn append(&mut self, other: &mut Self) {
| ^^^^^^
help: you might have meant to use `push`
|
8 | stuff.push(Thing);
| ~~~~
```
When given
```rust
trait Original {
fn f() -> impl Fn();
}
trait Erased {
fn f(&self) -> Box<dyn Fn()>;
}
impl<T: Original> Erased for T {
fn f(&self) -> Box<dyn Fn()> {
Box::new(<T as Original>::f())
}
}
```
avoid suggestion to restrict the `Trait::{opaque}` type in a `where` clause:
```
error[E0310]: the associated type `<T as Original>::{opaque#0}` may not live long enough
--> $DIR/missing-static-bound-from-impl.rs:11:9
|
LL | Box::new(<T as Original>::f())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| the associated type `<T as Original>::{opaque#0}` must be valid for the static lifetime...
| ...so that the type `impl Fn()` will meet its required lifetime bounds
```
CC #119773.
Do not provide a structured suggestion when the arguments don't match.
```
error[E0599]: no method named `test_mut` found for struct `Vec<{integer}>` in the current scope
--> $DIR/auto-ref-slice-plus-ref.rs:7:7
|
LL | a.test_mut();
| ^^^^^^^^
|
= help: items from traits can only be used if the trait is implemented and in scope
note: `MyIter` defines an item `test_mut`, perhaps you need to implement it
--> $DIR/auto-ref-slice-plus-ref.rs:14:1
|
LL | trait MyIter {
| ^^^^^^^^^^^^
help: there is a method `get_mut` with a similar name, but with different arguments
--> $SRC_DIR/core/src/slice/mod.rs:LL:COL
```
Consider methods beyond inherent ones when suggesting typos.
```
error[E0599]: no method named `owned` found for reference `&dyn Foo` in the current scope
--> $DIR/object-pointer-types.rs:11:7
|
LL | fn owned(self: Box<Self>);
| --------- the method might not be found because of this arbitrary self type
...
LL | x.owned();
| ^^^^^ help: there is a method with a similar name: `to_owned`
```
Fix#101013.
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.