Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ICE on rustdoc output-format json #89039

Closed
kpp opened this issue Sep 17, 2021 · 3 comments
Closed

ICE on rustdoc output-format json #89039

kpp opened this issue Sep 17, 2021 · 3 comments
Labels
A-rustdoc-json Area: Rustdoc JSON backend C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue.

Comments

@kpp
Copy link
Contributor

kpp commented Sep 17, 2021

If possible, try to provide a minimal verifiable example.

I failed. Sorry.

Code

~/rust/library/std$ cargo rustdoc -- -Z unstable-options --output-format json

Meta

~/rust/library/std$ git log -n1
commit b69fe57261086e70aea9d5b58819a1794bf7c121 

rustc --version --verbose:

rustc 1.57.0-nightly (fdf65053e 2021-09-07)
binary: rustc
commit-hash: fdf65053e99e8966f9bd83b5a8491326cb33d638
commit-date: 2021-09-07
host: x86_64-unknown-linux-gnu
release: 1.57.0-nightly
LLVM version: 13.0.0

Error output

 Documenting std v0.0.0 (/home/kpp/rust/library/std)
thread 'rustc' panicked at 'assertion failed: `(left == right)`
  left: `Item { id: Id("4:1258"), crate_id: 4, name: Some("BTreeMap"), .......
 right: `Item { id: Id("4:1258"), crate_id: 4, name: Some("BTreeMap"), .......

// See more in the backtrace

Backtrace

thread 'rustc' panicked at 'assertion failed: `(left == right)`
  left: `Item { id: Id("4:1258"), crate_id: 4, name: Some("BTreeMap"), span: Some(Span { filename: "/home/kpp/rust/library/alloc/src/collections/btree/map.rs", begin: (158, 0), end: (161, 1) }), visibility: Public, docs: Some("A map based on a [B-Tree].\n\nB-Trees represent a fundamental compromise between cache-efficiency and actually minimizing\nthe amount of work performed in a search. In theory, a binary search tree (BST) is the optimal\nchoice for a sorted map, as a perfectly balanced BST performs the theoretical minimum amount of\ncomparisons necessary to find an element (log<sub>2</sub>n). However, in practice the way this\nis done is *very* inefficient for modern computer architectures. In particular, every element\nis stored in its own individually heap-allocated node. This means that every single insertion\ntriggers a heap-allocation, and every single comparison should be a cache-miss. Since these\nare both notably expensive things to do in practice, we are forced to at very least reconsider\nthe BST strategy.\n\nA B-Tree instead makes each node contain B-1 to 2B-1 elements in a contiguous array. By doing\nthis, we reduce the number of allocations by a factor of B, and improve cache efficiency in\nsearches. However, this does mean that searches will have to do *more* comparisons on average.\nThe precise number of comparisons depends on the node search strategy used. For optimal cache\nefficiency, one could search the nodes linearly. For optimal comparisons, one could search\nthe node using binary search. As a compromise, one could also perform a linear search\nthat initially only checks every i<sup>th</sup> element for some choice of i.\n\nCurrently, our implementation simply performs naive linear search. This provides excellent\nperformance on *small* nodes of elements which are cheap to compare. However in the future we\nwould like to further explore choosing the optimal search strategy based on the choice of B,\nand possibly other factors. Using linear search, searching for a random element is expected\nto take O(B * log(n)) comparisons, which is generally worse than a BST. In practice,\nhowever, performance is excellent.\n\nIt is a logic error for a key to be modified in such a way that the key's ordering relative to\nany other key, as determined by the [`Ord`] trait, changes while it is in the map. This is\nnormally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.\nThe behavior resulting from such a logic error is not specified, but will not result in\nundefined behavior. This could include panics, incorrect results, aborts, memory leaks, and\nnon-termination.\n\n[B-Tree]: https://en.wikipedia.org/wiki/B-tree\n[`Cell`]: core::cell::Cell\n[`RefCell`]: core::cell::RefCell\n\n# Examples\n\n```\nuse std::collections::BTreeMap;\n\n// type inference lets us omit an explicit type signature (which\n// would be `BTreeMap<&str, &str>` in this example).\nlet mut movie_reviews = BTreeMap::new();\n\n// review some movies.\nmovie_reviews.insert(\"Office Space\",       \"Deals with real issues in the workplace.\");\nmovie_reviews.insert(\"Pulp Fiction\",       \"Masterpiece.\");\nmovie_reviews.insert(\"The Godfather\",      \"Very enjoyable.\");\nmovie_reviews.insert(\"The Blues Brothers\", \"Eye lyked it a lot.\");\n\n// check for a specific one.\nif !movie_reviews.contains_key(\"Les Misérables\") {\n    println!(\"We've got {} reviews, but Les Misérables ain't one.\",\n             movie_reviews.len());\n}\n\n// oops, this review has a lot of spelling mistakes, let's delete it.\nmovie_reviews.remove(\"The Blues Brothers\");\n\n// look up the values associated with some keys.\nlet to_find = [\"Up!\", \"Office Space\"];\nfor movie in &to_find {\n    match movie_reviews.get(movie) {\n       Some(review) => println!(\"{}: {}\", movie, review),\n       None => println!(\"{} is unreviewed.\", movie)\n    }\n}\n\n// Look up the value for a key (will panic if the key is not found).\nprintln!(\"Movie review: {}\", movie_reviews[\"Office Space\"]);\n\n// iterate over everything.\nfor (movie, review) in &movie_reviews {\n    println!(\"{}: \\\"{}\\\"\", movie, review);\n}\n```\n\nA `BTreeMap` with a known list of items can be initialized from an array:\n\n```\nuse std::collections::BTreeMap;\n\nlet solar_distance = BTreeMap::from([\n    (\"Mercury\", 0.4),\n    (\"Venus\", 0.7),\n    (\"Earth\", 1.0),\n    (\"Mars\", 1.5),\n]);\n```\n\n`BTreeMap` implements an [`Entry API`], which allows for complex\nmethods of getting, setting, updating and removing keys and their values:\n\n[`Entry API`]: BTreeMap::entry\n\n```\nuse std::collections::BTreeMap;\n\n// type inference lets us omit an explicit type signature (which\n// would be `BTreeMap<&str, u8>` in this example).\nlet mut player_stats = BTreeMap::new();\n\nfn random_stat_buff() -> u8 {\n    // could actually return some random value here - let's just return\n    // some fixed value for now\n    42\n}\n\n// insert a key only if it doesn't already exist\nplayer_stats.entry(\"health\").or_insert(100);\n\n// insert a key using a function that provides a new value only if it\n// doesn't already exist\nplayer_stats.entry(\"defence\").or_insert_with(random_stat_buff);\n\n// update a key, guarding against the key possibly not being set\nlet stat = player_stats.entry(\"attack\").or_insert(100);\n*stat += random_stat_buff();\n```"), links: {"BTreeMap::entry": Id("4:1258"), "`Ord`": Id("1:2676"), "core::cell::Cell": Id("1:4151"), "core::cell::RefCell": Id("1:4216")}, attrs: ["#[stable(feature = \"rust1\", since = \"1.0.0\")]", "#[rustc_diagnostic_item = \"BTreeMap\"]"], deprecation: None, inner: Struct(Struct { struct_type: Plain, generics: Generics { params: [GenericParamDef { name: "K", kind: Type { bounds: [], default: None } }, GenericParamDef { name: "V", kind: Type { bounds: [], default: None } }], where_predicates: [] }, fields_stripped: true, fields: [], impls: [] }) }`,
 right: `Item { id: Id("4:1258"), crate_id: 4, name: Some("BTreeMap"), span: Some(Span { filename: "/home/kpp/rust/library/alloc/src/collections/btree/map.rs", begin: (158, 0), end: (161, 1) }), visibility: Public, docs: Some("A map based on a [B-Tree].\n\nB-Trees represent a fundamental compromise between cache-efficiency and actually minimizing\nthe amount of work performed in a search. In theory, a binary search tree (BST) is the optimal\nchoice for a sorted map, as a perfectly balanced BST performs the theoretical minimum amount of\ncomparisons necessary to find an element (log<sub>2</sub>n). However, in practice the way this\nis done is *very* inefficient for modern computer architectures. In particular, every element\nis stored in its own individually heap-allocated node. This means that every single insertion\ntriggers a heap-allocation, and every single comparison should be a cache-miss. Since these\nare both notably expensive things to do in practice, we are forced to at very least reconsider\nthe BST strategy.\n\nA B-Tree instead makes each node contain B-1 to 2B-1 elements in a contiguous array. By doing\nthis, we reduce the number of allocations by a factor of B, and improve cache efficiency in\nsearches. However, this does mean that searches will have to do *more* comparisons on average.\nThe precise number of comparisons depends on the node search strategy used. For optimal cache\nefficiency, one could search the nodes linearly. For optimal comparisons, one could search\nthe node using binary search. As a compromise, one could also perform a linear search\nthat initially only checks every i<sup>th</sup> element for some choice of i.\n\nCurrently, our implementation simply performs naive linear search. This provides excellent\nperformance on *small* nodes of elements which are cheap to compare. However in the future we\nwould like to further explore choosing the optimal search strategy based on the choice of B,\nand possibly other factors. Using linear search, searching for a random element is expected\nto take O(B * log(n)) comparisons, which is generally worse than a BST. In practice,\nhowever, performance is excellent.\n\nIt is a logic error for a key to be modified in such a way that the key's ordering relative to\nany other key, as determined by the [`Ord`] trait, changes while it is in the map. This is\nnormally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.\nThe behavior resulting from such a logic error is not specified, but will not result in\nundefined behavior. This could include panics, incorrect results, aborts, memory leaks, and\nnon-termination.\n\n[B-Tree]: https://en.wikipedia.org/wiki/B-tree\n[`Cell`]: core::cell::Cell\n[`RefCell`]: core::cell::RefCell\n\n# Examples\n\n```\nuse std::collections::BTreeMap;\n\n// type inference lets us omit an explicit type signature (which\n// would be `BTreeMap<&str, &str>` in this example).\nlet mut movie_reviews = BTreeMap::new();\n\n// review some movies.\nmovie_reviews.insert(\"Office Space\",       \"Deals with real issues in the workplace.\");\nmovie_reviews.insert(\"Pulp Fiction\",       \"Masterpiece.\");\nmovie_reviews.insert(\"The Godfather\",      \"Very enjoyable.\");\nmovie_reviews.insert(\"The Blues Brothers\", \"Eye lyked it a lot.\");\n\n// check for a specific one.\nif !movie_reviews.contains_key(\"Les Misérables\") {\n    println!(\"We've got {} reviews, but Les Misérables ain't one.\",\n             movie_reviews.len());\n}\n\n// oops, this review has a lot of spelling mistakes, let's delete it.\nmovie_reviews.remove(\"The Blues Brothers\");\n\n// look up the values associated with some keys.\nlet to_find = [\"Up!\", \"Office Space\"];\nfor movie in &to_find {\n    match movie_reviews.get(movie) {\n       Some(review) => println!(\"{}: {}\", movie, review),\n       None => println!(\"{} is unreviewed.\", movie)\n    }\n}\n\n// Look up the value for a key (will panic if the key is not found).\nprintln!(\"Movie review: {}\", movie_reviews[\"Office Space\"]);\n\n// iterate over everything.\nfor (movie, review) in &movie_reviews {\n    println!(\"{}: \\\"{}\\\"\", movie, review);\n}\n```\n\nA `BTreeMap` with a known list of items can be initialized from an array:\n\n```\nuse std::collections::BTreeMap;\n\nlet solar_distance = BTreeMap::from([\n    (\"Mercury\", 0.4),\n    (\"Venus\", 0.7),\n    (\"Earth\", 1.0),\n    (\"Mars\", 1.5),\n]);\n```\n\n`BTreeMap` implements an [`Entry API`], which allows for complex\nmethods of getting, setting, updating and removing keys and their values:\n\n[`Entry API`]: BTreeMap::entry\n\n```\nuse std::collections::BTreeMap;\n\n// type inference lets us omit an explicit type signature (which\n// would be `BTreeMap<&str, u8>` in this example).\nlet mut player_stats = BTreeMap::new();\n\nfn random_stat_buff() -> u8 {\n    // could actually return some random value here - let's just return\n    // some fixed value for now\n    42\n}\n\n// insert a key only if it doesn't already exist\nplayer_stats.entry(\"health\").or_insert(100);\n\n// insert a key using a function that provides a new value only if it\n// doesn't already exist\nplayer_stats.entry(\"defence\").or_insert_with(random_stat_buff);\n\n// update a key, guarding against the key possibly not being set\nlet stat = player_stats.entry(\"attack\").or_insert(100);\n*stat += random_stat_buff();\n```"), links: {"BTreeMap::entry": Id("4:1258"), "`Ord`": Id("1:2676"), "core::cell::Cell": Id("1:4151"), "core::cell::RefCell": Id("1:4216")}, attrs: ["#[stable(feature = \"rust1\", since = \"1.0.0\")]", "#[stable(feature = \"rust1\", since = \"1.0.0\")]", "#[rustc_diagnostic_item = \"BTreeMap\"]"], deprecation: None, inner: Struct(Struct { struct_type: Plain, generics: Generics { params: [GenericParamDef { name: "K", kind: Type { bounds: [], default: None } }, GenericParamDef { name: "V", kind: Type { bounds: [], default: None } }], where_predicates: [] }, fields_stripped: true, fields: [], impls: [] }) }`', src/librustdoc/json/mod.rs:179:17
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

error: internal compiler error: unexpected panic

error: Unrecognized option: 'output-format'

error: could not document `std`

Caused by:
  process didn't exit successfully: `rustdoc --edition=2018 --crate-type dylib --crate-type rlib --crate-name std library/std/src/lib.rs -o /home/kpp/rust/target/doc --error-format=json --json=diagnostic-rendered-ansi -Z unstable-options --output-format json -L dependency=/home/kpp/rust/target/debug/deps --extern alloc=/home/kpp/rust/target/debug/deps/liballoc-c7e85a7af221c80d.rmeta --extern cfg_if=/home/kpp/rust/target/debug/deps/libcfg_if-0423127cb0adc6bf.rmeta --extern compiler_builtins=/home/kpp/rust/target/debug/deps/libcompiler_builtins-d354b280d3e008fc.rmeta --extern core=/home/kpp/rust/target/debug/deps/libcore-125020c7f228ae1c.rmeta --extern hashbrown=/home/kpp/rust/target/debug/deps/libhashbrown-f17e127c783ce208.rmeta --extern libc=/home/kpp/rust/target/debug/deps/liblibc-6b67a15ae9d7f6d7.rmeta --extern panic_abort=/home/kpp/rust/target/debug/deps/libpanic_abort-743d4330139c8443.rmeta --extern rustc_demangle=/home/kpp/rust/target/debug/deps/librustc_demangle-d8f9f69341f37046.rmeta --extern std_detect=/home/kpp/rust/target/debug/deps/libstd_detect-4fc3104d55e43d53.rmeta --extern unwind=/home/kpp/rust/target/debug/deps/libunwind-0dd299410b3286e5.rmeta --crate-version 0.0.0 --cfg backtrace_in_libstd` (exit status: 1)

The compiler fails here.

cc @aDotInTheVoid

@kpp kpp added C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Sep 17, 2021
@jyn514
Copy link
Member

jyn514 commented Sep 17, 2021

The second one is preserving the attribute "#[stable(feature = \"rust1\", since = \"1.0.0\")]" and the first is not.

@jyn514 jyn514 added A-rustdoc-json Area: Rustdoc JSON backend T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue. and removed T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Sep 17, 2021
@kpp
Copy link
Contributor Author

kpp commented Sep 18, 2021

Here goes MRE:

~/test_rustdoc_json$ tail -n+1 Cargo.toml foo/Cargo.toml foo/src/lib.rs bar/Cargo.toml bar/src/lib.rs 
==> Cargo.toml <==
[workspace]

members = [
    "foo",
    "bar",
]

==> foo/Cargo.toml <==
[package]
name = "foo"
version = "0.1.0"
edition = "2021"

[dependencies]

==> foo/src/lib.rs <==
pub struct Foo;

==> bar/Cargo.toml <==
[package]
name = "bar"
version = "0.1.0"
edition = "2021"

[dependencies]
foo = { path = "../foo" }

==> bar/src/lib.rs <==
pub mod bar {
    pub use foo::Foo;
}

/// Bar
pub use bar::Foo;
~/test_rustdoc_json/bar$ cargo rustdoc -- -Z unstable-options --output-format json
 Documenting bar v0.1.0 (/home/kpp/test_rustdoc_json/bar)
thread 'rustc' panicked at 'assertion failed: `(left == right)`
  left: `Item { id: Id("20:3"), crate_id: 20, name: Some("Foo"), span: Some(Span { filename: "/home/kpp/test_rustdoc_json/foo/src/lib.rs", begin: (1, 0), end: (1, 15) }), visibility: Public, docs: None, links: {}, attrs: [], deprecation: None, inner: Struct(Struct { struct_type: Unit, generics: Generics { params: [], where_predicates: [] }, fields_stripped: false, fields: [], impls: [] }) }`,
 right: `Item { id: Id("20:3"), crate_id: 20, name: Some("Foo"), span: Some(Span { filename: "/home/kpp/test_rustdoc_json/foo/src/lib.rs", begin: (1, 0), end: (1, 15) }), visibility: Public, docs: Some("Bar"), links: {}, attrs: [], deprecation: None, inner: Struct(Struct { struct_type: Unit, generics: Generics { params: [], where_predicates: [] }, fields_stripped: false, fields: [], impls: [] }) }`', src/librustdoc/json/mod.rs:179:17
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

error: internal compiler error: unexpected panic

error: Unrecognized option: 'output-format'

error: could not document `bar`

Caused by:
  process didn't exit successfully: `rustdoc --edition=2021 --crate-type lib --crate-name bar bar/src/lib.rs -o /home/kpp/test_rustdoc_json/target/doc --error-format=json --json=diagnostic-rendered-ansi -Z unstable-options --output-format json -L dependency=/home/kpp/test_rustdoc_json/target/debug/deps --extern foo=/home/kpp/test_rustdoc_json/target/debug/deps/libfoo-234c6169b2e7c94b.rmeta --crate-version 0.1.0` (exit status: 1)

@kpp
Copy link
Contributor Author

kpp commented Sep 18, 2021

Duplicate of #83057

@kpp kpp closed this as completed Sep 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-rustdoc-json Area: Rustdoc JSON backend C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ T-rustdoc Relevant to the rustdoc team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

2 participants