Remove special-casing around `AliasKind::Opaque` when structurally resolving in new solver
This fixes a few inconsistencies around where we don't eagerly resolve opaques to their (locally-defined) hidden types in the new solver. It essentially allows this code to work:
```rust
fn main() {
type Tait = impl Sized;
struct S {
i: i32,
}
let x: Tait = S { i: 0 };
println!("{}", x.i);
}
```
Since `Tait` is defined in `main`, we are able to poke through the type of `x` with deref.
r? lcnr
Errors in `DiagCtxtInner::emit_diagnostic` are never set to
`Level::Bug`, because the condition never succeeds, because
`self.treat_err_as_bug()` is called *before* the error counts are
incremented.
This commit switches to `self.treat_next_err_as_bug()`, fixing the
problem. This changes the error message output to actually say "internal
compiler error".
Add regression test for #106630
This PR adds a regression test for #106630. I was unsure where exactly to place the test or how to test it locally so please let me know if I should change something.
On borrow return type, suggest borrowing from arg or owned return type
When we encounter a function with a return type that has an anonymous lifetime with no argument to borrow from, besides suggesting the `'static` lifetime we now also suggest changing the arguments to be borrows or changing the return type to be an owned type.
```
error[E0106]: missing lifetime specifier
--> $DIR/variadic-ffi-6.rs:7:6
|
LL | ) -> &usize {
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
LL | ) -> &'static usize {
| +++++++
help: instead, you are more likely to want to change one of the arguments to be borrowed...
|
LL | x: &usize,
| +
help: ...or alternatively, to want to return an owned value
|
LL - ) -> &usize {
LL + ) -> usize {
|
```
Fix#85843.
When we encounter a function with a return type that has an anonymous
lifetime with no argument to borrow from, besides suggesting the
`'static` lifetime we now also suggest changing the arguments to be
borrows or changing the return type to be an owned type.
```
error[E0106]: missing lifetime specifier
--> $DIR/variadic-ffi-6.rs:7:6
|
LL | ) -> &usize {
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
LL | ) -> &'static usize {
| +++++++
help: instead, you are more likely to want to change one of the arguments to be borrowed...
|
LL | x: &usize,
| +
help: ...or alternatively, to want to return an owned value
|
LL - ) -> &usize {
LL + ) -> usize {
|
```
Fix#85843.
new solver normalization improvements
cool beans
At the core of this PR is a `try_normalize_ty` which stops for rigid aliases by using `commit_if_ok`.
Reworks alias-relate to fully normalize both the lhs and rhs and then equate the resulting rigid (or inference) types. This fixes https://github.com/rust-lang/trait-system-refactor-initiative/issues/68 by avoiding the exponential blowup. Also supersedes #116369 by only defining opaque types if the hidden type is rigid.
I removed the stability check in `EvalCtxt::evaluate_goal` due to https://github.com/rust-lang/trait-system-refactor-initiative/issues/75. While I personally have opinions on how to fix it, that still requires further t-types/`@nikomatsakis` buy-in, so I removed that for now. Once we've decided on our approach there, we can revert this commit.
r? `@compiler-errors`
Fix depth check in ProofTreeVisitor.
The hack to cutoff overflows and cycles in the new trait solver was incorrect. We want to inspect everything with depth [0..10].
This fix exposed a previously unseen bug, which caused the compiler to ICE when invoking `trait_ref` on a non-assoc type projection. I simply added the guard in the `AmbiguityCausesVisitor`, and updated the expected output for the `auto-trait-coherence` test which now includes the extra note:
```text
|
= note: upstream crates may add a new impl of trait `std::marker::Send` for type `OpaqueType` in future versions
```
r? `@lcnr`
When we encounter a `dyn Trait` that isn't object safe, look for its
implementors. If there's one, mention using it directly If there are
less than 9, mention the possibility of creating a new enum and using
that instead.
Account for object unsafe `impl Trait on dyn Trait {}`. Make a
distinction between public and sealed traits.
Fix#80194.
Consider alias bounds when computing liveness in NLL (but this time sound hopefully)
This is a revival of #116040, except removing the changes to opaque lifetime captures check to make sure that we're not triggering any unsoundness due to the lack of general existential regions and the currently-existing `ReErased` hack we use instead.
r? `@aliemjay` -- I appreciate you pointing out the unsoundenss in the previous iteration of this PR, and I'd like to hear that you're happy with this iteration of this PR before this goes back into FCP :>
Fixes#116794 as well
---
(mostly copied from #116040 and reworked slightly)
# Background
Right now, liveness analysis in NLL is a bit simplistic. It simply walks through all of the regions of a type and marks them as being live at points. This is problematic in the case of aliases, since it requires that we mark **all** of the regions in their args[^1] as live, leading to bugs like #42940.
In reality, we may be able to deduce that fewer regions are allowed to be present in the projected type (or "hidden type" for opaques) via item bounds or where clauses, and therefore ideally, we should be able to soundly require fewer regions to be live in the alias.
For example:
```rust
trait Captures<'a> {}
impl<T> Captures<'_> for T {}
fn capture<'o>(_: &'o mut ()) -> impl Sized + Captures<'o> + 'static {}
fn test_two_mut(mut x: ()) {
let _f1 = capture(&mut x);
let _f2 = capture(&mut x);
//~^ ERROR cannot borrow `x` as mutable more than once at a time
}
```
In the example above, we should be able to deduce from the `'static` bound on `capture`'s opaque that even though `'o` is a captured region, it *can never* show up in the opaque's hidden type, and can soundly be ignored for liveness purposes.
# The Fix
We apply a simple version of RFC 1214's `OutlivesProjectionEnv` and `OutlivesProjectionTraitDef` rules to NLL's `make_all_regions_live` computation.
Specifically, when we encounter an alias type, we:
1. Look for a unique outlives bound in the param-env or item bounds for that alias. If there is more than one unique region, bail, unless any of the outlives bound's regions is `'static`, and in that case, prefer `'static`. If we find such a unique region, we can mark that outlives region as live and skip walking through the args of the opaque.
2. Otherwise, walk through the alias's args recursively, as we do today.
## Limitation: Multiple choices
This approach has some limitations. Firstly, since liveness doesn't use the same type-test logic as outlives bounds do, we can't really try several options when we're faced with a choice.
If we encounter two unique outlives regions in the param-env or bounds, we simply fall back to walking the opaque via its args. I expect this to be mostly mitigated by the special treatment of `'static`, and can be fixed in a forwards-compatible by a more sophisticated analysis in the future.
## Limitation: Opaque hidden types
Secondly, we do not employ any of these rules when considering whether the regions captured by a hidden type are valid. That causes this code (cc #42940) to fail:
```rust
trait Captures<'a> {}
impl<T> Captures<'_> for T {}
fn a() -> impl Sized + 'static {
b(&vec![])
}
fn b<'o>(_: &'o Vec<i32>) -> impl Sized + Captures<'o> + 'static {}
```
We need to have existential regions to avoid [unsoundness](https://github.com/rust-lang/rust/pull/116040#issuecomment-1751628189) when an opaque captures a region which is not represented in its own substs but which outlives a region that does.
## Read more
Context: https://github.com/rust-lang/rust/pull/115822#issuecomment-1731153952 (for the liveness case)
More context: https://github.com/rust-lang/rust/issues/42940#issuecomment-455198309 (for the opaque capture case, which this does not fix)
[^1]: except for bivariant region args in opaques, which will become less relevant when we move onto edition 2024 capture semantics for opaques.
Stash and cancel cycle errors for auto trait leakage in opaques
We don't need to emit a traditional cycle error when we have a selection error that explains what's going on but in more detail.
We may want to augment this error to actually point out the cycle, now that the cycle error is not being emitted. We could do that by storing the set of opaques that was in the `CyclePlaceholder` that gets returned from `type_of_opaque`.
r? `@oli-obk` cc `@estebank` #117235
Rework negative coherence to properly consider impls that only partly overlap
This PR implements a modified negative coherence that handles impls that only have partial overlap.
It does this by:
1. taking both impl trait refs, instantiating them with infer vars
2. equating both trait refs
3. taking the equated trait ref (which represents the two impls' intersection), and resolving any vars
4. plugging all remaining infer vars with placeholder types
these placeholder-plugged trait refs can then be used normally with the new trait solver, since we no longer have to worry about the issue with infer vars in param-envs.
We use the **new trait solver** to reason correctly about unnormalized trait refs (due to deferred projection equality), since this avoid having to normalize anything under param-envs with infer vars in them.
This PR then additionally:
* removes the `FnPtr` knowable hack by implementing proper negative `FnPtr` trait bounds for rigid types.
---
An example:
Consider these two partially overlapping impls:
```
impl<T, U> PartialEq<&U> for &T where T: PartialEq<U> {}
impl<F> PartialEq<F> for F where F: FnPtr {}
```
Under the old algorithm, we would take one of these impls and replace it with infer vars, then try unifying it with the other impl under identity substitutions. This is not possible in either direction, since it either sets `T = U`, or tries to equate `F = &?0`.
Under the new algorithm, we try to unify `?0: PartialEq<?0>` with `&?1: PartialEq<&?2>`. This gives us `?0 = &?1 = &?2` and thus `?1 = ?2`. The intersection of these two trait refs therefore looks like: `&?1: PartialEq<&?1>`. After plugging this with placeholders, we get a trait ref that looks like `&!0: PartialEq<&!0>`, with the first impl having substs `?T = ?U = !0` and the second having substs `?F = &!0`[^1].
Then we can take the param-env from the first impl, and try to prove the negated where clause of the second.
We know that `&!0: !FnPtr` never holds, since it's a rigid type that is also not a fn ptr, we successfully detect that these impls may never overlap.
[^1]: For the purposes of this example, I just ignored lifetimes, since it doesn't really matter.
Fix implied outlives check for GAT in RPITIT
We enforce certain `Self: 'lt` bounds for GATs to save space for more sophisticated implied bounds, but those currently operate on the HIR. Code was easily reworked to operate on def-ids so that we can properly let these suggestions propagate through synthetic associated types like RPITITs and AFITs.
r? `@jackh726` or `@aliemjay`
Fixes#116789
Relate alias ty with variance
In the new solver, turns out that the subst-relate branch of the alias-relate predicate was relating args invariantly even for opaques, which have variance 💀.
This change is a bit more invasive, but I'd rather not special-case it [here](aeaa5c30e5/compiler/rustc_trait_selection/src/solve/alias_relate.rs (L171-L190)) and then have it break elsewhere. I'm doing a perf run to see if the extra call to `def_kind` is that expensive, if it is, I'll reconsider.
r? ``@lcnr``
Show more information when multiple `impl`s apply
- When there are `impl`s without type params, show only those (to avoid showing overly generic `impl`s).
```
error[E0283]: type annotations needed
--> $DIR/multiple-impl-apply.rs:34:9
|
LL | let y = x.into();
| ^ ---- type must be known at this point
|
note: multiple `impl`s satisfying `_: From<Baz>` found
--> $DIR/multiple-impl-apply.rs:14:1
|
LL | impl From<Baz> for Bar {
| ^^^^^^^^^^^^^^^^^^^^^^
...
LL | impl From<Baz> for Foo {
| ^^^^^^^^^^^^^^^^^^^^^^
= note: required for `Baz` to implement `Into<_>`
help: consider giving `y` an explicit type
|
LL | let y: /* Type */ = x.into();
| ++++++++++++
```
- Lower the importance of `T: Sized`, `T: WellFormed` and coercion errors, to prioritize more relevant errors. The pre-existing deduplication logic deals with hiding redundant errors better that way, and we show errors with more metadata that is useful to the user.
- Show `<SelfTy as Trait>::assoc_fn` suggestion in more cases.
```
error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
--> $DIR/cross-return-site-inference.rs:38:16
|
LL | return Err(From::from("foo"));
| ^^^^^^^^^^ cannot call associated function of trait
|
help: use a fully-qualified path to a specific available implementation
|
LL | return Err(</* self type */ as From>::from("foo"));
| +++++++++++++++++++ +
```
Fix#88284.
Add a note to duplicate diagnostics
Helps explain why there may be a difference between manual testing and the test suite output and highlights them as something to potentially look into
For existing duplicate diagnostics I just blessed them other than a few files that had other `NOTE` annotations in
More accurately point to where default return type should go
When getting the "default return type" span, instead of pointing to the low span of the next token, point to the high span of the previous token. This:
1. Makes forming return type suggestions more uniform, since we expect them all in the same place.
2. Arguably makes labels easier to understand, since we're pointing to where the implicit `-> ()` would've gone, rather than the starting brace or the semicolon.
r? ```@estebank```
In `report_fullfillment_errors` push back `T: Sized`, `T: WellFormed`
and coercion errors to the end of the list. The pre-existing
deduplication logic eliminates redundant errors better that way, keeping
the resulting output with fewer errors than before, while also having
more detail.
Stabilize `impl_trait_projections`
Closes#115659
## TL;DR:
This allows us to mention `Self` and `T::Assoc` in async fn and return-position `impl Trait`, as you would expect you'd be able to.
Some examples:
```rust
#![feature(return_position_impl_trait_in_trait, async_fn_in_trait)]
// (just needed for final tests below)
// ---------------------------------------- //
struct Wrapper<'a, T>(&'a T);
impl Wrapper<'_, ()> {
async fn async_fn() -> Self {
//^ Previously rejected because it returns `-> Self`, not `-> Wrapper<'_, ()>`.
Wrapper(&())
}
fn impl_trait() -> impl Iterator<Item = Self> {
//^ Previously rejected because it mentions `Self`, not `Wrapper<'_, ()>`.
std::iter::once(Wrapper(&()))
}
}
// ---------------------------------------- //
trait Trait<'a> {
type Assoc;
fn new() -> Self::Assoc;
}
impl Trait<'_> for () {
type Assoc = ();
fn new() {}
}
impl<'a, T: Trait<'a>> Wrapper<'a, T> {
async fn mk_assoc() -> T::Assoc {
//^ Previously rejected because `T::Assoc` doesn't mention `'a` in the HIR,
// but ends up resolving to `<T as Trait<'a>>::Assoc`, which does rely on `'a`.
// That's the important part -- the elided trait.
T::new()
}
fn a_few_assocs() -> impl Iterator<Item = T::Assoc> {
//^ Previously rejected for the same reason
[T::new(), T::new(), T::new()].into_iter()
}
}
// ---------------------------------------- //
trait InTrait {
async fn async_fn() -> Self;
fn impl_trait() -> impl Iterator<Item = Self>;
}
impl InTrait for &() {
async fn async_fn() -> Self { &() }
//^ Previously rejected just like inherent impls
fn impl_trait() -> impl Iterator<Item = Self> {
//^ Previously rejected just like inherent impls
[&()].into_iter()
}
}
```
## Technical:
Lifetimes in return-position `impl Trait` (and `async fn`) are duplicated as early-bound generics local to the opaque in order to make sure we are able to substitute any late-bound lifetimes from the function in the opaque's hidden type. (The [dev guide](https://rustc-dev-guide.rust-lang.org/return-position-impl-trait-in-trait.html#aside-opaque-lifetime-duplication) has a small section about why this is necessary -- this was written for RPITITs, but it applies to all RPITs)
Prior to #103491, all of the early-bound lifetimes not local to the opaque were replaced with `'static` to avoid issues where relating opaques caused their *non-captured* lifetimes to be related. This `'static` replacement led to strange and possibly unsound behaviors (https://github.com/rust-lang/rust/issues/61949#issuecomment-508836314) (https://github.com/rust-lang/rust/issues/53613) when referencing the `Self` type alias in an impl or indirectly referencing a lifetime parameter via a projection type (via a `T::Assoc` projection without an explicit trait), since lifetime resolution is performed on the HIR, when neither `T::Assoc`-style projections or `Self` in impls are expanded.
Therefore an error was implemented in #62849 to deny this subtle behavior as a known limitation of the compiler. It was attempted by `@cjgillot` to fix this in #91403, which was subsequently unlanded. Then it was re-attempted to much success (🎉) in #103491, which is where we currently are in the compiler.
The PR above (#103491) fixed this issue technically by *not* replacing the opaque's parent lifetimes with `'static`, but instead using variance to properly track which lifetimes are captured and are not. The PR gated any of the "side-effects" of the PR behind a feature gate (`impl_trait_projections`) presumably to avoid having to involve T-lang or T-types in the PR as well. `@cjgillot` can clarify this if I'm misunderstanding what their intention was with the feature gate.
Since we're not replacing (possibly *invariant*!) lifetimes with `'static` anymore, there are no more soundness concerns here. Therefore, this PR removes the feature gate.
Tests:
* `tests/ui/async-await/feature-self-return-type.rs`
* `tests/ui/impl-trait/feature-self-return-type.rs`
* `tests/ui/async-await/issues/issue-78600.rs`
* `tests/ui/impl-trait/capture-lifetime-not-in-hir.rs`
---
r? cjgillot on the impl (not much, just removing the feature gate)
I'm gonna mark this as FCP for T-lang and T-types.
Anonymize binders for `refining_impl_trait` check
We're naively using the equality impl for `ty::Clause` in the refinement check, which is okay *except* for binders, which carry some information about where they come from in the AST. Those locations are not gonna be equal between traits and impls, so anonymize those clauses so that this doesn't matter.
Fixes#116135
Only prevent field projections into opaque types, not types containing opaque types
fixes https://github.com/rust-lang/rust/issues/115778
I did not think that original condition through properly... I'll also need to check the similar check around the other `ProjectionKind::OpaqueCast` creation site (this one is in hir, the other one is in mir), but I'll do that change in another PR that doesn't go into a beta backport.
Use placeholders to prevent using inferred RPITIT types to imply their own well-formedness
The issue here is that we use the same signature to do RPITIT inference as we do to compute implied bounds. To fix this, when gathering the assumed wf types for the method, we replace all of the infer vars (that will be eventually used to infer RPITIT types) with type placeholders, which imply nothing about lifetime bounds.
This solution kind of sucks, but I'm not certain there's another feasible way to fix this. If anyone has a better solution, I'd be glad to hear it.
My naive first solution was, instead of using placeholders, to replace the signature with the RPITIT projections that it originally started out with. But turns out that we can't just use the unnormalized signature of the trait method in `implied_outlives_bounds` since we normalize during WF computation -- that would cause a query cycle in `collect_return_position_impl_trait_in_trait_tys`.
idk who to request review...
r? `@lcnr` or `@aliemjay` i guess.
Fixes#116060
adjust how closure/generator types are printed
I saw `&[closure@$DIR/issue-20862.rs:2:5]` and I thought it is a slice type, because that's usually what `&[_]` is... it took me a while to realize that this is just a confusing printer and actually there's no slice. Let's use something that cannot be mistaken for a regular type.
Bubble up opaque <eq> opaque operations instead of picking an order
In case we are in `Bubble` mode (meaning every opaque type that is defined in the current crate is treated as if it were in its defining scope), we don't try to register an opaque type as the hidden type of another opaque type, but instead bubble up an obligation to equate them at the query caller site. Usually that means we have a `DefiningAnchor::Bind` and thus can reliably figure out whether an opaque type is in its defining scope. Where we can't, we'll error out, so the default is sound.
With this change we start using `AliasTyEq` predicates in the old solver, too.
fixes https://github.com/rust-lang/rust/issues/108498
But also regresses `tests/ui/impl-trait/anon_scope_creep.rs`. Our use of `Bubble` for `check_opaque_type_well_formed` is going to keep biting us.
r? `@lcnr` `@compiler-errors`
Capture lifetimes for associated type bounds destined to be lowered to opaques
Some associated type bounds get lowered to opaques, but they're not represented in the AST as opaques.
That means that we never collect lifetimes for them (`record_lifetime_params_for_impl_trait`) which are used currently for RPITITs, which capture all of their in-scope lifetimes[^1]. This means that the nested RPITITs that arise from some type like `impl Foo<Type: Bar>` (~> `impl Foo<Type = impl Bar>`) don't capture any lifetimes, leading to ICEs.
This PR makes sure we collect the lifetimes for associated type bounds as well, and make sure that they are set up correctly for opaque type lowering later.
Fixes#115360
[^1]: #114489
Don't check unnecessarily that impl trait is RPIT
We have this random `return_type_impl_trait` function to detect if a function returns an RPIT which is used in outlives suggestions, but removing it doesn't actually change any diagnostics. Let's just remove it.
Also, suppress a spurious outlives error from a ReError.
Fixes#114274
Change default panic handler message format.
This changes the default panic hook's message format from:
```
thread '{thread}' panicked at '{message}', {location}
```
to
```
thread '{thread}' panicked at {location}:
{message}
```
This puts the message on its own line without surrounding quotes, making it easiser to read. For example:
Before:
```
thread 'main' panicked at 'env variable `IMPORTANT_PATH` should be set by `wrapper_script.sh`', src/main.rs:4:6
```
After:
```
thread 'main' panicked at src/main.rs:4:6:
env variable `IMPORTANT_PATH` should be set by `wrapper_script.sh`
```
---
See this PR by `@nyurik,` which does that for only multi-line messages (specifically because of `assert_eq`): https://github.com/rust-lang/rust/pull/111071
This is the change that does that for *all* panic messages.
Map RPITIT's opaque type bounds back from projections to opaques
An RPITIT in a program's AST is eventually translated into both a projection GAT and an opaque. The opaque is used for default trait methods, like:
```
trait Foo {
fn bar() -> impl Sized { 0i32 }
}
```
The item bounds for both the projection and opaque are identical, and both have a *projection* self ty. This is mostly okay, since we can normalize this projection within the default trait method body to the opaque, but it does two things:
1. it leads to bugs in places where we don't normalize item bounds, like `deduce_future_output_from_obligations`
2. it leads to extra match arms that are both suspicious looking and also easy to miss
This PR maps the opaque type bounds of the RPITIT's *opaque* back to the opaque's self type to avoid this quirk. Then we can fix the UI test for #108304 (1.) and also remove a bunch of match arms (2.).
Fixes#108304
r? `@spastorino`
Don't install default projection bound for return-position `impl Trait` in trait methods with no body
This ensures that we never try to project to an opaque type in a trait method that has no body to infer its hidden type, which means we never later call `type_of` on that opaque. This is because opaque types try to reveal their hidden type when proving auto traits.
I thought about this a lot, and I think this is a fix that's less likely to introduce other strange downstream ICEs than #113461.
Fixes#113434
r? `@spastorino`
Fix invalid suggestion for mismatched types in closure arguments
This PR fixes the invalid suggestion for mismatched types in closure arguments.
The invalid suggestion came from a wrongly created span in the parser for closure arguments that don't have a type specified. Specifically, the span in this case was the last token span, but in the case of tuples, the span represented the last parenthesis instead of the whole tuple, which is fixed by taking the more accurate span of the pattern.
There is one unfortunate downside of this fix, it worsens even more the diagnostic for mismatched types in closure args without an explicit type. This happens because there is no correct span for implied inferred type. I tried also fixing this but it's a rabbit hole.
Fixes https://github.com/rust-lang/rust/issues/114180
The invalid suggestion came from a wrongly created span in `rustc_parse'
for closure arguments that didn't have a type specified. Specifically,
the span in this case was the last token span, but in the case of
tuples, the span represented the last parenthesis instead of the whole
tuple, which is fixed by taking the more accurate span of the pattern.
Skip reporting item name when checking RPITIT GAT's associated type bounds hold
Doesn't really make sense to label an item that has a name that users can't really mention. Fixes#114145. Also fixes#113794.
r? `@spastorino`
allow opaques to be defined by trait queries, again
This basically reverts #112963.
Moreover, all call-sites of `enter_canonical_trait_query` can now define opaque types, see the ui test `defined-by-user-annotation.rs`.
Fixes#113689
r? `@compiler-errors` `@oli-obk`
Replace RPITIT current impl with new strategy that lowers as a GAT
This PR replaces the current implementation of RPITITs with the new implementation that we had under -Zlower-impl-trait-in-trait-to-assoc-ty flag that lowers the RPIT as a GAT on the trait and on the impls that implement that trait.
Opening this PR as a draft because this goes after #112682, ~#112981~ and ~#112983~.
As soon as those are merged, I can rebase and we should run perf, crater and test a lot.
r? `@compiler-errors`
Don't call `query_normalize` when reporting similar impls
Firstly, It's sketchy to be using `query_normalize` at all during HIR typeck -- it's asking for an ICE 😅. Secondly, we're normalizing an impl trait ref that potentially has parameter types in `ty::ParamEnv::empty()`, which is kinda sketchy as well.
The only UI test change from removing this normalization is that we don't evaluate anonymous constants in impls, which end up giving us really ugly suggestions:
```
error[E0277]: the trait bound `[X; 35]: Default` is not satisfied
--> /home/gh-compiler-errors/test.rs:4:5
|
4 | <[X; 35] as Default>::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `[X; 35]`
|
= help: the following other types implement trait `Default`:
&[T]
&mut [T]
[T; 32]
[T; core::::array::{impl#30}::{constant#0}]
[T; core::::array::{impl#31}::{constant#0}]
[T; core::::array::{impl#32}::{constant#0}]
[T; core::::array::{impl#33}::{constant#0}]
[T; core::::array::{impl#34}::{constant#0}]
and 27 others
```
So just fold the impls with a `BottomUpFolder` that calls `ty::Const::eval`. This doesn't work totally correctly with generic-const-exprs, but it's fine for stable code, and this is error reporting after all.
Reveal opaques in new solver
We were testing against the wrong reveal mode 😨
Also a couple of misc commits that I don't want to really put in separate prs
r? ``@lcnr``
Rollup of 8 pull requests
Successful merges:
- #113413 (Add needs-triage to all new issues)
- #113426 (Don't ICE in `resolve_bound_vars` when associated return-type bounds are in bad positions)
- #113427 (Remove `variances_of` on RPITIT GATs, remove its one use-case)
- #113441 (miri: check that assignments do not self-overlap)
- #113453 (Remove unused from_method from rustc_on_unimplemented)
- #113456 (Avoid calling report_forbidden_specialization for RPITITs)
- #113466 (Update cargo)
- #113467 (Fix comment of `fn_can_unwind`)
r? `@ghost`
`@rustbot` modify labels: rollup
Remove chalk support from the compiler
Removes chalk (`-Ztrait-solver=chalk`) from the compiler and prunes any dead code resulting from this, mainly:
* Remove the chalk compatibility layer in `compiler/rustc_traits/src/chalk`
* Remove the chalk flag `-Ztrait-solver=chalk` and its `TraitEngine` implementation
* Remove `TypeWellFormedFromEnv` (and its many `bug!()` match arms)
* Remove the chalk migration mode from compiletest
* Remove the `chalkify` UI tests (do we want to keep any of these, but migrate them to `-Ztrait-solver=next`??)
Fulfills rust-lang/types-team#93.
r? `@jackh726`
Make RPITITs assume/require their parent method's predicates
Removes a FIXME from the `param_env` query where we were manually adding the parent function's predicates to the RPITIT's assumptions.
r? `@spastorino`
Error when RPITITs' hidden types capture more lifetimes than their trait definitions
This implements a stricter set of captures rules for RPITITs. They now may only capture:
1. Lifetimes from the impl header (both the self type and any trait substs -- we may want to restrict just to the self type's lifetimes, but the PR makes that easy to do, too)
2. Lifetimes mentioned by the `impl Trait` in the trait method's definition.
Namely, they may not mention lifetimes from the method (early or late) that are not mentioned in the `impl Trait`.
cc #105258 which I think was trying to do this too, though I'm not super familiar with what exactly differs from that or why that one was broken.
cc #112194 (doesn't fix this issue per se, because it's still an open question, but I think this is objectively better than the status quo, and gets us closer to resolving that issue.)
Technically is a fix for the ICE in #108580, but it turns that issue into an error now. We can decide separately whether or not nested RPITITs should capture lifetimes from their parents.
r? ``@oli-obk``
Encode item bounds for `DefKind::ImplTraitPlaceholder`
This was lost in a refactoring -- `hir::ItemKind::OpaqueTy` doesn't always map to `DefKind::Opaque`, specifically for RPITITs, so the check was migrated subtly wrong, and unfortunately I never had a test for this 🙃Fixes#113155
r? ``@cjgillot``
Account for late-bound vars from parent arg-position impl trait
We should be reporting an error like we do for late-bound args coming from a parent APIT.
Fixes#113016
Preserve substs in opaques recorded in typeck results
This means that we now prepopulate MIR with opaques with the right substs.
The first commit is a hack that I think we discussed, having to do with `DefiningAnchor::Bubble` basically being equivalent to `DefiningAnchor::Error` in the new solver, so having to use `DefiningAnchor::Bind` instead, lol.
r? `@lcnr`
Note user-facing types of coercion failure
When coercing, for example, `Box<A>` into `Box<dyn B>`, make sure that any failure notes mention *those* specific types, rather than mentioning inner types, like "the cast from `A` to `dyn B`".
I expect end-users are often confused when we skip layers of types and only mention the "innermost" part of a coercion, especially when other notes point at HIR, e.g. #111406.
Fix problems with backtraces in two ui tests.
`default-backtrace-ice.rs` started started failing for me recently,
because on my Ubuntu 23.04 system there are 100 stack frames, and the
current stack filtering pattern doesn't match on a stack frame with a
three digit number.
`issue-86800.rs` can also be improved, backtrace-wise.
r? `@Nilstrieb`
Because it then just has to be filtered out.
This change makes this test more like these other tests:
- tests/ui/treat-err-as-bug/err.rs
- tests/ui/treat-err-as-bug/delay_span_bug.rs
- tests/ui/mir/validate/storage-live.rs
- tests/ui/associated-inherent-types/bugs/ice-substitution.rs
- tests/ui/layout/valid_range_oob.rs
Encode def span for foreign return-position `impl Trait` in trait
Fixes#111031, yet another def-span encoding issue :/
Includes a smaller repro than the issue, but I can confirm it ICEs:
```
query stack during panic:
#0 [def_span] looking up span for `rpitit::Foo::bar::{opaque#0}`
#1 [object_safety_violations] determining object safety of trait `rpitit::Foo`
#2 [check_is_object_safe] checking if trait `rpitit::Foo` is object safe
#3 [typeck] type-checking `main`
#4 [used_trait_imports] finding used_trait_imports `main`
#5 [analysis] running analysis passes on this crate
```
Luckily since this only affects nightly, this desn't need to be backported.
Allow to feed a value in another query's cache and remove `WithOptConstParam`
I used it to remove `WithOptConstParam` queries, as an example.
The idea is that a query (here `typeck(function)`) can write into another query's cache (here `type_of(anon const)`). The dependency node for `type_of` would depend on all the current dependencies of `typeck`.
There is still an issue with cycles: if `type_of(anon const)` is accessed before `typeck(function)`, we will still have the usual cycle. The way around this issue is to `ensure` that `typeck(function)` is called before accessing `type_of(anon const)`.
When replayed, we may the following cases:
- `typeck` is green, in that case `type_of` is green too, and all is right;
- `type_of` is green, `typeck` may still be marked as red (it depends on strictly more things than `type_of`) -> we verify that the saved value and the re-computed value of `type_of` have the same hash;
- `type_of` is red, then `typeck` is red -> it's the caller responsibility to ensure `typeck` is recomputed *before* `type_of`.
As `anon consts` have their own `DefPathData`, it's not possible to have the def-id of the anon-const point to something outside the original function, but the general case may have to be resolved before using this device more broadly.
There is an open question about loading from the on-disk cache. If `typeck` is loaded from the on-disk cache, the side-effect does not happen. The regular `type_of` implementation can go and fetch the correct value from the decoded `typeck` results, and the dep-graph will check that the hashes match, but I'm not sure we want to rely on this behaviour.
I specifically allowed to feed the value to `type_of` from inside a call to `type_of`. In that case, the dep-graph will check that the fingerprints of both values match.
This implementation is still very sensitive to cycles, and requires that we call `typeck(function)` before `typeck(anon const)`. The reason is that `typeck(anon const)` calls `type_of(anon const)`, which calls `typeck(function)`, which feeds `type_of(anon const)`, and needs to build the MIR so needs `typeck(anon const)`. The latter call would not cycle, since `type_of(anon const)` has been set, but I'd rather not remove the cycle check.
compiletest: Don't allow tests with overlapping prefix names
Some tests will delete their output directory before starting. The output directory is based on the test names. If one test is the prefix of another test, then when that test starts, it could try to delete the output directory of the other test with the longer path, or otherwise clash with it while the two tests are trying to create/delete/modify the same directory.
In practice, this manifested as a random error on macOS where two tests were trying to create/delete/create `rustdoc/primitive` and `rustdoc/primitive/no_std`, which resulted in an EINVAL (InvalidInput) error.
This renames some of the offending tests, adds `compiletest-ignore-dir` to prevent compiletest from processing some files, and adds a check to prevent this from happening in the future.
Fixes#109397
Some tests will delete their output directory before starting.
The output directory is based on the test names.
If one test is the prefix of another test, then when that test
starts, it could try to delete the output directory of the other
test with the longer path.
Do not consider synthesized RPITITs on missing items checks
Without this patch for `tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.rs` we get ...
```
warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
--> tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.rs:4:12
|
4 | #![feature(return_position_impl_trait_in_trait)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
= note: `#[warn(incomplete_features)]` on by default
error[E0046]: not all trait items implemented, missing: `foo`, ``
--> tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.rs:12:1
|
8 | fn foo(&self) -> impl Sized;
| ----------------------------
| | |
| | `` from trait
| `foo` from trait
...
12 | impl MyTrait for i32 {
| ^^^^^^^^^^^^^^^^^^^^ missing `foo`, `` in implementation
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0046`.
```
instead of ...
```
warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/dont-project-to-rpitit-with-no-value.rs:4:12
|
LL | #![feature(return_position_impl_trait_in_trait)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
= note: `#[warn(incomplete_features)]` on by default
error[E0046]: not all trait items implemented, missing: `foo`
--> $DIR/dont-project-to-rpitit-with-no-value.rs:12:1
|
LL | fn foo(&self) -> impl Sized;
| ---------------------------- `foo` from trait
...
LL | impl MyTrait for i32 {
| ^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0046`.
```
r? `@compiler-errors`
Walk un-shifted nested `impl Trait` in trait when setting up default trait method assumptions
Fixes a double subtraction in some binder math in return-position `impl Trait` in trait handling code.
Fixes#109239
Fix generics_of for impl's RPITIT synthesized associated type
The only useful commit is the last one.
This makes `generics_of` for the impl side RPITIT copy from the trait's associated type and avoid the fn on the impl side which was previously wrongly used.
This solution is better but we still need to fix resolution of the generated generics.
r? ``@compiler-errors``
Fix generics mismatch errors for RPITITs on -Zlower-impl-trait-in-trait-to-assoc-ty
This PR stops reporting errors due to different count of generics on the new synthesized associated types for RPITITs. Those were already reported when we compare the function on the triat with the function on the impl.
r? ``@compiler-errors``
Make fns from other crates with RPITIT work for -Zlower-impl-trait-in-trait-to-assoc-ty
Only the last two commits are meaningful.
r? `@compiler-errors`
Remove tests/ui/impl-trait/in-trait/new-lowering-strategy in favor of using revisions on existing tests
r? `@compiler-errors`
This one again sits on top of existing approved PRs and it still needs to add revisions to tests in `tests/ui/impl-trait/in-trait` as it only does so for async in traits.
Remove `identity_future` indirection
This was previously needed because the indirection used to hide some unexplained lifetime errors, which it turned out were related to the `min_choice` algorithm.
Removing the indirection also solves a couple of cycle errors, large moves and makes async blocks support the `#[track_caller]`annotation.
Fixes https://github.com/rust-lang/rust/issues/104826.
This was previously needed because the indirection used to hide some unexplained lifetime errors, which it turned out were related to the `min_choice` algorithm.
Removing the indirection also solves a couple of cycle errors, large moves and makes async blocks support the `#[track_caller]` annotation.
Account for binders correctly when adding default RPITIT method assumption
As of #108203, we install extra projection predicates into the param-env of a default trait method when it has return-position `impl Trait` (or is async).
The implementation didn't account for the fact that it's walking into and out of binders, so we just need to shift all the debruijn indices accordingly when constructing the projection predicates.
Fixes#108579
r? types
Label opaque type for 'captures lifetime' error message
Providing more information may help make this somewhat opaque (lol) error message a bit clearer.
diagnostics: remove inconsistent English article "this" from E0107
Consider [`tests/ui/const-generics/generic_const_exprs/issue-102768.stderr`][issue-102768.stderr], the error message where it gives additional notes about where the associated type is defined, and how the dead code lint doesn't have an article, like in [`tests/ui/lint/dead-code/issue-85255.stderr`][issue-85255.stderr]. They don't have articles, so it seems unnecessary to have one here.
[issue-102768.stderr]: 07c993eba8/tests/ui/const-generics/generic_const_exprs/issue-102768.stderr
[issue-85255.stderr]: 07c993eba8/tests/ui/lint/dead-code/issue-85255.stderr
Consider `tests/ui/const-generics/generic_const_exprs/issue-102768.stderr`,
the error message where it gives additional notes about where the associated
type is defined, and how the dead code lint doesn't have an article,
like in `tests/ui/lint/dead-code/issue-85255.stderr`. They don't have
articles, so it seems unnecessary to have one here.
Ban associated type bounds in bad positions
We should not try to lower associated type bounds into TAITs in positions where `impl Trait` is not allowed (except for in `where` clauses, like `where T: Trait<Assoc: Bound>`).
This is achieved by using the same `rustc_ast_lowering` machinery as impl-trait does to characterize positions as universal/existential/disallowed.
Fixes#106077
Split out the first commit into #108066, since it's not really related.
Define the `named_static_lifetimes` lint
This lint will replace the existing hard-warning.
Replace the named static lifetime hard-warning with the new lint
Update the UI tests for the `named_static_lifetimes` lint
Remove the direct dependency on `rustc_lint_defs`
fix build
Signed-off-by: Zhi Qi <qizhi@pingcap.com>
use "UNUSED_LIFETIMES" instead
Signed-off-by: Zhi Qi <qizhi@pingcap.com>
update 1 test and fix typo
Signed-off-by: Zhi Qi <qizhi@pingcap.com>
update tests
Signed-off-by: Zhi Qi <qizhi@pingcap.com>
fix tests: add extra blank line
Signed-off-by: Zhi Qi <qizhi@pingcap.com>
Most tests involving save-analysis were removed, but I kept a few where
the `-Zsave-analysis` was an add-on to the main thing being tested,
rather than the main thing being tested.
For `x.py install`, the `rust-analysis` target has been removed.
For `x.py dist`, the `rust-analysis` target has been kept in a
degenerate form: it just produces a single file `reduced.json`
indicating that save-analysis has been removed. This is necessary for
rustup to keep working.
Closes#43606.
fix: improve the suggestion on future not awaited
Considering the following code
```rust
fn foo() -> u8 {
async fn async_fn() -> u8 { 22 }
async_fn()
}
fn main() {}
```
the error generated before this commit from the compiler is
```
➜ rust git:(macros/async_fn_suggestion) ✗ rustc test.rs --edition 2021
error[E0308]: mismatched types
--> test.rs:4:5
|
1 | fn foo() -> u8 {
| -- expected `u8` because of return type
...
4 | async_fn()
| ^^^^^^^^^^ expected `u8`, found opaque type
|
= note: expected type `u8`
found opaque type `impl Future<Output = u8>`
help: consider `await`ing on the `Future`
|
4 | async_fn().await
| ++++++
error: aborting due to previous error
```
In this case the error is nor perfect, and can confuse the user that do not know that the opaque type is the future.
So this commit will propose (and conclude the work start in https://github.com/rust-lang/rust/issues/80658)
to change the string `opaque type` to `future` when applicable and also remove the Expected vs Received note by adding a more specific one regarding the async function that return a future type.
So the new error emitted by the compiler is
```
error[E0308]: mismatched types
--> test.rs:4:5
|
1 | fn foo() -> u8 {
| -- expected `u8` because of return type
...
4 | async_fn()
| ^^^^^^^^^^ expected `u8`, found future
|
note: calling an async function returns a future
--> test.rs:4:5
|
4 | async_fn()
| ^^^^^^^^^^
help: consider `await`ing on the `Future`
|
4 | async_fn().await
| ++++++
error: aborting due to previous error
```
Fixes https://github.com/rust-lang/rust/issues/80658
It remains to rework the case described in the following issue https://github.com/rust-lang/rust/issues/107899 but I think this deserves its own PR after we discuss a little bit how to handle these kinds of cases.
r? `@eholk`
`@rustbot` label +I-async-nominated
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
Considering the following code
```rust
fn foo() -> u8 {
async fn async_fn() -> u8 { 22 }
async_fn()
}
fn main() {}
```
the error generated before this commit from the compiler is
```
➜ rust git:(macros/async_fn_suggestion) ✗ rustc test.rs --edition 2021
error[E0308]: mismatched types
--> test.rs:4:5
|
1 | fn foo() -> u8 {
| -- expected `u8` because of return type
...
4 | async_fn()
| ^^^^^^^^^^ expected `u8`, found opaque type
|
= note: expected type `u8`
found opaque type `impl Future<Output = u8>`
help: consider `await`ing on the `Future`
|
4 | async_fn().await
| ++++++
error: aborting due to previous error
```
In this case the error is nor perfect, and can confuse the user
that do not know that the opaque type is the future.
So this commit will propose (and conclude the work start in
https://github.com/rust-lang/rust/issues/80658)
to change the string `opaque type` to `future` when applicable
and also remove the Expected vs Received note by adding a more
specific one regarding the async function that return a future type.
So the new error emitted by the compiler is
```
error[E0308]: mismatched types
--> test.rs:4:5
|
1 | fn foo() -> u8 {
| -- expected `u8` because of return type
...
4 | async_fn()
| ^^^^^^^^^^ expected `u8`, found future
|
note: calling an async function returns a future
--> test.rs:4:5
|
4 | async_fn()
| ^^^^^^^^^^
help: consider `await`ing on the `Future`
|
4 | async_fn().await
| ++++++
error: aborting due to previous error
```
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
Don't cause a cycle when formatting query description that references a FnDef
When a function returns `-> _`, we use typeck to compute what the resulting type of the body _should_ be. If we call another query inside of typeck and hit a cycle error, we attempt to report the cycle error which requires us to compute all of the query descriptions for the stack.
However, if one of the queries in that cycle has a query description that references this function as a FnDef type, we'll cause a *second* cycle error from within the cycle error reporting code, since rendering a FnDef requires us to compute its signature. This causes an unwrap to ICE, since during the *second* cycle reporting code, we try to look for a job that isn't in the active jobs list.
We can avoid this by using `with_no_queries!` when computing these query descriptions.
Fixes#107089
The only drawback is that the rendering of opaque types in cycles regresses a bit :| I'm open to alternate suggestions about how we may handle this...
Remove confusing 'while checking' note from opaque future type mismatches
Maybe I'm just misinterpreting the wording of the note. The only value I can see in this note is that it points out where the async's opaque future is coming from, but the way it's doing it is misleading IMO.
For example:
```rust
note: while checking the return type of the `async fn`
--> $DIR/dont-suggest-missing-await.rs:7:24
|
LL | async fn make_u32() -> u32 {
| ^^^ checked the `Output` of this `async fn`, found opaque type
```
We point at the type `u32` in the HIR, but then say "found opaque type". We also say "while checking"... but we're typechecking a totally different function when we get this type mismatch!
r? ``@estebank`` but feel free to reassign and/or take your time reviewing this. I'd be inclined to also discuss reworking the presentation of this type mismatch to restore some of these labels in a way that makes it more clear what it's trying to point out.
Do not filter substs in `remap_generic_params_to_declaration_params`.
The relevant filtering should have been performed by borrowck.
Fixes https://github.com/rust-lang/rust/issues/105826
r? types