Do not consider elaborated projection predicates for objects in new solver
Object types have projection bounds which are elaborated during astconv. There's no need to do it again for projection goals, since that'll give us duplicate projection candidatesd that are distinct up to regions due to the fact that we canonicalize every region to a separate variable. See quick example below the break for a better explanation.
Discussed this with lcnr, and adding a stop-gap until we get something like intersection region constraints (or modify canonicalization to canonicalize identical regions to the same canonical regions) -- after which, this will hopefully not matter and may be removed.
r? `@lcnr`
---
See `tests/ui/traits/new-solver/more-object-bound.rs`:
Consider a goal: `<dyn Iter<'a, ()> as Iterator>::Item = &'a ()`.
After canonicalization: `<dyn Iter<'!0r, (), Item = '!1r ()> as Iterator>::Item == &!'2r ()`
* First object candidate comes from the item bound in the dyn's bounds itself, giving us `<dyn Iter<'!0r, (), Item = '?!r ()> as Iterator>::Item == &!'1r ()`. This gives us one region constraint: `!'1r == !'2r`.
* Second object candidate comes from elaborating the principal trait ref, gives us `<dyn Iter<'!0r, (), Item = '!1r ()> as Iterator>::Item == &!'0r ()`. This gives us one region constraint: `!'0r == !'2r`.
* Oops! Ambiguity!
Rename `IndexVec::last` → `last_index`
As I've been trying to replace a `Vec` with an `IndexVec`, having `last` exist on both but returning very different types makes the transition a bit awkward -- the errors are later, where you get things like "there's no `ty` method on `mir::Field`" rather than a more localized error like "hey, there's no `last` on `IndexVec`".
So I propose renaming `last` to `last_index` to help distinguish `Vec::last`, which returns an element, and `IndexVec::last_index`, which returns an index.
(Similarly, `Iterator::last` also returns an element, not an index.)
Check for overflow in `assemble_candidates_after_normalizing_self_ty`
Prevents a stack overflow (⚠️❗) in the new solver when we have param-env candidates that look like: `T: Trait<Assoc = <T as Trait>::Assoc>`
The current error message looks bad, but that's because we don't distinguish overflow and other ambiguity errors. I'll break that out into a separate PR since the fix may be controversial.
r? `@lcnr`
As I've been trying to replace a `Vec` with an `IndexVec`, having `last` exist on both but returning very different types makes the transition a bit awkward -- the errors are later, where you get things like "there's no `ty` method on `mir::Field`" rather than a more localized error like "hey, there's no `last` on `IndexVec`".
So I propose renaming `last` to `last_index` to help distinguish `Vec::last`, which returns an element, and `IndexVec::last_index`, which returns an index.
(Similarly, `Iterator::last` also returns an element, not an index.)
Rollup of 8 pull requests
Successful merges:
- #91793 (socket ancillary data implementation for FreeBSD (from 13 and above).)
- #92284 (Change advance(_back)_by to return the remainder instead of the number of processed elements)
- #102472 (stop special-casing `'static` in evaluation)
- #108480 (Use Rayon's TLV directly)
- #109321 (Erase impl regions when checking for impossible to eagerly monomorphize items)
- #109470 (Correctly substitute GAT's type used in `normalize_param_env` in `check_type_bounds`)
- #109562 (Update ar_archive_writer to 0.1.3)
- #109629 (remove obsolete `givens` from regionck)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Add a builtin `FnPtr` trait that is implemented for all function pointers
r? `@ghost`
Rebased version of https://github.com/rust-lang/rust/pull/99531 (plus adjustments mentioned in the PR).
If perf is happy with this version, I would like to land it, even if the diagnostics fix in 9df8e1befb5031a5bf9d8dfe25170620642d3c59 only works for `FnPtr` specifically, and does not generally improve blanket impls.
stop special-casing `'static` in evaluation
fixes#102360
I have no idea whether this actually removed all places where `'static` matters. Without canonicalization it's very easy to accidentally rely on `'static` again. Blocked on changing the `order_dependent_trait_objects` future-compat lint to a hard error
r? `@nikomatsakis`
Don't elaborate non-obligations into obligations
It's suspicious to elaborate a `PolyTraitRef` or `Predicate` into an `Obligation`, since the former does not have a param-env associated with it, but the latter does. This is a footgun that, while not being misused *currently* in the compiler, easily could be misused by someone less familiar with the elaborator's inner workings.
This PR just changes the API -- ideally, the elaborator wouldn't even have to deal with obligations if we're not elaborating obligations, but that would require a bit more abstraction than I could be bothered with today.
Implement non-const `Destruct` trait in new solver
Makes it so that we can call stdlib methods like `Option::map` in **non-const** environments, since *many* stdlib methods have `Destruct` bounds 😅
This doesn't bother to implement `const Destruct` yet, but it shouldn't be too hard to do so. Just didn't bother since we already don't have much support for const traits in the new solver anyways. I'd be happy to add skeleton support for `const Destruct`, though, if the reviewer desires.
Rollup of 9 pull requests
Successful merges:
- #108629 (rustdoc: add support for type filters in arguments and generics)
- #108924 (panic_immediate_abort requires abort as a panic strategy)
- #108961 (Refine error spans for const args in hir typeck)
- #108986 (sync LVI tests)
- #109142 (Add block-based mutex unlocking example)
- #109368 (fix typo in the creation of OpenOption for RustyHermit)
- #109493 (Return nested obligations from canonical response var unification)
- #109515 (Add AixLinker to support linking on AIX)
- #109536 (resolve: Rename some cstore methods to match queries and add comments)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Return nested obligations from canonical response var unification
Handle alias-eq obligations being emitted from `instantiate_and_apply_query_response` in:
* `EvalCtxt` - by processing the nested obligations in the next loop by `new_goals`
* `FulfillCtxt` - by adding the nested obligations to the fulfillment's pending obligations
* `InferCtxt::evaluate_obligation` - ~~by returning `EvaluationResult::EvaluatedToAmbig` (boo 👎, see the FIXME)~~ same behavior as above, since we use fulfillment and `select_where_possible`
The only one that's truly sketchy is `evaluate_obligation`, but it's not hard to modify this behavior moving forward.
From #109037, I think a smaller repro could be crafted if I were smarter, but I am not, so I just took this from #105878.
r? `@lcnr` cc `@BoxyUwU`
Refine error spans for const args in hir typeck
Improve just a couple of error messages having to do with mismatched consts.
r? `@ghost` i'll put this up when the dependent commits are merged
Rollup of 7 pull requests
Successful merges:
- #108541 (Suppress `opaque_hidden_inferred_bound` for nested RPITs)
- #109137 (resolve: Querify most cstore access methods (subset 2))
- #109380 (add `known-bug` test for unsoundness issue)
- #109462 (Make alias-eq have a relation direction (and rename it to alias-relate))
- #109475 (Simpler checked shifts in MIR building)
- #109504 (Stabilize `arc_into_inner` and `rc_into_inner`.)
- #109506 (make param bound vars visibly bound vars with -Zverbose)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Make alias-eq have a relation direction (and rename it to alias-relate)
Emitting an "alias-eq" is too strict in some situations, since we don't always want strict equality between a projection and rigid ty. Adds a relation direction.
* I could probably just reuse this [`RelationDir`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/combine/enum.RelationDir.html) -- happy to uplift that struct into middle and use that instead, but I didn't feel compelled to... 🤷
* Some of the matching in `compute_alias_relate_goal` is a bit verbose -- I guess I could simplify it by using [`At::relate`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/at/struct.At.html#method.relate) and mapping the relation-dir to a variance.
* Alternatively, I coulld simplify things by making more helper functions on `EvalCtxt` (e.g. `EvalCtxt::relate_with_direction(T, T)` that also does the nested goal registration). No preference.
r? ```@lcnr``` cc ```@BoxyUwU``` though boxy can claim it if she wants
NOTE: first commit is all the changes, the second is just renaming stuff
new solver cleanup + implement coherence
the cleanup:
- change `Certainty::unify_and` to consider ambig + overflow to be ambig
- rename `trait_candidate_should_be_dropped_in_favor_of` to `candidate_should_be_dropped_in_favor_of`
- remove outdated fixme
For coherence I mostly just add an ambiguous candidate if the current trait ref is unknowable. I am doing the same for reservation impl where I also just add an ambiguous candidate.
a general type system cleanup
removes the helper functions `traits::fully_solve_X` as they add more complexity then they are worth. It's confusing which of these helpers should be used in which context.
changes the way we deal with overflow to always add depth in `evaluate_predicates_recursively`. It may make sense to actually fully transition to not have `recursion_depth` on obligations but that's probably a bit too much for this PR.
also removes some other small - and imo unnecessary - helpers.
r? types
Do not suggest bounds restrictions for synthesized RPITITs
Before this PR we were getting ...
```
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
--> tests/ui/async-await/in-trait/missing-send-bound.rs:5:12
|
5 | #![feature(async_fn_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: future cannot be sent between threads safely
--> tests/ui/async-await/in-trait/missing-send-bound.rs:17:20
|
17 | assert_is_send(test::<T>());
| ^^^^^^^^^^^ future returned by `test` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `impl Future<Output = ()>`
note: future is not `Send` as it awaits another future which is not `Send`
--> tests/ui/async-await/in-trait/missing-send-bound.rs:13:5
|
13 | T::bar().await;
| ^^^^^^^^ await occurs here on type `impl Future<Output = ()>`, which is not `Send`
note: required by a bound in `assert_is_send`
--> tests/ui/async-await/in-trait/missing-send-bound.rs:21:27
|
21 | fn assert_is_send(_: impl Send) {}
| ^^^^ required by this bound in `assert_is_send`
help: consider further restricting the associated type
|
16 | fn test2<T: Foo>() where impl Future<Output = ()>: Send {
| ++++++++++++++++++++++++++++++++++++
error: aborting due to previous error; 1 warning emitted
```
and we want this output ...
```
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/missing-send-bound.rs:5:12
|
LL | #![feature(async_fn_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: future cannot be sent between threads safely
--> $DIR/missing-send-bound.rs:17:20
|
LL | assert_is_send(test::<T>());
| ^^^^^^^^^^^ future returned by `test` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `impl Future<Output = ()>`
note: future is not `Send` as it awaits another future which is not `Send`
--> $DIR/missing-send-bound.rs:13:5
|
LL | T::bar().await;
| ^^^^^^^^ await occurs here on type `impl Future<Output = ()>`, which is not `Send`
note: required by a bound in `assert_is_send`
--> $DIR/missing-send-bound.rs:21:27
|
LL | fn assert_is_send(_: impl Send) {}
| ^^^^ required by this bound in `assert_is_send`
error: aborting due to previous error; 1 warning emitted
```
r? `@compiler-errors`
Only implement Fn* traits for extern "Rust" safe function pointers and items
Since calling the function via an `Fn` trait will assume `extern "Rust"` ABI and not do any safety checks, only safe `extern "Rust"` function can implement the `Fn` traits. This syncs the logic between the old solver and the new solver.
r? `@compiler-errors`
Constrain const vars to error if const types are mismatched
When equating two consts of different types, if either are const variables, constrain them to the correct const error kind.
This helps us avoid "successfully" matching a const against an impl signature but leaving unconstrained const vars, which will lead to incremental ICEs when we call const-eval queries during const projection.
Fixes#109296
The second commit in the stack fixes a regression in the first commit where we end up mentioning `[const error]` in an impl overlap error message. I think the error message changes for the better, but I could implement alternative strategies to avoid this without delaying the overlap error message...
r? `@BoxyUwU`
new solver: make all goal evaluation able to be automatically rerun
It is generally wrong to call `evaluate_goal` multiple times or `evaluate_goal` and `evaluate_all` for the same `QueryResult` without correctly handling rerunning the goals when inference makes progress. Not doing so will result in the assertion in `evaluate_goal` firing because rerunning the goal will lead to a more accurate `QueryResult`.
Currently there are lots of places that get this wrong and generally it is complex and error prone to handle correctly everywhere. This PR introduces a way to add goals to the `EvalCtxt` and then run all the added goals in a loop so that `evaluate_goal`/`evaluate_all` is not necessary to call manually.
There are a few complications for making everything work "right":
1. the `normalizes-to` hack that replaces the rhs with an unconstrained infer var requires special casing in the new `try_evaluate_added_goals` function similar to how `evaluate_goal`'s assertion special cases that hack.
2. `assemble_candidates_after_normalizing_self_ty`'s normalization step needs to be reran for each candidate otherwise the found candidates will potentially get a more accurate `QueryResult` when rerunning the projection/trait goal which can effect the `QueryResult` of the projection/trait goal.
This is implemented via `EvalCtxt::probe`'s closure's `EvalCtxt` inheriting the added goals of the `EvalCtxt` that `probe` is called on, allowing us to add goals in a probe, and then enter a nested probe for each candidate and evaluate added goals which include the normalization step's goals.
I made `make_canonical_response` evaluate added goals so that it will be hard to mess up the impl of the solver by forgetting to evaluate added goals. Right now the only way to mess this up would be to call `response_no_constraints` (which from the name is obviously weird).
The visibility of `evaluate_goal` means that it can be called from various `compute_x_goal` or candidate assembly functions, this is generally wrong and we should never call `evaluate_goal` manually, instead we should be calling `add_goal`/`add_goals`. This is solved by moving `evaluate_goal` `evaluate_canonical_goal` and `compute_goal` into `eval_ctxt`'s module and making them private so they cannot be called from elsewhere, forcing people to call `add_goal/s` and `evaluate_added_goals_and_make_canonical_resposne`/`try_evaluate_added_goals`
---
Other changes:
- removed the `&& false` that was introduced to the assertion in `evaluate_goal` in #108839
- remove a `!self.did_overflow()` requirement in `search_graph.is_empty()` which causes goals that overflow to ICE
- made `EvalCtxt::eq` take `&mut self` and add all the nested goals via `add_goals` instead of returning them as 99% of call sites just immediately called `EvalCtxt::add_goals` manually.
r? `````@lcnr`````
- only borrow the refcell once per loop
- avoid complex matches to reduce branch paths in the hot loop
- use a by-ref fast path that avoids mutations at the expense of having false negatives
Install projection from RPITIT to default trait method opaque correctly
1. For new lowering strategy `-Zlower-impl-trait-in-trait-to-assoc-ty`, install the correct default trait method projection predicates (RPITIT -> opaque). This makes default trait body tests pass!
2. Fix two WF-checking bugs -- first, we want to make sure that we're always looking for an opaque type in `check_return_position_impl_trait_in_trait_bounds`. That's because the RPITIT projections are normalized to opaques during wfcheck. Second, fix RPITIT's param-envs by not adding the projection predicates that we install on trait methods to make default RPITITs work -- I left a comment why.
3. Also, just a small drive-by for `rustc_on_unimplemented`. Not sure if it affects any tests, but can't hurt.
r? ````@spastorino,```` based off of #109140
Remove box expressions from HIR
After #108516, `#[rustc_box]` is used at HIR->THIR lowering and this is no longer emitted, so it can be removed.
This is based on top of #108471 to help with conflicts, so 43490488ccacd1a822e9c621f5ed6fca99959a0b is the only relevant commit (sorry for all the duplicated pings!)
````@rustbot```` label +S-blocked
Some cleanups in our normalization logic
Changed a match to be exhaustive and deduplicated some code.
r? ```@compiler-errors```
this pulls out the uncontroversial part of https://github.com/rust-lang/rust/pull/108860
make `define_opaque_types` fully explicit
based on the idea of #108389. Moved `define_opaque_types` into the actual operations, e.g. `eq`, instead of `infcx.at` because normalization doesn't use `define_opaque_types` and even creates it's own `At` with a different `define_opaque_types` internally.
Somewhat surprisingly, coherence actually relies on `DefineOpaqueTypes::Yes` for soundness which was revealed because I've incorrectly used `DefineOpaqueTypes::No` in `equate_impl_headers`. It feels concerning that even though this is the case, we still sometimes use `DefineOpaqueTypes::No` in coherence. I did not look into this as part of this PR as it is purely changing the structure of the code without changing behavior in any way.
r? ```@oli-obk```
Remove some direct calls to local_def_id_to_hir_id on diagnostics
Was playing with `tests/ui/impl-trait/in-trait/default-body-with-rpit.rs` and was able to remove some ICEs. Still getting ...
```
error[E0277]: `impl Future<Output = Foo::{opaque#0}>` is not a future
--> tests/ui/impl-trait/in-trait/default-body-with-rpit.rs:10:28
|
10 | async fn baz(&self) -> impl Debug {
| ^^^^^^^^^^ `impl Future<Output = Foo::{opaque#0}>` is not a future
|
= help: the trait `Future` is not implemented for `impl Future<Output = Foo::{opaque#0}>`
= note: impl Future<Output = Foo::{opaque#0}> must be a future or must implement `IntoFuture` to be awaited
note: required by a bound in `Foo::{opaque#1}`
--> tests/ui/impl-trait/in-trait/default-body-with-rpit.rs:10:28
|
10 | async fn baz(&self) -> impl Debug {
| ^^^^^^^^^^ required by this bound in `Foo::{opaque#1}`
error[E0277]: the size for values of type `impl Future<Output = Foo::{opaque#0}>` cannot be known at compilation time
--> tests/ui/impl-trait/in-trait/default-body-with-rpit.rs:10:28
|
10 | async fn baz(&self) -> impl Debug {
| ^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `impl Future<Output = Foo::{opaque#0}>`
note: required by a bound in `Foo::{opaque#1}`
--> tests/ui/impl-trait/in-trait/default-body-with-rpit.rs:10:28
|
10 | async fn baz(&self) -> impl Debug {
| ^^^^^^^^^^ required by this bound in `Foo::{opaque#1}`
error: internal compiler error: compiler/rustc_hir_typeck/src/closure.rs:724:18: async fn generator return type not an inference variable: Foo::{opaque#1}<'_>
--> tests/ui/impl-trait/in-trait/default-body-with-rpit.rs:10:39
|
10 | async fn baz(&self) -> impl Debug {
| _______________________________________^
11 | | ""
12 | | }
| |_____^
```
But I guess this is a little bit of progress anyway.
This one goes on top of #108700 and #108945
r? `@compiler-errors`
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.
Add suggestion to diagnostic when user has array but trait wants slice. (rebased)
Rebase of #91314, except for change to multipart suggestion
Resolves#90528
r? ``@compiler-errors`` since you requested the multipart suggestion
tidy: enforce comment blocks to have an even number of backticks
After PR #108694, most unmatched backticks in `compiler/` comments have been eliminated. This PR adds a tidy lint to ensure no new unmatched backticks are added, and either addresses the lint in the remaining instances it found, or allows it.
Very often, backtick containing sections wrap around lines, for example:
```Rust
// This function takes a tuple `(Vec<String>,
// Box<[u8]>)` and transforms it into `Vec<u8>`.
```
The lint is implemented to work on top of blocks, counting each line with a `//` into a block, and counting if there are an odd or even number of backticks in the entire block, instead of looking at just a single line.
This makes it easier to open the messages file while developing on features.
The commit was the result of automatted changes:
for p in compiler/rustc_*; do mv $p/locales/en-US.ftl $p/messages.ftl; rmdir $p/locales; done
for p in compiler/rustc_*; do sed -i "s#\.\./locales/en-US.ftl#../messages.ftl#" $p/src/lib.rs; done
Implement goal caching with the new solver
Maybe it's wrong, idk. Opening mostly for first impressions before I go to sleep.
r? ``@lcnr,`` cc ``@cjgillot``
Don't even try to combine consts with incompatible types
~I left a more detailed explanation for why this fixes this issue in the UI test, but in general, we should not try to unify const infer vars and rigid consts if they have incompatible types. That's because we don't want something like a `ConstArgHasType` predicate to suddenly go from passing to failing, or vice versa, due to a shallow resolve.~
1. Use the `type_of` for a parameter in `try_eval_lit_or_param`, instead of the "expected" type from a `WithOptConstParam` def id.
2. Don't combine consts that have incompatible types.
Fixes#108781
Do not ICE when we have fn pointer `Fn` obligations with bound vars in the self type
We never supported solving `for<'a> fn(&'a ()): Fn(&'a ())` -- I tried to add that support in #104929, but iirc `@lcnr` wanted to support this more generally by eagerly instantiating trait predicate binders with placeholders. That never happened due to blockers in the old solver, but we probably shouldn't ICE in any case.
On the bright side, this passes on the new solver :^)
Emit alias-eq when equating numeric var and projection
This doesn't fix everything having to do with projections and infer vars, but it does fix a common case I saw in HIR typeck.
r? `@lcnr`
Remove `body_def_id` from `Inherited`
We can just use the body id from the obligation cause.
Follow-up to #108945, only my commit is relevant.
r? `@cjgillot` cc `@spastorino`
Rollup of 8 pull requests
Successful merges:
- #108754 (Retry `pred_known_to_hold_modulo_regions` with fulfillment if ambiguous)
- #108759 (1.41.1 supported 32-bit Apple targets)
- #108839 (Canonicalize root var when making response from new solver)
- #108856 (Remove DropAndReplace terminator)
- #108882 (Tweak E0740)
- #108898 (Set `LIBC_CHECK_CFG=1` when building Rust code in bootstrap)
- #108911 (Improve rustdoc-gui/tester.js code a bit)
- #108916 (Remove an unused return value in `rustc_hir_typeck`)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Canonicalize root var when making response from new solver
During trait solving, if we equate two inference variables `?0` and `?1` but don't equate them with any rigid types, then `InferCtxt::probe_ty_var` will return `Err` for both of these. The canonicalizer code will then canonicalize the variables independently(!), and the response will not reflect the fact that these two variables have been made equal.
This hinders inference and I also don't think it's sound? I haven't thought too much about it past that, so let's talk about it.
r? ``@lcnr``
Retry `pred_known_to_hold_modulo_regions` with fulfillment if ambiguous
Fixes#108721
The problem here is that when we're checking `is_sized_raw` during codegen on some type that has a lot of opaques in it, something emits several nested obligations that are individually ambiguous, but when processed together in a loop then apply modulo regions. Since the `evaluate_predicates_recursively` inner loop doesn't process predicates until they stop changing, we return `EvaluatedToAmbig`, which makes the sized check return false incorrectly. See:
f15f0ea739/compiler/rustc_trait_selection/src/traits/select/mod.rs (L596-L606)
... Compared to the analogous loop in the new solver:
f15f0ea739/compiler/rustc_trait_selection/src/solve/mod.rs (L481-L512)
To fix this, if we get ambiguous during `pred_known_to_hold_modulo_regions`, just retry the obligation in a fulfillment context.
--
Unfortunately... I don't have a test for this. I've only tested this locally. Pending minimization :/
r? types
Suppress copy impl error when post-normalized type references errors
Suppress spurious errors from the `Copy` impl validity check when fields have bad types *post*-normalization, instead of just pre-normalization.
----
The const-generics test regressed recently due to #107965, cc `````@BoxyUwU.`````
* I think it's because `[_; 0u32]: Copy` now fails to hold because a nested obligation `ConstArgHasType(0u32, usize)` fails.
* It's interesting that `[const_error]` shows up in the type only after normalization, though, but I'm pretty sure that it's due to the evaluate call that happens when normalizing unevaluated consts.
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.
always resolve to universal regions if possible
`RegionConstraintCollector::opportunistic_resolve_var`, which is used in canonicalization and projection logic, doesn't resolve the region var to an equal universal region. So if we have equated `'static == '1 == '2`, it doesn't resolve `'1` or `'2` to `'static`. Now it does!
Addresses review comment https://github.com/rust-lang/rust/pull/107376#discussion_r1093233687.
r? `@lcnr`
rustc_middle: Remove trait `DefIdTree`
This trait was a way to generalize over both `TyCtxt` and `Resolver`, but now `Resolver` has access to `TyCtxt`, so this trait is no longer necessary.
Don't project specializable RPITIT projection
This effective rejects specialization + RPITIT/AFIT (usages of `impl Trait` in traits) because the implementation is significantly complicated over making regular "default" trait method bodies work.
I have another PR that experimentally fixes all this, but the code may not be worth investing in.
Treat `str` as containing `[u8]` for auto trait purposes
Wanted to gauge ``@rust-lang/lang`` and ``@rust-lang/types`` teams' thoughts on treating `str` as "containing" a `[u8]` slice for auto-trait purposes.
``@dtolnay`` brought this up in https://github.com/rust-lang/rust/issues/13231#issuecomment-1399386472 as a blocker for future `str` type librarification, and I think it's both a valid concern and very easy to fix. I'm interested in actually doing that `str` type librarification (#107939), but this probably should be considered in the mean time regardless of that PR.
r? types for the impl, though this definitely needs an FCP.
(This is a large commit. The changes to
`compiler/rustc_middle/src/ty/context.rs` are the most important ones.)
The current naming scheme is a mess, with a mix of `_intern_`, `intern_`
and `mk_` prefixes, with little consistency. In particular, in many
cases it's easy to use an iterator interner when a (preferable) slice
interner is available.
The guiding principles of the new naming system:
- No `_intern_` prefixes.
- The `intern_` prefix is for internal operations.
- The `mk_` prefix is for external operations.
- For cases where there is a slice interner and an iterator interner,
the former is `mk_foo` and the latter is `mk_foo_from_iter`.
Also, `slice_interners!` and `direct_interners!` can now be `pub` or
non-`pub`, which helps enforce the internal/external operations
division.
It's not perfect, but I think it's a clear improvement.
The following lists show everything that was renamed.
slice_interners
- const_list
- mk_const_list -> mk_const_list_from_iter
- intern_const_list -> mk_const_list
- substs
- mk_substs -> mk_substs_from_iter
- intern_substs -> mk_substs
- check_substs -> check_and_mk_substs (this is a weird one)
- canonical_var_infos
- intern_canonical_var_infos -> mk_canonical_var_infos
- poly_existential_predicates
- mk_poly_existential_predicates -> mk_poly_existential_predicates_from_iter
- intern_poly_existential_predicates -> mk_poly_existential_predicates
- _intern_poly_existential_predicates -> intern_poly_existential_predicates
- predicates
- mk_predicates -> mk_predicates_from_iter
- intern_predicates -> mk_predicates
- _intern_predicates -> intern_predicates
- projs
- intern_projs -> mk_projs
- place_elems
- mk_place_elems -> mk_place_elems_from_iter
- intern_place_elems -> mk_place_elems
- bound_variable_kinds
- mk_bound_variable_kinds -> mk_bound_variable_kinds_from_iter
- intern_bound_variable_kinds -> mk_bound_variable_kinds
direct_interners
- region
- intern_region (unchanged)
- const
- mk_const_internal -> intern_const
- const_allocation
- intern_const_alloc -> mk_const_alloc
- layout
- intern_layout -> mk_layout
- adt_def
- intern_adt_def -> mk_adt_def_from_data (unusual case, hard to avoid)
- alloc_adt_def(!) -> mk_adt_def
- external_constraints
- intern_external_constraints -> mk_external_constraints
Other
- type_list
- mk_type_list -> mk_type_list_from_iter
- intern_type_list -> mk_type_list
- tup
- mk_tup -> mk_tup_from_iter
- intern_tup -> mk_tup
Use `tcx.ty_error_with_guaranteed` in more places, rename variants
1. Use `ty_error_with_guaranteed` more so we don't delay so many span bugs
2. Rename `ty_error_with_guaranteed` to `ty_error`, `ty_error` to `ty_error_misc`. This is to incentivize using the former over the latter in cases where we already are witness to a `ErrorGuaranteed` token.
Second commit is just name replacement, so the first commit can be reviewed on its own with more scrutiny.
Use associated type bounds in some places in the compiler
Use associated type bounds for some nested `impl Trait<Assoc = impl Trait2>` cases. I'm generally keen to introduce new lang features that are more mature into the compiler, but maybe let's see what others think?
Side-note: I was surprised that the only use-cases of nested impl trait in the compiler are just iterator related?!
Remove type-traversal trait aliases
#107924 moved the type traversal (folding and visiting) traits into the type library, but created trait aliases in `rustc_middle` to minimise both the API churn for trait consumers and the arising boilerplate. As mentioned in that PR, an alternative approach of defining subtraits with blanket implementations of the respective supertraits was also considered at that time but was ruled out as not adding much value.
Unfortunately, it has since emerged that rust-analyzer has difficulty with these trait aliases at present, resulting in a degraded contributor experience (see the recent [r-a has become useless](https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/r-a.20has.20become.20useless) topic on the #t-compiler/help Zulip stream).
This PR removes the trait aliases, and accordingly the underlying type library traits are now used directly; they are parameterised by `TyCtxt<'tcx>` rather than just the `'tcx` lifetime, and imports have been updated to reflect the fact that the trait aliases' explicitly named traits are no longer automatically brought into scope. These changes also roll-back the (no-longer required) workarounds to #107747 that were made in b409329c62.
Since this PR is just a find+replace together with the changes necessary for compilation & tidy to pass, it's currently just one mega-commit. Let me know if you'd like it broken up.
r? `@oli-obk`
errors: generate typed identifiers in each crate
Instead of loading the Fluent resources for every crate in `rustc_error_messages`, each crate generates typed identifiers for its own diagnostics and creates a static which are pulled together in the `rustc_driver` crate and provided to the diagnostic emitter.
There are advantages and disadvantages to this change..
#### Advantages
- Changing a diagnostic now only recompiles the crate for that diagnostic and those crates that depend on it, rather than `rustc_error_messages` and all crates thereafter.
- This approach can be used to support first-party crates that want to supply translatable diagnostics (e.g. `rust-lang/thorin` in https://github.com/rust-lang/rust/pull/102612#discussion_r985372582, cc `@JhonnyBillM)`
- We can extend this a little so that tools built using rustc internals (like clippy or rustdoc) can add their own diagnostic resources (much more easily than those resources needing to be available to `rustc_error_messages`)
#### Disadvantages
- Crates can only refer to the diagnostic messages defined in the current crate (or those from dependencies), rather than all diagnostic messages.
- `rustc_driver` (or some other crate we create for this purpose) has to directly depend on *everything* that has error messages.
- It already transitively depended on all these crates.
#### Pending work
- [x] I don't know how to make `rustc_codegen_gcc`'s translated diagnostics work with this approach - because `rustc_driver` can't depend on that crate and so can't get its resources to provide to the diagnostic emission. I don't really know how the alternative codegen backends are actually wired up to the compiler at all.
- [x] Update `triagebot.toml` to track the moved FTL files.
r? `@compiler-errors`
cc #100717
Move some `InferCtxt` methods to `EvalCtxt` in new solver
Moving towards eventually making the `InferCtxt` within `EvalCtxt` private, so that we make sure not to do anything strange in the solver. This doesn't finish this work yet, just gets it started.
r? ``@lcnr``
Instead of loading the Fluent resources for every crate in
`rustc_error_messages`, each crate generates typed identifiers for its
own diagnostics and creates a static which are pulled together in the
`rustc_driver` crate and provided to the diagnostic emitter.
Signed-off-by: David Wood <david.wood@huawei.com>
Use DefKind to give more item kind information during BindingObligation note
The current label says "required by a bound in this". When I see that label, my immediate impression is "this... **what**?". It feels like it was cut short.
Alternative to this would be saying "in this item", but adding the item kind is strictly more informational and adds very little overhead to the existing error presentation.
Fix RPITITs in default trait methods (by assuming projection predicates in param-env)
Instead of having special projection logic that allows us to turn `ProjectionTy(RPITIT, [Self#0, ...])` into `OpaqueTy(RPITIT, [Self#0, ...])`, we can instead augment the param-env of default trait method bodies to assume these as projection predicates. This should allow us to only project where we're allowed to!
In order to make this work without introducing a bunch of cycle errors, we additionally tweak the `OpaqueTypeExpander` used by `ParamEnv::with_reveal_all_normalized` to not normalize the right-hand side of projection predicates. This should be fine, because if we use the projection predicate to normalize some other projection type, we'll continue to normalize the opaque that it gets projected to.
This also makes it possible to support default trait methods with RPITITs in an associated-type based RPITIT lowering strategy without too much extra effort.
Fixes#107002
Alternative to #108142
Fix some more `non_lifetime_binders` stuff with higher-ranked trait bounds
1. When assembling candidates for `for<T> T: Sized`, we can't ICE because the self-type is a bound type.
2. Fix an issue where, when canonicalizing in non-universe preserving mode, we don't actually set the universe for placeholders to the root even though we do the same for region vars.
3. Make `Placeholder("T")` format like `T` in error messages.
Fixes#108180Fixes#108182
r? types
This function has this line twice:
```
let bound_vars = tcx.intern_bound_variable_kinds(&bound_vars);
```
The second occurrence is effectively a no-op, because the first
occurrence interned any that needed it.
`InternIteratorElement` is a trait used to intern values produces by
iterators. There are three impls, corresponding to iterators that
produce different types:
- One for `T`, which operates straightforwardly.
- One for `Result<T, E>`, which is fallible, and will fail early with an
error result if any of the iterator elements are errors.
- One for `&'a T`, which clones the items as it iterates.
That last one is bad: it's extremely easy to use it without realizing
that it clones, which goes against Rust's normal "explicit is better"
approach to cloning.
So this commit just removes it. In practice, there weren't many use
sites. For all but one of them `into_iter()` could be used, which avoids
the need for cloning. And for the one remaining case `copied()` is
used.
There are several `mk_foo`/`intern_foo` pairs, where the former takes an
iterator and the latter takes a slice. (This naming convention is bad,
but that's a fix for another PR.)
This commit changes several `mk_foo` occurrences into `intern_foo`,
avoiding the need for some `.iter()`/`.into_iter()` calls. Affected
cases:
- mk_type_list
- mk_tup
- mk_substs
- mk_const_list
Switch to `EarlyBinder` for `type_of` query
Part of the work to finish #105779 and implement https://github.com/rust-lang/types-team/issues/78.
Several queries `X` have a `bound_X` variant that wraps the output in `EarlyBinder`. This adds `EarlyBinder` to the return type of the `type_of` query and removes `bound_type_of`.
r? `@lcnr`
Do not ICE on unmet trait alias impl bounds
Fixes#108132
I've also added some documentation to the `impl_def_id` field of `DerivedObligationCause` to try and minimise the risk of such errors in future.
r? `@compiler-errors`
Implement partial support for non-lifetime binders
This implements support for non-lifetime binders. It's pretty useless currently, but I wanted to put this up so the implementation can be discussed.
Specifically, this piggybacks off of the late-bound lifetime collection code in `rustc_hir_typeck::collect::lifetimes`. This seems like a necessary step given the fact we don't resolve late-bound regions until this point, and binders are sometimes merged.
Q: I'm not sure if I should go along this route, or try to modify the earlier nameres code to compute the right bound var indices for type and const binders eagerly... If so, I'll need to rename all these queries to something more appropriate (I've done this for `resolve_lifetime::Region` -> `resolve_lifetime::ResolvedArg`)
cc rust-lang/types-team#81
r? `@ghost`
Rollup of 7 pull requests
Successful merges:
- #106347 (More accurate spans for arg removal suggestion)
- #108057 (Prevent some attributes from being merged with others on reexports)
- #108090 (`if $c:expr { Some($r:expr) } else { None }` =>> `$c.then(|| $r)`)
- #108092 (note issue for feature(packed_bundled_libs))
- #108099 (use chars instead of strings where applicable)
- #108115 (Do not ICE on unmet trait alias bounds)
- #108125 (Add new people to the compiletest review rotation)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Optimize `mk_region`
PR #107869 avoiding some interning under `mk_ty` by special-casing `Ty` variants with simple (integer) bodies. This PR does something similar for regions.
r? `@compiler-errors`
Use `target` instead of `machine` for mir interpreter integer handling.
The naming of `machine` only makes sense from a mir interpreter internals perspective, but outside users talk about the `target` platform. As per https://github.com/rust-lang/rust/pull/108029#issuecomment-1429791015
r? `@RalfJung`
use semantic equality for const param type equality assertion
Fixes#107898
See added test for what caused this ICE
---
The current in assertion in `relate.rs` is rather inadequate when keeping in mind future expansions to const generics:
- it will ICE when there are infer vars in a projection in a const param ty
- it will spurriously return false when either ty has infer vars because of using `==` instead of `infcx.at(..).eq`
- i am also unsure if it would be possible with `adt_const_params` to craft a situation where the const param type is not wf causing `normalize_erasing_regions` to `bug!` when we would have emitted a diagnostic.
This impl feels pretty Not Great to me although i am not sure what a better idea would be.
- We have to have the logic behind a query because neither `relate.rs` or `combine.rs` have access to trait solving machinery (without evaluating nested obligations this assert will become _far_ less useful under lazy norm, which consts are already doing)
- `relate.rs` does not have access to canonicalization machinery which is necessary in order to have types potentially containing infer vars in query arguments.
We could possible add a method to `TypeRelation` to do this assertion rather than a query but to avoid implementing the same logic over and over we'd probably end up with the logic in a free function somewhere in `rustc_trait_selection` _anyway_ so I don't think that would be much better.
We could also just remove this assertion, it should not actually be necessary for it to be present. It has caught some bugs in the past though so if possible I would like to keep it.
r? `@compiler-errors`
Much like there are specialized variants of `mk_ty`. This will enable
some optimization in the next commit.
Also rename the existing `re_error*` functions as `mk_re_error*`, for
consistency.
add an unstable `#[rustc_coinductive]` attribute
useful to test coinduction, especially in the new solver.
as this attribute should remain permanently unstable I don't think this needs any official approval. cc ``@rust-lang/types``
had to weaken the check for stable query results in the solver to prevent an ICE if there's a coinductive cycle with constraints.
r? ``@compiler-errors``
Rollup of 9 pull requests
Successful merges:
- #105019 (Add parentheses properly for borrowing suggestion)
- #106001 (Stop at the first `NULL` argument when iterating `argv`)
- #107098 (Suggest function call on pattern type mismatch)
- #107490 (rustdoc: remove inconsistently-present sidebar tooltips)
- #107855 (Add a couple random projection tests for new solver)
- #107857 (Add ui test for implementation on projection)
- #107878 (Clarify `new_size` for realloc means bytes)
- #107888 (revert #107074, add regression test)
- #107900 (Zero the `REPARSE_MOUNTPOINT_DATA_BUFFER` header)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
correctly update goals in the cache
we may want to actually write the response for our goal into the provisional or global cache instead of simply using the result from the last iteration '^^
r? ```@rust-lang/initiative-trait-system-refactor```
Rename `replace_bound_vars_with_*` to `instantiate_binder_with_*`
Mentioning "binder" rather than "bound vars", imo, makes it clearer that we're doing something to the binder as a whole.
Also, "instantiate" is the verb that I'm always reaching for when I'm looking for these functions, and the name that we use in the new solver anyways.
r? types
Rename `PointerSized` to `PointerLike`
The old name was unnecessarily vague. This PR renames a nightly language feature that I added, so I don't think it needs any additional approval, though anyone can feel free to speak up if you dislike the rename.
It's still unsatisfying that we don't the user which of {size, alignment} is wrong, but this trait really is just a stepping stone for a more generalized mechanism to create `dyn*`, just meant for nightly testing, so I don't think it really deserves additional diagnostic machinery for now.
Fixes#107696, cc ``@RalfJung``
r? ``@eholk``
Modify existing bounds if they exist
Fixes#107335.
This implementation is kinda gross but I don't really see a better way to do it.
This primarily does two things: Modifies `suggest_constraining_type_param` to accept a new parameter that indicates a span to be replaced instead of added, if presented, and limit the additive suggestions to either suggest a new bound on an existing bound (see newly added unit test) or add the generics argument if a generics argument wasn't found.
The former change is required to retain the capability to add an entirely new bounds if it was entirely omitted.
r? ``@compiler-errors``
Refine error spans for "The trait bound `T: Trait` is not satisfied" when passing literal structs/tuples
This PR adds a new heuristic which refines the error span reported for "`T: Trait` is not satisfied" errors, by "drilling down" into individual fields of structs/enums/tuples to point to the "problematic" value.
Here's a self-contained example of the difference in error span:
```rs
struct Burrito<Filling> {
filling: Filling,
}
impl <Filling: Delicious> Delicious for Burrito<Filling> {}
fn eat_delicious_food<Food: Delicious>(food: Food) {}
fn will_type_error() {
eat_delicious_food(Burrito { filling: Kale });
// ^~~~~~~~~~~~~~~~~~~~~~~~~ (before) The trait bound `Kale: Delicious` is not satisfied
// ^~~~ (after) The trait bound `Kale: Delicious` is not satisfied
}
```
(kale is fine, this is just a silly food-based example)
Before this PR, the error span is identified as the entire argument to the generic function `eat_delicious_food`. However, since only `Kale` is the "problematic" part, we can point at it specifically. In particular, the primary error message itself mentions the missing `Kale: Delicious` trait bound, so it's much clearer if this part is called out explicitly.
---
The _existing_ heuristic tries to label the right function argument in `point_at_arg_if_possible`. It goes something like this:
- Look at the broken base trait `Food: Delicious` and find which generics it mentions (in this case, only `Food`)
- Look at the parameter type definitions and find which of them mention `Filling` (in this case, only `food`)
- If there is exactly one relevant parameter, label the corresponding argument with the error span, instead of the entire call
This PR extends this heuristic by further refining the resulting expression span in the new `point_at_specific_expr_if_possible` function. For each `impl` in the (broken) chain, we apply the following strategy:
The strategy to determine this span involves connecting information about our generic `impl`
with information about our (struct) type and the (struct) literal expression:
- Find the `impl` (`impl <Filling: Delicious> Delicious for Burrito<Filling>`)
that links our obligation (`Kale: Delicious`) with the parent obligation (`Burrito<Kale>: Delicious`)
- Find the "original" predicate constraint in the impl (`Filling: Delicious`) which produced our obligation.
- Find all of the generics that are mentioned in the predicate (`Filling`).
- Examine the `Self` type in the `impl`, and see which of its type argument(s) mention any of those generics.
- Examing the definition for the `Self` type, and identify (for each of its variants) if there's a unique field
which uses those generic arguments.
- If there is a unique field mentioning the "blameable" arguments, use that field for the error span.
Before we do any of this logic, we recursively call `point_at_specific_expr_if_possible` on the parent
obligation. Hence we refine the `expr` "outwards-in" and bail at the first kind of expression/impl we don't recognize.
This function returns a `Result<&Expr, &Expr>` - either way, it returns the `Expr` whose span should be
reported as an error. If it is `Ok`, then it means it refined successfull. If it is `Err`, then it may be
only a partial success - but it cannot be refined even further.
---
I added a new test file which exercises this new behavior. A few existing tests were affected, since their error spans are now different. In one case, this leads to a different code suggestion for the autofix - although the new suggestion isn't _wrong_, it is different from what used to be.
This change doesn't create any new errors or remove any existing ones, it just adjusts the spans where they're presented.
---
Some considerations: right now, this check occurs in addition to some similar logic in `adjust_fulfillment_error_for_expr_obligation` function, which tidies up various kinds of error spans (not just trait-fulfillment error). It's possible that this new code would be better integrated into that function (or another one) - but I haven't looked into this yet.
Although this code only occurs when there's a type error, it's definitely not as efficient as possible. In particular, there are definitely some cases where it degrades to quadratic performance (e.g. for a trait `impl` with 100+ generic parameters or 100 levels deep nesting of generic types). I'm not sure if these are realistic enough to worry about optimizing yet.
There's also still a lot of repetition in some of the logic, where the behavior for different types (namely, `struct` vs `enum` variant) is _similar_ but not the same.
---
I think the biggest win here is better targeting for tuples; in particular, if you're using tuples + traits to express variadic-like functions, the compiler can't tell you which part of a tuple has the wrong type, since the span will cover the entire argument. This change allows the individual field in the tuple to be highlighted, as in this example:
```
// NEW
LL | want(Wrapper { value: (3, q) });
| ---- ^ the trait `T3` is not implemented for `Q`
// OLD
LL | want(Wrapper { value: (3, q) });
| ---- ^~~~~~~~~~~~~~~~~~~~~~~~~ the trait `T3` is not implemented for `Q`
```
Especially with large tuples, the existing error spans are not very effective at quickly narrowing down the source of the problem.
This now uses `node_to_string` for both missing and seen Ids, which includes
the snippet of code for which the Id was allocated.
Also removes the duplicated printing of `HirId`, as `node_to_string` includes that already.
Similarly, changes all other users of `node_to_string` that do so, and changes the output of `node_to_string`, which is now "$hirid ($what `$span` in $path)".
Track bound types like bound regions
When we instantiate bound types into placeholder types, we throw away the names for some reason. These names are particularly useful for error reporting once we have `for<T>` binders.
r? types
small refactor to new projection code
extract `eq_term_and_make_canonical_response` into a helper function which also is another guarantee that the expected term does not influence candidate selection for projections.
also change `evaluate_all(vec![single_goal])` to use `evaluate_goal`.
the second commit now also adds a `debug_assert!` to `evaluate_goal`.
Modify primary span label for E0308
Looking at the reactions to https://hachyderm.io/`@ekuber/109622160673605438,` a lot of people seem to have trouble understanding the current output, where the primary span label on type errors talks about the specific types that diverged, but these can be deeply nested type parameters. Because of that we could see "expected i32, found u32" in the label while the note said "expected Vec<i32>, found Vec<u32>". This understandably confuses people. I believe that once people learn to read these errors it starts to make more sense, but this PR changes the output to be more in line with what people might expect, without sacrificing terseness.
Fix#68220.
Use `ObligationCtxt::new_in_snapshot` in `satisfied_from_param_env`
We can evaluate nested `ConstEvaluatable` obligations in an evaluation probe, which will ICE if we use `ObligationCtxt::new`.
Fixes#107474Fixes#106666
r? `@BoxyUwU` but feel free to reassign
cc `@JulianKnodt` who i think added this assertion code
Not sure if the rustdoc test is needed, but can't hurt. They're the same root cause, though.
Skip possible where_clause_object_safety lints when checking `multiple_supertrait_upcastable`
Fix#106247
To achieve this, I lifted the `WhereClauseReferencesSelf` out from `object_safety_violations` and move it into `is_object_safe` (which is changed to a new query).
cc `@dtolnay`
r? `@compiler-errors`
Remove HirId -> LocalDefId map from HIR.
Having this map in HIR prevents the creating of new definitions after HIR has been built.
Thankfully, we do not need it.
Based on https://github.com/rust-lang/rust/pull/103902
Remove `ControlFlow::{BREAK, CONTINUE}`
Libs-API decided to remove these in #102697.
Follow-up to #107023, which removed them from `compiler/`, but a couple new ones showed up since that was merged.
r? libs
Minor tweaks in the new solver
1. `InferCtxt::probe` is not needed in `compute_subtype_goal` and `compute_well_formed_goal`.
2. Add a handful of comments.
3. Add a micro-optimization in `consider_assumption` where we check the def-ids of the assumption and goal match before instantiating any binders.
r? ``@lcnr``
Correct suggestions for closure arguments that need a borrow
Fixes#107301 by dealing with binders correctly
Fixes another issue where we were suggesting adding just `&` when we expected `&mut _` in a closure arg
Use new solver in `evaluate_obligation` query (when new solver is enabled)
(only when `-Ztrait-solver=next`, of course)
... Does this make sense? It seems to me like it should be reasonable, but maybe there's some reason why this is a bad idea.
r? ``@lcnr``
Needs a perf run because I guess this `solver == TraitSolver::Next` check is on a hot path.
Libs-API decided to remove these in #102697.
Follow-up to #107023, which removed them from `compiler/`, but a couple new ones showed up since that was merged.
Compute generator saved locals on MIR
Generators are currently type-checked by introducing a `witness` type variable, which is unified with a `GeneratorWitness(captured types)` whose purpose is to ensure that the auto traits correctly migrate from the captured types to the `witness` type. This requires computing the captured types on HIR during type-checking, only to re-do it on MIR later.
This PR proposes to drop the HIR-based computation, and only keep the MIR one. This is done in 3 steps.
1. During type-checking, the `witness` type variable is never unified. This allows to stall all the obligations that depend on it until the end of type-checking. Then, the stalled obligations are marked as successful, and saved into the typeck results for later verification.
2. At type-checking writeback, `witness` is replaced by `GeneratorWitnessMIR(def_id, substs)`. From this point on, all trait selection involving `GeneratorWitnessMIR` will fetch the MIR-computed locals, similar to what opaque types do. There is no lifetime to be preserved here: we consider all the lifetimes appearing in this witness type to be higher-ranked.
3. After borrowck, the stashed obligations are verified against the actually computed types, in the `check_generator_obligations` query. If any obligation was wrongly marked as fulfilled in step 1, it should be reported here.
There are still many issues:
- ~I am not too happy having to filter out some locals from the checked bounds, I think this is MIR building that introduces raw pointers polluting the analysis;~ solved by a check specific to static variables.
- the diagnostics for captured types don't show where they are used/dropped;
- I do not attempt to support chalk.
cc `@eholk` `@jyn514` for the drop-tracking work
r? `@oli-obk` as you warned me of potential unsoundness
solver comments + remove `TyCtxt::evaluate_goal`
from the `RustcContributor::explore` session yesterday.
This also removes `TyCtxt::evaluate_goal` because to canonicalize you have to use an `InferCtxt` anyways at which point we should just always get people to use `evaluate_root_goal`.
r? ``@spastorino``
ICE in new solver if we see an inference variable
By construction, we do not expect to see any `ty::Infer(ty::TyVar(_))` inference types in the solver (we treat this as ambiguous, since we need to be able to structurally resolve the self type at least one layer to assemble candidates for it). Additionally, since we're doing no freshening, we also don't expect to see any fresh vars of any kind in the solver.
Let's make that an ICE so we can catch any mistakes.
When #107282 lands, we should also ICE there too if we see a non-int/float infer.
r? `@lcnr`
use `LocalDefId` instead of `HirId` in trait resolution to simplify the obligation clause resolution
This commit introduces a refactoring suggested by `@lcnr` to simplify the obligation clause resolution.
This is just the first PR that introduces a type of refactoring, but others PRs will follow this to introduce name changing to change from the variable name from `body_id` to something else.
Fixes https://github.com/rust-lang/rust/issues/104827
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
`@rustbot` r? `@lcnr`
use LocalDefId instead of HirId in trait resolution to simplify
the obligation clause resolution
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
Implement some more new solver candidates and fix some bugs
First, fix some bugs:
1. `IndexVec::drain_enumerated(a..b)` does not give us an iterator of index keys + items enumerated from `a..b`, but from `0..(b-a)`... That caused a bug. See first commit for the fix.
2. Implement the `_: Trait` ambiguity hack. I put it in assemble, let me know if it should live elsewhere. This is important, since we otherwise consider `_: Sized` to have no solutions, and nothing passes!
3. Swap `Ambiguity` and `Unimplemented` cases for the new solver. Sorry for accidentally swapping them 😄
4. Check GATs' own predicates during projection confirmation.
Then implement a few builtin traits:
5. Implement `PointerSized`. Pretty independent.
6. Implement `Fn` family of traits for fnptr, fndef, and closures. Closures are currently broken because `FulfillCtxt::relationships` is intentionally left unimplemented. See comment in the test.
r? ```@lcnr```
Rollup of 8 pull requests
Successful merges:
- #106783 (Recover labels written as identifiers)
- #106973 (Don't treat closures from other crates as local)
- #106979 (Document how to get the type of a default associated type)
- #107053 (signal update string representation for haiku.)
- #107058 (Recognise double-equals homoglyph)
- #107067 (Custom MIR: Support storage statements)
- #107076 (Added const-generic ui test case for issue #106419)
- #107091 (Fix broken format strings in `infer.ftl`)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Don't treat closures from other crates as local
fixes#104817
r? `@lcnr`
Specialization can prefer an impl for an opaque type over a blanket impls that also matches. If the blanket impl only applies if an auto-trait applies, we look at the hidden type of the opaque type to see if that implements the auto trait. The hidden type can be a closure or generator, and thus we will end up seeing these types in coherence and have to handle them properly.
Stop using `BREAK` & `CONTINUE` in compiler
Switching them to `Break(())` and `Continue(())` instead.
Entirely search-and-replace, though there's one spot where rustfmt insisted on a reformatting too.
libs-api would like to remove these constants (https://github.com/rust-lang/rust/pull/102697#issuecomment-1385705202), so stop using them in compiler to make the removal PR later smaller.
Switching them to `Break(())` and `Continue(())` instead.
libs-api would like to remove these constants, so stop using them in compiler to make the removal PR later smaller.
Switch to `EarlyBinder` for `item_bounds` query
Part of the work to finish #105779 (also see https://github.com/rust-lang/types-team/issues/78).
Several queries `X` have a `bound_X` variant that wraps the output in `EarlyBinder`. This adds `EarlyBinder` to the return type of the `item_bounds` query and removes `bound_item_bounds`.
r? `@lcnr`
new trait solver: rebase impl substs for gats correctly
you might've caught this while working on projection code, if so then you can close this pr
r? `@lcnr`
Rework some `predicates_of`/`{Generic,Instantiated}Predicates` code
1. Make `instantiate_own` return an iterator, since it's a bit more efficient and easier to work with
2. Remove `bound_{explicit,}_predicates_of` -- these `bound_` methods in particular were a bit awkward to work with since `ty::GenericPredicates` *already* acts kinda like an `EarlyBinder` with its own `instantiate_*` methods, and had only a few call sites anyways.
3. Implement `IntoIterator` for `InstantiatedPredicates`, since it's *very* commonly being `zip`'d together.
Implement some FIXME methods in the new trait solver
Implement just enough of the solver's response logic to make it not ICE.
Also, fix a bug with `no_bound_vars` call failing due to canonical bound vars.
r? `@lcnr`
Consolidate two almost duplicated fn info extraction routines
Moves `extract_callable_info` up to trait selection, because it was being (almost) duplicated fully there for similar diagnostic purposes. This also generalizes the diagnostics we can give slightly (see UI test).
Rollup of 8 pull requests
Successful merges:
- #105526 (libcore: make result of iter::from_generator Clone)
- #106563 (Fix `unused_braces` on generic const expr macro call)
- #106661 (Stop probing for statx unless necessary)
- #106820 (Deprioritize fulfillment errors that come from expansions.)
- #106828 (rustdoc: remove `docblock` class from notable trait popover)
- #106849 (Allocate one less vec while parsing arrays)
- #106855 (rustdoc: few small cleanups)
- #106860 (Remove various double spaces in the libraries.)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Switch to `EarlyBinder` for `const_param_default` and `impl_trait_ref` queries
Part of the work to close#105779 and implement https://github.com/rust-lang/types-team/issues/78.
Several queries `X` have a `bound_X` variant that wraps the output in `EarlyBinder`. This PR adds `EarlyBinder` to the return type of `const_param_default` and `impl_trait_ref`, and removes their `bound_X` variants.
r? `@lcnr`
I encountered an instance where an `FnPtr` implemented a trait, but I was passing an `FnDef`. To
the end user, there is really no way to differentiate each of them, but it is necessary to cast
to the generic function in order to compile. It is thus useful to suggest `as` in the help note,
(even if the Fn output implements the trait).
Rename `Ty::is_ty_infer` -> `Ty::is_ty_or_numeric_infer`
Makes sure people are aware that they may have a type variable *or* an int/float variable.
r? `@oli-obk` https://github.com/rust-lang/rust/pull/106322#issuecomment-1376913539 but I could instead implement your solution, let me know.
(This will conflict with #106322 for now, ignore that 😄)
Handle inference variables in `CollectAllMismatches` correctly
1. Fix#106240
2. Treat int/float type variables correctly (see `src/test/ui/iterators/invalid-iterator-chain-with-int-infer.rs`), so we can point out things like "`Iterator::Item` changed to `{integer}` here"
Move autoderef to `rustc_hir_analysis`
Not sure if this is a change we actually want, but autoderef really is only (functionally) used by `rustc_hir_analysis` and `rustc_hir_typeck`, so it probably should live there.
Instead, implement a separate autoderef helper in `TypeErrCtxt` for the one use-case that goes against the ordering of the crate graph..
Clean up `OnUnimplementedFormatString::verify`
Lift the always-allowed symbols to a static array and replace a `match iter().find(...)` with `iter().any(...)`
Prefer non-`[type error]` candidates during selection
Fixes#102130Fixes#106351
r? types
note: Alternatively we could filter out error where-clauses during param-env construction? But we still need to filter out impls with errors during `match_impl`, I think.
Note predicate span on `ImplDerivedObligation`
Seems obvious to point out the where-clause that introduces the `ImplDerivedObligation` :)
r? `@estebank`
Check `impl`'s `where` clauses in `consider_impl_candidate` in experimental solver
Check impl's nested predicates as part of the recursive evaluate in `consider_impl_candidate`.
<sub>Unless, for some reason, these are intentionally **not** checked here -- in which case, I really don't understand where they're being checked...<sub>
r? ```@lcnr```
remove E0280
After looking at #61137 I tried my hand at E0280. I'm unable to find a reasonable example that emits the error. There are a couple of old examples that compile with the current compiler ([#26217](https://github.com/rust-lang/rust/issues/26217), [#42114](https://github.com/rust-lang/rust/issues/42114), [#27113](https://github.com/rust-lang/rust/issues/27113)) and there is a [bug with chalk](b7cdb635c4/src/test/ui/chalkify/bugs/async.rs) that makes it emit the error, with a couple more chalk bugs on zulip.
It seems like the error is supposed to be emitted from unfulfilled where bounds, of which two are related to borrow checking (error in where T: 'a or where 'a: 'b) and thus tend to emit errors like "lifetime may not live long enough" from borrow checking instead. The final case is with type equality constraints (where <T as Iterator>::Item == u32), which is unimplemented ([#20041](https://github.com/rust-lang/rust/issues/20041)). That such different problems are supposed to have the same error code also seems strange to me.
Since the error seems to only be emitted when using chalk I propose to remove it and replace it with an ICE instead. A crater run might be warranted.
Pinging `@jackh726` due to removal of chalk test that now ICEs.
Simplify some canonical type alias names
* delete the `Canonicalized<'tcx>` type alias in favor for `Canonical<'tcx>`
* `CanonicalizedQueryResponse` -> `CanonicalQueryResponse`
I don't particularly care about the latter, but it should be consistent. We could alternatively delete the first alias and rename the struct to `Canonicalized`, and then keep the name of `CanonicalizedQueryResponse` untouched.
Remove invalid case for mutable borrow suggestion
If we have a call such as `foo(&mut buf)` and after reference
collapsing the type is inferred as `&T` where-as the required type is
`&mut T`, don't suggest `foo(&mut mut buf)`. This is wrong syntactically
and the issue lies elsewhere, not in the borrow.
Fixes#105645
Simplify match statement
Add multiple tests
- 1 test for checking `N + 1 + 1` does not unify with `N+1`
- 2 tests for checking that a function that uses two parameters only returns the parameter that
is actually used.
- Check exact repeat predicates
Instead of just switching to a probe, check for different matches, and see how many there are.
If one, unify it, otherwise return true and let it be unified later.
fix [type error] for error E0029 and E0277
check explicitly for the type references error
if ty.references_error() is true change the error to be err.delay_as_bug() and prevent the error E0029 and E0277 from emitting out this fix#105946
check explicitly for the type references error
if ty.references_error() is true change the error to be err.delay_as_bug()
and prevent the error E0029 and E0277 from emitting out
this fix#105946
Rollup of 6 pull requests
Successful merges:
- #105846 (Account for return-position `impl Trait` in trait in `opt_suggest_box_span`)
- #106385 (Split `-Zchalk` flag into `-Ztrait-solver=(classic|chalk|next)` flag)
- #106403 (Rename `hir::Map::{get_,find_}parent_node` to `hir::Map::{,opt_}parent_id`, and add `hir::Map::{get,find}_parent`)
- #106462 (rustdoc: remove unnecessary wrapper around sidebar and mobile logos)
- #106464 (Update Fuchsia walkthrough with new configs)
- #106478 (Tweak wording of fn call with wrong number of args)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Rename `hir::Map::{get_,find_}parent_node` to `hir::Map::{,opt_}parent_id`, and add `hir::Map::{get,find}_parent`
The `hir::Map::get_parent_node` function doesn't return a `Node`, and I think that's quite confusing. Let's rename it to something that sounds more like something that gets the parent hir id => `hir::Map::parent_id`. Same with `find_parent_node` => `opt_parent_id`.
Also, combine `hir.get(hir.parent_id(hir_id))` and similar `hir.find(hir.parent_id(hir_id))` function into new functions that actually retrieve the parent node in one call. This last commit is the only one that might need to be looked at closely.
Don't deduce a signature that makes a closure cyclic
Sometimes when elaborating supertrait bounds for closure signature inference, we end up deducing a closure signature that is cyclical because either a parameter or the return type references a projection mentioning `Self` that also has escaping bound vars, which means that it's not eagerly replaced with an inference variable.
Interestingly, this is not *just* related to my PR that elaborates supertrait bounds for closure signature deduction. The committed test `supertrait-hint-cycle-3.rs` shows **stable** code that is fixed by this PR:
```rust
trait Foo<'a> {
type Input;
}
impl<F: Fn(u32)> Foo<'_> for F {
type Input = u32;
}
fn needs_super<F: for<'a> Fn(<F as Foo<'a>>::Input) + for<'a> Foo<'a>>(_: F) {}
fn main() {
needs_super(|_: u32| {});
}
```
Fixes#105401Fixes#105396
r? types
Rollup of 9 pull requests
Successful merges:
- #104531 (Provide a better error and a suggestion for `Fn` traits with lifetime params)
- #105899 (`./x doc library --open` opens `std`)
- #106190 (Account for multiple multiline spans with empty padding)
- #106202 (Trim more paths in obligation types)
- #106234 (rustdoc: simplify settings, help, and copy button CSS by not reusing)
- #106236 (docs/test: add docs and a UI test for `E0514` and `E0519`)
- #106259 (Update Clippy)
- #106260 (Fix index out of bounds issues in rustdoc)
- #106263 (Formatter should not try to format non-Rust files)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Some `compare_method` tweaks
1. Make some of the comparison functions' names more regular
2. Reduce pub scope of some of the things in `compare_method`
~3. Remove some unnecessary opaque type handling code -- `InferCtxt` already is in a mode that doesn't define opaque types~
* moved to a different PR
4. Bubble up `ErrorGuaranteed` for region constraint errors in `compare_method` - Improves a redundant error message in one unit test.
5. Move the `compare_method` module to have a more general name, since it's more like `compare_impl_item` :)
6. Rename `collect_trait_impl_trait_tys`
implement the skeleton of the updated trait solver
cc ```@rust-lang/initiative-trait-system-refactor```
This is mostly following the architecture discussed in the types team meetup.
After discussing the desired changes for the trait solver, we encountered cyclic dependencies between them. Most notably between changing evaluate to be canonical and returning inference constraints. We cannot canonicalize evaluate without returning inference constraints due to coinductive cycles. However, caching inference constraints also relies on canonicalization. Implementing both of these changes at once in-place is not feasible.
This somewhat closely mirrors the current `evaluate` implementation with the following notable differences:
- it moves `project` into the core solver, allowing us to correctly deal with coinductive projections (will be required for implied bounds, perfect derive)
- it changes trait solver overflow to be non-fatal (required to backcompat breakage from changes to the iteration order of nested goals, deferred projection equality, generally very useful)
- it returns inference constraints and canonicalizes inputs and outputs (required for a lot things, most notably merging fulfill and evaluate, and deferred projection equality)
- it is implemented to work with lazy normalization
A lot of things aren't yet implemented, but the remaining FIXMEs should all be fairly self-contained and parallelizable. If the architecture looks correct and is what we want here, I would like to quickly merge this and then split the work.
r? ```@compiler-errors``` / ```@rust-lang/types``` :3
always use `anonymize_bound_vars`
Unless this is perf-sensitive, it's probably best to always use one anonymize function that does the right thing for all bound vars.
r? types
Highlight conflicting param-env candidates, again
Un-reverts #98794 (i.e. reverts #99290).
The previous time I attempted to land this PR, it was because of an incremental issue (#99233). The repro instructions in the issue is no longer manifest the ICE -- I think it's because this ambiguity code was refactored (I think by `@lcnr)` to no longer store the ambiguities in the fulfillment error, but instead recompute them on the fly.
The main motivation for trying to re-land this is that it fixes#105131 by highlighting the root-cause of the issue, which is conflicting param-env candidates:
```
error[E0283]: type annotations needed: cannot satisfy `Self: Gen<'source>`
|
note: multiple `impl`s or `where` clauses satisfying `Self: Gen<'source>` found
--> $DIR/conflicting-bounds.rs:3:1
|
LL | pub trait Gen<'source> {
| ^^^^^^^^^^^^^^^^^^^^^^
...
LL | Self: for<'s> Gen<'s, Output = T>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0283`.
```
Fixes#105131.
Fixes (again) #98786
Combine `ty::Projection` and `ty::Opaque` into `ty::Alias`
Implements https://github.com/rust-lang/types-team/issues/79.
This PR consolidates `ty::Projection` and `ty::Opaque` into a single `ty::Alias`, with an `AliasKind` and `AliasTy` type (renamed from `ty::ProjectionTy`, which is the inner data of `ty::Projection`) defined as so:
```
enum AliasKind {
Projection,
Opaque,
}
struct AliasTy<'tcx> {
def_id: DefId,
substs: SubstsRef<'tcx>,
}
```
Since we don't have access to `TyCtxt` in type flags computation, and because repeatedly calling `DefKind` on the def-id is expensive, these two types are distinguished with `ty::AliasKind`, conveniently glob-imported into `ty::{Projection, Opaque}`. For example:
```diff
match ty.kind() {
- ty::Opaque(..) =>
+ ty::Alias(ty::Opaque, ..) => {}
_ => {}
}
```
This PR also consolidates match arms that treated `ty::Opaque` and `ty::Projection` identically.
r? `@ghost`
Rollup of 7 pull requests
Successful merges:
- #105147 (Allow unsafe through inline const)
- #105438 (Move some codegen-y methods from `rustc_hir_analysis::collect` -> `rustc_codegen_ssa`)
- #105464 (Support #[track_caller] on async closures)
- #105476 (Change pattern borrowing suggestions to be verbose and remove invalid suggestion)
- #105500 (Make some diagnostics not depend on the source of what they reference being available)
- #105628 (Small doc fixes)
- #105659 (Don't require owned data in `MaybeStorageLive`)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Remove previously existing fallback that tried to give a good turbofish
suggestion, `need_type_info` is already good enough.
Special case `::<Vec<_>` suggestion for `Iterator::collect`.
If we have a call such as `foo(&mut buf)` and after reference
collapsing the type is inferred as `&T` where-as the required type is
`&mut T`, don't suggest `foo(&mut mut buf)`. This is wrong syntactically
and the issue lies elsewhere, not in the borrow.
Fixes#105645
Point out the type of associated types in every method call of iterator chains
Partially address #105184 by pointing out the type of associated types in every method call of iterator chains:
```
note: the expression is of type `Map<std::slice::Iter<'_, {integer}>, [closure@src/test/ui/iterators/invalid-iterator-chain.rs:12:18: 12:21]>`
--> src/test/ui/iterators/invalid-iterator-chain.rs:12:14
|
10 | vec![0, 1]
| ---------- this expression has type `Vec<{integer}>`
11 | .iter()
| ------ associated type `std::iter::Iterator::Item` is `&{integer}` here
12 | .map(|x| { x; })
| ^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `()` here
```
We also reduce the number of impls we mention when any of the candidates is an "exact match". This benefits the output of cases with numerics greatly.
Outstanding work would be to provide a structured suggestion for appropriate changes, like in this case detecting the spurious `;` in the closure.
When encountering an unmet obligation that affects a method chain, like
in iterator chains where one of the links has the wrong associated
type, we point at every method call and mention their evaluated
associated type at that point to give context to the user of where
expectations diverged from the code as written.
```
note: the expression is of type `Map<std::slice::Iter<'_, {integer}>, [closure@$DIR/invalid-iterator-chain.rs:12:18: 12:21]>`
--> $DIR/invalid-iterator-chain.rs:12:14
|
LL | vec![0, 1]
| ---------- this expression has type `Vec<{integer}>`
LL | .iter()
| ------ associated type `std::iter::Iterator::Item` is `&{integer}` here
LL | .map(|x| { x; })
| ^^^^^^^^^^^^^^^ associated type `std::iter::Iterator::Item` is `()` here
```
Move some queries and methods
Each commit's title should be self-explanatory. Motivated to break up some large, general files and move queries into leaf crates.
normalize before handling simple checks for evaluatability of `ty::Const`
`{{{{{{{ N }}}}}}}` is desugared into a `ConstKind::Unevaluated` for an anonymous `const` item so when calling `is_const_evaluatable` on it we skip the `ConstKind::Param(_) => Ok(())` arm which is incorrect.
Make `note_obligation_cause_code` take a `impl ToPredicate` for predicate
The only usecase that wasn't `impl ToPredicate` was noting overflow errors while revealing opaque types, which passed in an `Obligation<'tcx, Ty<'tcx>>`... Since this only happens in a `RevealAll` environment, which is after typeck (and probably primarily within `normalize_erasing_regions`) we're unlikely to display anything useful while noting this code, evidenced by the lack of UI test changes.
support `ConstKind::Expr` in `is_const_evaluatable` and `WfPredicates::compute`
Fixes#105205
Currently we haven't implemented a way to evaluate `ConstKind::Expr(Expr::Binop(Add, 1, 2))` so I just left that with a `FIXME` and a `delay_span_bug` since I have no idea how to do that and it would make this a much larger (and more complicated) PR :P
Tweak "the following other types implement trait"
When *any* of the suggested impls is an exact match, *only* show the exact matches. This is particularly relevant for integer types.
r? `@compiler-errors`