mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-03 12:13:43 +00:00
3e293634e2
rustdoc: fix & clean up handling of cross-crate higher-ranked parameters Preparatory work for the refactoring planned in #113015 (for correctness & maintainability). --- 1. Render the higher-ranked parameters of cross-crate function pointer types **(*)**. 2. Replace occurrences of `collect_referenced_late_bound_regions()` (CRLBR) with `bound_vars()`. The former is quite problematic and the use of the latter allows us to yank a lot of hacky code **(†)** as you can tell from the diff! :) 3. Add support for cross-crate higher-ranked types (`#![feature(non_lifetime_binders)]`). We were previously ICE'ing on them (see `inline_cross/non_lifetime_binders.rs`). --- **(*)**: Extracted from test `inline_cross/fn-type.rs`: ```diff - fn(_: &'z fn(_: &'b str), _: &'a ()) -> &'a () + for<'z, 'a, '_unused> fn(_: &'z for<'b> fn(_: &'b str), _: &'a ()) -> &'a () ``` **(†)**: It returns an `FxHashSet` which isn't *predictable* or *stable* wrt. source code (`.rmeta`) changes. To elaborate, the ordering of late-bound regions doesn't necessarily reflect the ordering found in the source code. It does seem to be stable across compilations but modifying the source code of the to-be-documented crates (like adding or renaming items) may result in a different order: <details><summary>Example</summary> Let's assume that we're documenting the cross-crate re-export of `produce` from the code below. On `master`, rustdoc would render the list of binders as `for<'x, 'y, 'z>`. However, once you add back the functions `a`–`l`, it would be rendered as `for<'z, 'y, 'x>` (reverse order)! Results may vary. `bound_vars()` fixes this as it returns them in source order. ```rs // pub fn a() {} // pub fn b() {} // pub fn c() {} // pub fn d() {} // pub fn e() {} // pub fn f() {} // pub fn g() {} // pub fn h() {} // pub fn i() {} // pub fn j() {} // pub fn k() {} // pub fn l() {} pub fn produce() -> impl for<'x, 'y, 'z> Trait<'z, 'y, 'x> {} pub trait Trait<'a, 'b, 'c> {} impl Trait<'_, '_, '_> for () {} ``` </details> Further, as the name suggests, CRLBR only collects *referenced* regions and thus we drop unused binders. `bound_vars()` contains unused binders on the other hand. Let's stay closer to the source where possible and keep unused binders. Lastly, using `bound_vars()` allows us to get rid of * the deduplication and alphabetical sorting hack in `simplify.rs` * the weird field `bound_params` on `EqPredicate` both of which were introduced by me in #102707 back when I didn't know better. To illustrate, let's look at the cross-crate bound `T: for<'a, 'b> Trait<A<'a> = (), B<'b> = ()>`. * With CRLBR + `EqPredicate.bound_params`, *before* bounds simplification we would have the bounds `T: Trait`, `for<'a> <T as Trait>::A<'a> == ()` and `for<'b> <T as Trait>::B<'b> == ()` which required us to merge `for<>`, `for<'a>` and `for<'b>` into `for<'a, 'b>` in a deterministic manner and without introducing duplicate binders. * With `bound_vars()`, we now have the bounds `for<'a, b> T: Trait`, `<T as Trait>::A<'a> == ()` and `<T as Trait>::B<'b> == ()` before bound simplification similar to rustc itself. This obviously no longer requires any funny merging of `for<>`s. On top of that `for<'a, 'b>` is guaranteed to be in source order. |
||
---|---|---|
.. | ||
assembly | ||
auxiliary | ||
codegen | ||
codegen-units | ||
coverage-map | ||
debuginfo | ||
incremental | ||
mir-opt | ||
pretty | ||
run-coverage | ||
run-coverage-rustdoc | ||
run-make | ||
run-make-fulldeps | ||
run-pass-valgrind | ||
rustdoc | ||
rustdoc-gui | ||
rustdoc-js | ||
rustdoc-js-std | ||
rustdoc-json | ||
rustdoc-ui | ||
ui | ||
ui-fulldeps | ||
COMPILER_TESTS.md |