Don't call `with_reveal_all_normalized` in const-eval when `param_env` has inference vars in it
**what:** This slightly shifts the order of operations from an existing hack:
5b6ed253c4/compiler/rustc_middle/src/ty/consts/kind.rs (L225-L230)
in order to avoid calling a tcx query (`TyCtxt::reveal_opaque_types_in_bounds`, via `ParamEnv::with_reveal_all_normalized`) when a param-env has inference variables in it.
**why:** This allows us to enable fingerprinting of query keys/values outside of incr-comp in deubg mode, to make sure we catch other places where we're passing infer vars and other bad things into query keys. Currently that (bbf33836b9adfe4328aefa108c421e670a3923b7) crashes because we introduce inference vars into a param-env in the blanket-impl finder in rustdoc 😓5b6ed253c4/src/librustdoc/clean/blanket_impl.rs (L43)
See the CI failure here: https://github.com/rust-lang/rust/actions/runs/4058194838/jobs/6984834619
Deny non-lifetime bound vars in `for<..> ||` closure binders
Moves the check for illegal bound var types from astconv to resolve_bound_vars. If a binder is defined to have a type or const late-bound var that's not allowed, we'll resolve any usages to ty error or const error values, so we shouldn't ever see late-bound types or consts in places they aren't expected.
Fixes#108184Fixes#108181Fixes#108192
Don't eagerly convert principal to string
Fixes#108155
~~I haven't yet been able to reproduce the ICE in a minimal example unfortunately.~~ Added a test
Add `Clause::ConstArgHasType`
Currently the way that we check that a const arg has the correct type for the const param it is an argument for is by setting the expected type of `typeck` on the anon const of the argument to be the const param's type.
In the future for a potential `min_generic_const_exprs` we will allow providing const arguments that do not have an associated anon const that can be typeck'd which will require us to actually check that the const argument has the correct type. While it would potentially be possible to just call `eq` when creating substs this would not work if we support generics of the form `const N: T, T` (the const parameters type referencing generics declared after itself).
Additionally having `ConstArgHasType` will allow us to potentially make progress on removing the `ty` field of `Const` which may be desirable. Once progress has been made on this, `ConstArgHasType` will also be helpful in ensuring we do not make mistakes in trait/impl checking by declaring functions with the wrong const parameter types as the checks that the param env is compatible would catch it. (We have messed this up in the past, and with generic const parameter types these checks will get more complex)
There is a [document](https://hackmd.io/wuCS6CJBQ9-fWbwaW7nQRw?view) about the types of const generics that may provide some general information on this subject
---
This PR shouldn't have any impact on whether code compiles or not on stable, it primarily exists to make progress on unstable const generics features that are desirable.
There are two traits, `InternAs` and `InternIteratorElement`. I found
them confusing to use, particularly this:
```
pub fn mk_tup<I: InternAs<Ty<'tcx>, Ty<'tcx>>>(self, iter: I) -> I::Output {
iter.intern_with(|ts| self.intern_tup(ts))
}
```
where I thought there might have been two levels of interning going on
(there isn't) due to the `intern_with`/`InternAs` + `intern_tup` naming.
And then I found the actual traits and impls themselves *very*
confusing.
- `InternAs` has a single impl, for iterators, with four type variables.
- `InternAs` is only implemented for iterators because it wouldn't
really make sense to implement for any other type. And you can't
really understand the trait without seeing that single impl, which is
suspicious.
- `InternAs` is basically just a wrapper for `InternIteratorElement`
which does all the actual work.
- Neither trait actually does any interning. They just have `Intern` in
their name because they are used *by* interning code.
- There are no comments.
So this commit improves things.
- It removes `InternAs` completely. This makes the `mk_*` function
signatures slightly more verbose -- two trait bounds instead of one --
but much easier to read, because you only need to understand one trait
instead of two.
- It renames `InternIteratorElement` as `CollectAndApply`. Likewise, it
renames its method `intern_with` as `collect_and_apply`. These names
describe better what's going on: we collect the iterator elements into
a slice and then apply a function to the slice.
- It adds comments, making clear that all this is all there just to
provide an optimized version of `f(&iter.collect::<Vec<_>>())`.
It took me a couple of attempts to come up with this commit. My initial
attempt kept `InternAs` around, but renamed things and added comments,
and I wasn't happy with it. I think this version is much better. The
resulting code is shorter, despite the addition of the comments.
`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`
Factor query arena allocation out from query caches
This moves the logic for arena allocation out from the query caches into conditional code in the query system. The specialized arena caches are removed. A new `QuerySystem` type is added in `rustc_middle` which contains the arenas, providers and query caches.
Performance seems to be slightly regressed:
<table><tr><td rowspan="2">Benchmark</td><td colspan="1"><b>Before</b></th><td colspan="2"><b>After</b></th></tr><tr><td align="right">Time</td><td align="right">Time</td><td align="right">%</th></tr><tr><td>🟣 <b>clap</b>:check</td><td align="right">1.8053s</td><td align="right">1.8109s</td><td align="right"> 0.31%</td></tr><tr><td>🟣 <b>hyper</b>:check</td><td align="right">0.2600s</td><td align="right">0.2597s</td><td align="right"> -0.10%</td></tr><tr><td>🟣 <b>regex</b>:check</td><td align="right">0.9973s</td><td align="right">1.0006s</td><td align="right"> 0.34%</td></tr><tr><td>🟣 <b>syn</b>:check</td><td align="right">1.6048s</td><td align="right">1.6051s</td><td align="right"> 0.02%</td></tr><tr><td>🟣 <b>syntex_syntax</b>:check</td><td align="right">6.2992s</td><td align="right">6.3159s</td><td align="right"> 0.26%</td></tr><tr><td>Total</td><td align="right">10.9664s</td><td align="right">10.9922s</td><td align="right"> 0.23%</td></tr><tr><td>Summary</td><td align="right">1.0000s</td><td align="right">1.0017s</td><td align="right"> 0.17%</td></tr></table>
Incremental performance is a bit worse:
<table><tr><td rowspan="2">Benchmark</td><td colspan="1"><b>Before</b></th><td colspan="2"><b>After</b></th></tr><tr><td align="right">Time</td><td align="right">Time</td><td align="right">%</th></tr><tr><td>🟣 <b>clap</b>:check:initial</td><td align="right">2.2103s</td><td align="right">2.2247s</td><td align="right"> 0.65%</td></tr><tr><td>🟣 <b>hyper</b>:check:initial</td><td align="right">0.3335s</td><td align="right">0.3349s</td><td align="right"> 0.41%</td></tr><tr><td>🟣 <b>regex</b>:check:initial</td><td align="right">1.2597s</td><td align="right">1.2650s</td><td align="right"> 0.42%</td></tr><tr><td>🟣 <b>syn</b>:check:initial</td><td align="right">2.0521s</td><td align="right">2.0613s</td><td align="right"> 0.45%</td></tr><tr><td>🟣 <b>syntex_syntax</b>:check:initial</td><td align="right">7.8275s</td><td align="right">7.8583s</td><td align="right"> 0.39%</td></tr><tr><td>Total</td><td align="right">13.6832s</td><td align="right">13.7442s</td><td align="right"> 0.45%</td></tr><tr><td>Summary</td><td align="right">1.0000s</td><td align="right">1.0046s</td><td align="right"> 0.46%</td></tr></table>
It does seem like LLVM optimizers struggle a bit with the current state of the query system.
Based on top of https://github.com/rust-lang/rust/pull/107782 and https://github.com/rust-lang/rust/pull/107802.
r? `@cjgillot`
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`
Don't ICE in `might_permit_raw_init` if reference is polymorphic
Emitting optimized MIR for a polymorphic function may require computing layout of a type that isn't (yet) known. This happens in the instcombine pass, for example. Let's fail gracefully in that condition.
cc `@saethlin`
fixes#107999