diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index e56347ab38e..6175894b205 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -700,12 +700,14 @@ pub fn list_metadata( sess: &Session, metadata_loader: &dyn MetadataLoader, ) -> Compilation { - if sess.opts.unstable_opts.ls { + let ls_kinds = &sess.opts.unstable_opts.ls; + if !ls_kinds.is_empty() { match sess.io.input { Input::File(ref ifile) => { let path = &(*ifile); let mut v = Vec::new(); - locator::list_file_metadata(&sess.target, path, metadata_loader, &mut v).unwrap(); + locator::list_file_metadata(&sess.target, path, metadata_loader, &mut v, ls_kinds) + .unwrap(); 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 bf6004ba864..3062939d8da 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -903,10 +903,11 @@ pub fn list_file_metadata( path: &Path, metadata_loader: &dyn MetadataLoader, out: &mut dyn Write, + ls_kinds: &[String], ) -> IoResult<()> { let flavor = get_flavor_from_path(path); match get_metadata_section(target, flavor, path, metadata_loader) { - Ok(metadata) => metadata.list_crate_metadata(out), + Ok(metadata) => metadata.list_crate_metadata(out, ls_kinds), Err(msg) => write!(out, "{msg}\n"), } } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 13236f4ce1f..8f7099971d4 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -725,78 +725,125 @@ impl MetadataBlob { LazyValue::::from_position(NonZeroUsize::new(pos).unwrap()).decode(self) } - pub(crate) fn list_crate_metadata(&self, out: &mut dyn io::Write) -> io::Result<()> { + pub(crate) fn list_crate_metadata( + &self, + out: &mut dyn io::Write, + ls_kinds: &[String], + ) -> io::Result<()> { let root = self.get_root(); - writeln!(out, "Crate info:")?; - writeln!(out, "name {}{}", root.name(), root.extra_filename)?; - writeln!(out, "hash {} stable_crate_id {:?}", root.hash(), root.stable_crate_id)?; - writeln!(out, "proc_macro {:?}", root.proc_macro_data.is_some())?; - writeln!(out, "triple {}", root.header.triple.triple())?; - writeln!(out, "edition {}", root.edition)?; - writeln!(out, "symbol_mangling_version {:?}", root.symbol_mangling_version)?; - writeln!( - out, - "required_panic_strategy {:?} panic_in_drop_strategy {:?}", - root.required_panic_strategy, root.panic_in_drop_strategy - )?; - writeln!( - out, - "has_global_allocator {} has_alloc_error_handler {} has_panic_handler {} has_default_lib_allocator {}", - root.has_global_allocator, - root.has_alloc_error_handler, - root.has_panic_handler, - root.has_default_lib_allocator - )?; - writeln!( - out, - "compiler_builtins {} needs_allocator {} needs_panic_runtime {} no_builtins {} panic_runtime {} profiler_runtime {}", - root.compiler_builtins, - root.needs_allocator, - root.needs_panic_runtime, - root.no_builtins, - root.panic_runtime, - root.profiler_runtime - )?; - writeln!(out, "\n=External Dependencies=")?; - let dylib_dependency_formats = - root.dylib_dependency_formats.decode(self).collect::>(); - for (i, dep) in root.crate_deps.decode(self).enumerate() { - let CrateDep { name, extra_filename, hash, host_hash, kind, is_private } = dep; - let number = i + 1; + let all_ls_kinds = vec!["root".to_owned(), "lang_items".to_owned(), "features".to_owned()]; + let ls_kinds = if ls_kinds.contains(&"all".to_owned()) { + &all_ls_kinds + } else { + ls_kinds + }; - writeln!( - out, - "{number} {name}{extra_filename} hash {hash} host_hash {host_hash:?} kind {kind:?} {privacy}{linkage}", - privacy = if is_private { "private" } else { "public" }, - linkage = if dylib_dependency_formats.is_empty() { - String::new() - } else { - format!(" linkage {:?}", dylib_dependency_formats[i]) + for kind in ls_kinds { + match &**kind { + "root" => { + writeln!(out, "Crate info:")?; + writeln!(out, "name {}{}", root.name(), root.extra_filename)?; + writeln!( + out, + "hash {} stable_crate_id {:?}", + root.hash(), + root.stable_crate_id + )?; + writeln!(out, "proc_macro {:?}", root.proc_macro_data.is_some())?; + writeln!(out, "triple {}", root.header.triple.triple())?; + writeln!(out, "edition {}", root.edition)?; + writeln!(out, "symbol_mangling_version {:?}", root.symbol_mangling_version)?; + writeln!( + out, + "required_panic_strategy {:?} panic_in_drop_strategy {:?}", + root.required_panic_strategy, root.panic_in_drop_strategy + )?; + writeln!( + out, + "has_global_allocator {} has_alloc_error_handler {} has_panic_handler {} has_default_lib_allocator {}", + root.has_global_allocator, + root.has_alloc_error_handler, + root.has_panic_handler, + root.has_default_lib_allocator + )?; + writeln!( + out, + "compiler_builtins {} needs_allocator {} needs_panic_runtime {} no_builtins {} panic_runtime {} profiler_runtime {}", + root.compiler_builtins, + root.needs_allocator, + root.needs_panic_runtime, + root.no_builtins, + root.panic_runtime, + root.profiler_runtime + )?; + + writeln!(out, "\n=External Dependencies=")?; + let dylib_dependency_formats = + root.dylib_dependency_formats.decode(self).collect::>(); + for (i, dep) in root.crate_deps.decode(self).enumerate() { + let CrateDep { name, extra_filename, hash, host_hash, kind, is_private } = + dep; + let number = i + 1; + + writeln!( + out, + "{number} {name}{extra_filename} hash {hash} host_hash {host_hash:?} kind {kind:?} {privacy}{linkage}", + privacy = if is_private { "private" } else { "public" }, + linkage = if dylib_dependency_formats.is_empty() { + String::new() + } else { + format!(" linkage {:?}", dylib_dependency_formats[i]) + } + )?; + } + write!(out, "\n")?; } - )?; - } - write!(out, "\n")?; - writeln!(out, "\n=Lang items=")?; - for (id, lang_item) in root.lang_items.decode(self) { - writeln!( - out, - "{} = crate{}", - lang_item.name(), - DefPath::make(LOCAL_CRATE, id, |parent| root - .tables - .def_keys - .get(self, parent) - .unwrap() - .decode(self)) - .to_string_no_crate_verbose() - )?; + "lang_items" => { + writeln!(out, "\n=Lang items=")?; + for (id, lang_item) in root.lang_items.decode(self) { + writeln!( + out, + "{} = crate{}", + lang_item.name(), + DefPath::make(LOCAL_CRATE, id, |parent| root + .tables + .def_keys + .get(self, parent) + .unwrap() + .decode(self)) + .to_string_no_crate_verbose() + )?; + } + for lang_item in root.lang_items_missing.decode(self) { + writeln!(out, "{} = ", lang_item.name())?; + } + write!(out, "\n")?; + } + + "features" => { + writeln!(out, "\n=Lib features=")?; + for (feature, since) in root.lib_features.decode(self) { + writeln!( + out, + "{}{}", + feature, + if let Some(since) = since { + format!(" since {since}") + } else { + String::new() + } + )?; + } + write!(out, "\n")?; + } + + _ => { + writeln!(out, "unknown -Zls kind. allowed values are: no, all, root, lang_items, features")?; + } + } } - for lang_item in root.lang_items_missing.decode(self) { - writeln!(out, "{} = ", lang_item.name())?; - } - write!(out, "\n")?; Ok(()) } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index d241d1cf18d..7b1ba1e026f 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1086,7 +1086,7 @@ impl Options { /// Returns `true` if there will be an output file generated. pub fn will_create_output_file(&self) -> bool { !self.unstable_opts.parse_only && // The file is just being parsed - !self.unstable_opts.ls // The file is just being queried + self.unstable_opts.ls.is_empty() // The file is just being queried } #[inline] diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 6c26859228c..06d11fa68ed 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1597,8 +1597,9 @@ options! { "what location details should be tracked when using caller_location, either \ `none`, or a comma separated list of location details, for which \ valid options are `file`, `line`, and `column` (default: `file,line,column`)"), - ls: bool = (false, parse_bool, [UNTRACKED], - "list the symbols defined by a library crate (default: no)"), + ls: Vec = (Vec::new(), parse_list, [UNTRACKED], + "decode and print various part of the crate metadata for a library crate \ + (space separated)"), macro_backtrace: bool = (false, parse_bool, [UNTRACKED], "show macro backtraces (default: no)"), maximal_hir_to_mir_coverage: bool = (false, parse_bool, [TRACKED],