1
Fork 0

rustdoc: catch and don't blow up on impl Trait cycles

An odd feature of Rust is that `Foo` is invalid, but `Bar` is okay:

    type Foo<'a, 'b> = Box<dyn PartialEq<Foo<'a, 'b>>>;
    type Bar<'a, 'b> = impl PartialEq<Bar<'a, 'b>>;

To get it right, track every time rustdoc descends into a type alias,
so if it shows up twice, it can be write the path instead of
infinitely expanding it.
This commit is contained in:
Michael Howell 2023-04-20 18:08:06 -07:00
parent 87b1f891ea
commit b1d08275a9
6 changed files with 127 additions and 19 deletions

View file

@ -0,0 +1,12 @@
type Bar<'a, 'b> = Box<dyn PartialEq<Bar<'a, 'b>>>;
//~^ ERROR cycle detected when expanding type alias
fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
Box::new(i)
}
fn main() {
let meh = 42;
let muh = 42;
assert!(bar(&meh) == bar(&muh));
}

View file

@ -0,0 +1,25 @@
error[E0391]: cycle detected when expanding type alias `Bar`
--> $DIR/issue-110629-private-type-cycle-dyn.rs:1:38
|
LL | type Bar<'a, 'b> = Box<dyn PartialEq<Bar<'a, 'b>>>;
| ^^^^^^^^^^^
|
= note: ...which immediately requires expanding type alias `Bar` again
= note: type aliases cannot be recursive
= help: consider using a struct, enum, or union instead to break the cycle
= help: see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information
note: cycle used when collecting item types in top-level module
--> $DIR/issue-110629-private-type-cycle-dyn.rs:1:1
|
LL | / type Bar<'a, 'b> = Box<dyn PartialEq<Bar<'a, 'b>>>;
LL | |
LL | |
LL | | fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
... |
LL | | assert!(bar(&meh) == bar(&muh));
LL | | }
| |_^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0391`.

View file

@ -0,0 +1,15 @@
// check-pass
#![feature(type_alias_impl_trait)]
type Bar<'a, 'b> = impl PartialEq<Bar<'a, 'b>> + std::fmt::Debug;
fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
i
}
fn main() {
let meh = 42;
let muh = 42;
assert_eq!(bar(&meh), bar(&muh));
}