diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 31353d1eac0fb..b4a6cd33a60f4 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -598,15 +598,26 @@ fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) { match sess.io.input { Input::File(ref path) => { let mut v = Vec::new(); - locator::list_file_metadata( + if let Err(error) = locator::list_file_metadata( &sess.target, path, metadata_loader, &mut v, &sess.opts.unstable_opts.ls, sess.cfg_version, - ) - .unwrap(); + ) { + if path.extension().is_some_and(|extension| extension == "rs") { + let mut err = sess + .dcx() + .struct_fatal("`-Zls` takes a `.rmeta` file as input, not a source file"); + if rustc_session::utils::was_invoked_from_cargo() { + // Give a Cargo-tailored suggestion if we're coming from Cargo + err.note("use `rustc +nightly -Zls=... path/to/file.rmeta` directly, instead of going through Cargo"); + } + err.emit(); + } + sess.dcx().fatal(error.to_string()); + } safe_println!("{}", String::from_utf8(v).unwrap()); } Input::Str { .. } => { diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 874d4812502e6..78d06add675dc 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -213,7 +213,7 @@ //! metadata::locator or metadata::creader for all the juicy details! use std::borrow::Cow; -use std::io::{self, Result as IoResult, Write}; +use std::io::{self, Error as IoError, ErrorKind as IoErrorKind, Result as IoResult, Write}; use std::ops::Deref; use std::path::{Path, PathBuf}; use std::{cmp, fmt}; @@ -963,7 +963,7 @@ pub fn list_file_metadata( let flavor = get_flavor_from_path(path); match get_metadata_section(target, flavor, path, metadata_loader, cfg_version, None) { Ok(metadata) => metadata.list_crate_metadata(out, ls_kinds), - Err(msg) => write!(out, "{msg}\n"), + Err(msg) => Err(IoError::new(IoErrorKind::Other, msg.to_string())), } } diff --git a/src/doc/unstable-book/src/compiler-flags/ls.md b/src/doc/unstable-book/src/compiler-flags/ls.md new file mode 100644 index 0000000000000..812f2eee1d57f --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/ls.md @@ -0,0 +1,25 @@ +# `ls` + +--- + +Option `-Zls` instructs the compiler to list all metadata from a given metadata file (i.e. files with the `.rmeta` extension). + +This allows for debugging the metadata emitted by an earlier compilation. + +Note that, while `rustc` usually works with `.rs` files, this option is meant purely for analyzing `.rmeta` files, and does not produce any compilation artifact. + +Allowed values are: + +- `root`: Crate info. +- `lang_items`: Language items used and missing, if any. +- `features`: Library features defined via the `#[stable]` and `#[unstable]` internal attributes. +- `items`: All items (such as modules, functions...) in the crate, including attributes like their visibility +- `all`: All of the above + +## Example + +```sh +rustc +nightly -Zls=all target/debug/deps/libmy_crate-*.rmeta +``` + +This lists to stdout all metadata from the given `.rmeta` file diff --git a/tests/run-make/ls-metadata/rmake.rs b/tests/run-make/ls-metadata/rmake.rs index 42db97a292bed..3fc7c911f6da9 100644 --- a/tests/run-make/ls-metadata/rmake.rs +++ b/tests/run-make/ls-metadata/rmake.rs @@ -10,7 +10,7 @@ use run_make_support::{rfs, rustc}; fn main() { rustc().input("foo.rs").run(); - rustc().arg("-Zls=root").input("foo").run(); + rustc().arg("-Zls=root").input("foo").run_fail(); rfs::create_file("bar"); - rustc().arg("-Zls=root").input("bar").run(); + rustc().arg("-Zls=root").input("bar").run_fail(); }