From 5d38a15d0bb171e05672db7acbe81cc3eccbaa39 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 27 Mar 2023 11:39:43 -0700 Subject: [PATCH 1/3] rustdoc: convert `masked_crates` to a query --- compiler/rustc_metadata/src/rmeta/decoder.rs | 6 +++++ .../src/rmeta/decoder/cstore_impl.rs | 24 +++++++++++++++++-- compiler/rustc_metadata/src/rmeta/encoder.rs | 22 +++++++++++++++++ compiler/rustc_metadata/src/rmeta/mod.rs | 2 ++ compiler/rustc_middle/src/query/mod.rs | 13 ++++++++++ compiler/rustc_middle/src/ty/parameterized.rs | 1 + compiler/rustc_middle/src/ty/util.rs | 19 +++++++++++++++ src/librustdoc/clean/types.rs | 16 ------------- src/librustdoc/clean/utils.rs | 16 ------------- src/librustdoc/formats/cache.rs | 15 +++--------- 10 files changed, 88 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 06a64f0db0e32..466a8836e4ac4 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1549,6 +1549,12 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.root.tables.is_intrinsic.get(self, index) } + fn get_doc_masked_crates(self) -> Vec { + let mut v: Vec = self.root.doc_masked_crates.decode(self).collect(); + v.sort_unstable(); + v + } + fn get_doc_link_resolutions(self, index: DefIndex) -> DocLinkResMap { self.root .tables diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 3a50d7c93635c..a1af07d68b45f 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -17,10 +17,10 @@ use rustc_middle::query::LocalCrate; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::query::{ExternProviders, Providers}; use rustc_middle::ty::{self, TyCtxt}; -use rustc_session::cstore::CrateStore; +use rustc_session::cstore::{CrateStore, ExternCrateSource}; use rustc_session::{Session, StableCrateId}; use rustc_span::hygiene::{ExpnHash, ExpnId}; -use rustc_span::symbol::{kw, Symbol}; +use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::Span; use rustc_data_structures::sync::Lrc; @@ -355,6 +355,7 @@ provide! { tcx, def_id, other, cdata, expn_that_defined => { cdata.get_expn_that_defined(def_id.index, tcx.sess) } generator_diagnostic_data => { cdata.get_generator_diagnostic_data(tcx, def_id.index) } is_doc_hidden => { cdata.get_attr_flags(def_id.index).contains(AttrFlags::IS_DOC_HIDDEN) } + doc_masked_crates => { tcx.arena.alloc_from_iter(cdata.get_doc_masked_crates()) } doc_link_resolutions => { tcx.arena.alloc(cdata.get_doc_link_resolutions(def_id.index)) } doc_link_traits_in_scope => { tcx.arena.alloc_from_iter(cdata.get_doc_link_traits_in_scope(def_id.index)) @@ -495,6 +496,25 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { tcx.untracked().cstore.leak(); tcx.arena.alloc_from_iter(CStore::from_tcx(tcx).iter_crate_data().map(|(cnum, _)| cnum)) }, + doc_masked_crates: |tcx, LocalCrate| { + let mut v: Vec = CStore::from_tcx(tcx) + .iter_crate_data() + .filter_map(|(cnum, cdata)| { + if let Some(extern_crate) = *cdata.extern_crate.lock() && + let ExternCrateSource::Extern(did) = extern_crate.src && + tcx + .get_attrs(did, sym::doc) + .filter_map(|attr| attr.meta_item_list()) + .any(|items| items.iter().any(|item| item.has_name(sym::masked))) { + Some(cnum) + } else { + None + } + }) + .collect(); + v.sort_unstable(); + tcx.arena.alloc_from_iter(v) + }, ..*providers }; } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 2652a4280d373..8d0193b9c11ec 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -44,6 +44,7 @@ use std::collections::hash_map::Entry; use std::hash::Hash; use std::io::{Read, Seek, Write}; use std::iter; +use std::mem; use std::num::NonZeroUsize; use std::path::{Path, PathBuf}; @@ -74,6 +75,8 @@ pub(super) struct EncodeContext<'a, 'tcx> { is_proc_macro: bool, hygiene_ctxt: &'a HygieneEncodeContext, symbol_table: FxHashMap, + + doc_masked_crates: Vec, } /// If the current crate is a proc-macro, returns early with `LazyArray::default()`. @@ -642,6 +645,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // encode_def_path_table. let proc_macro_data = stat!("proc-macro-data", || self.encode_proc_macros()); + let doc_masked_crates = stat!("doc-masked-crates", || self.encode_doc_masked_crates()); + let tables = stat!("tables", || self.tables.encode(&mut self.opaque)); let debugger_visualizers = @@ -683,6 +688,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE), has_default_lib_allocator: attr::contains_name(&attrs, sym::default_lib_allocator), proc_macro_data, + doc_masked_crates, debugger_visualizers, compiler_builtins: attr::contains_name(&attrs, sym::compiler_builtins), needs_allocator: attr::contains_name(&attrs, sym::needs_allocator), @@ -770,6 +776,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { struct AnalyzeAttrState { is_exported: bool, is_doc_hidden: bool, + is_doc_masked: bool, } /// Returns whether an attribute needs to be recorded in metadata, that is, if it's usable and @@ -804,6 +811,10 @@ fn analyze_attr(attr: &Attribute, state: &mut AnalyzeAttrState) -> bool { state.is_doc_hidden = true; break; } + if item.has_name(sym::masked) { + state.is_doc_masked = true; + break; + } } } } @@ -1136,6 +1147,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let mut state = AnalyzeAttrState { is_exported: tcx.effective_visibilities(()).is_exported(def_id), is_doc_hidden: false, + is_doc_masked: false, }; let attr_iter = tcx .opt_local_def_id_to_hir_id(def_id) @@ -1149,6 +1161,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if state.is_doc_hidden { attr_flags |= AttrFlags::IS_DOC_HIDDEN; } + if state.is_doc_masked && let Some(krate) = tcx.extern_mod_stmt_cnum(def_id) { + self.doc_masked_crates.push(krate); + } self.tables.attr_flags.set(def_id.local_def_index, attr_flags); } @@ -1784,6 +1799,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } + fn encode_doc_masked_crates(&mut self) -> LazyArray { + empty_proc_macro!(self); + let masked_crates = mem::take(&mut self.doc_masked_crates); + self.lazy_array(masked_crates.iter()) + } + fn encode_debugger_visualizers(&mut self) -> LazyArray { empty_proc_macro!(self); self.lazy_array(self.tcx.debugger_visualizers(LOCAL_CRATE).iter()) @@ -2207,6 +2228,7 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) { is_proc_macro: tcx.sess.crate_types().contains(&CrateType::ProcMacro), hygiene_ctxt: &hygiene_ctxt, symbol_table: Default::default(), + doc_masked_crates: Vec::new(), }; // Encode the rustc version string in a predictable location. diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 6dc6041b284ea..c5081cc217eb5 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -243,6 +243,7 @@ pub(crate) struct CrateRoot { incoherent_impls: LazyArray, interpret_alloc_index: LazyArray, proc_macro_data: Option, + doc_masked_crates: LazyArray, tables: LazyTables, debugger_visualizers: LazyArray, @@ -357,6 +358,7 @@ define_tables! { associated_types_for_impl_traits_in_associated_fn: Table>, opt_rpitit_info: Table>>, unused_generic_params: Table, + doc_masked_crates: Table, - optional: attributes: Table>, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 9203dd59a7e63..5ecd79fee1edf 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1215,6 +1215,19 @@ rustc_queries! { desc { |tcx| "checking whether `{}` is `doc(notable_trait)`", tcx.def_path_str(def_id) } } + /// Determines whether a crate is [`#[doc(masked)]`][doc_masked]. + /// + /// [doc_masked]: https://doc.rust-lang.org/nightly/unstable-book/language-features/doc-masked.html + query is_doc_masked(crate_num: CrateNum) -> bool { + cache_on_disk_if { false } + desc { |tcx| "checking whether crate is `doc(masked)`" } + } + + query doc_masked_crates(crate_num: CrateNum) -> &'tcx [CrateNum] { + desc { |tcx| "list crates marked as #[doc(masked)] by given crate" } + separate_provide_extern + } + /// Returns the attributes on the item at `def_id`. /// /// Do not use this directly, use `tcx.get_attrs` instead. diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 7534d06ae91f1..54bee49ded796 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -83,6 +83,7 @@ trivially_parameterized_over_tcx! { rustc_hir::LangItem, rustc_hir::def::DefKind, rustc_hir::def::DocLinkResMap, + rustc_hir::def_id::CrateNum, rustc_hir::def_id::DefId, rustc_hir::def_id::DefIndex, rustc_hir::definitions::DefKey, diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index dcd9743196e1d..f713d867a5ffc 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -9,6 +9,7 @@ use crate::ty::{ TypeVisitableExt, }; use crate::ty::{GenericArgKind, SubstsRef}; +use hir::def_id::CrateNum; use rustc_apfloat::Float as _; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -1452,6 +1453,23 @@ pub fn is_doc_notable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool { .any(|items| items.iter().any(|item| item.has_name(sym::notable_trait))) } +/// Determines whether a crate is annotated with `doc(masked)`. +pub fn is_doc_masked(tcx: TyCtxt<'_>, crate_num: CrateNum) -> bool { + // The current crate is never masked + if crate_num == rustc_span::def_id::LOCAL_CRATE { + return false; + } + + // `compiler_builtins` should be masked too, but we can't apply + // `#[doc(masked)]` to the injected `extern crate` because it's unstable. + if tcx.is_compiler_builtins(crate_num) { + return true; + } + + let extern_crate = tcx.extern_crate(crate_num.as_def_id()).expect("crate root"); + tcx.doc_masked_crates(extern_crate.dependency_of).binary_search(&crate_num).is_ok() +} + /// Determines whether an item is an intrinsic by Abi. pub fn is_intrinsic(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { matches!(tcx.fn_sig(def_id).skip_binder().abi(), Abi::RustIntrinsic | Abi::PlatformIntrinsic) @@ -1462,6 +1480,7 @@ pub fn provide(providers: &mut ty::query::Providers) { reveal_opaque_types_in_bounds, is_doc_hidden, is_doc_notable_trait, + is_doc_masked, is_intrinsic, ..*providers } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 7dbb3f76a0a83..72c142a1db568 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1057,22 +1057,6 @@ impl Attributes { self.other_attrs.lists(name) } - pub(crate) fn has_doc_flag(&self, flag: Symbol) -> bool { - for attr in &self.other_attrs { - if !attr.has_name(sym::doc) { - continue; - } - - if let Some(items) = attr.meta_item_list() { - if items.iter().filter_map(|i| i.meta_item()).any(|it| it.has_name(flag)) { - return true; - } - } - } - - false - } - pub(crate) fn from_ast(attrs: &[ast::Attribute]) -> Attributes { Attributes::from_ast_iter(attrs.iter().map(|attr| (attr, None)), false) } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index cca50df0db213..3c8531b310c83 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -33,22 +33,6 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate { // understood by rustdoc. let mut module = clean_doc_module(&module, cx); - match *module.kind { - ItemKind::ModuleItem(ref module) => { - for it in &module.items { - // `compiler_builtins` should be masked too, but we can't apply - // `#[doc(masked)]` to the injected `extern crate` because it's unstable. - if it.is_extern_crate() - && (it.attrs.has_doc_flag(sym::masked) - || cx.tcx.is_compiler_builtins(it.item_id.krate())) - { - cx.cache.masked_crates.insert(it.item_id.krate()); - } - } - } - _ => unreachable!(), - } - let local_crate = ExternalCrate { crate_num: LOCAL_CRATE }; let primitives = local_crate.primitives(cx.tcx); let keywords = local_crate.keywords(cx.tcx); diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 0295de8437ef1..e82c6441946bf 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -87,11 +87,6 @@ pub(crate) struct Cache { /// This is stored in `Cache` so it doesn't need to be passed through all rustdoc functions. pub(crate) document_private: bool, - /// Crates marked with [`#[doc(masked)]`][doc_masked]. - /// - /// [doc_masked]: https://doc.rust-lang.org/nightly/unstable-book/language-features/doc-masked.html - pub(crate) masked_crates: FxHashSet, - // Private fields only used when initially crawling a crate to build a cache stack: Vec, parent_stack: Vec, @@ -210,13 +205,9 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // If the impl is from a masked crate or references something from a // masked crate then remove it completely. if let clean::ImplItem(ref i) = *item.kind { - if self.cache.masked_crates.contains(&item.item_id.krate()) - || i.trait_ - .as_ref() - .map_or(false, |t| self.cache.masked_crates.contains(&t.def_id().krate)) - || i.for_ - .def_id(self.cache) - .map_or(false, |d| self.cache.masked_crates.contains(&d.krate)) + if self.tcx.is_doc_masked(item.item_id.krate()) + || i.trait_.as_ref().map_or(false, |t| self.tcx.is_doc_masked(t.def_id().krate)) + || i.for_.def_id(self.cache).map_or(false, |d| self.tcx.is_doc_masked(d.krate)) { return None; } From a28eba90825f3c726e5e914d7d8970ed9e073d99 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 27 Mar 2023 20:44:15 -0700 Subject: [PATCH 2/3] diagnostics: do not suggest masked crate impls --- .../src/traits/error_reporting/mod.rs | 1 + .../auxiliary/masked-crate.rs | 20 ++++++++++++++++ .../issue-88696.rs | 23 +++++++++++++++++++ .../issue-88696.stderr | 11 +++++++++ 4 files changed, 55 insertions(+) create mode 100644 tests/ui/suggestions/dont-suggest-doc-masked-impls/auxiliary/masked-crate.rs create mode 100644 tests/ui/suggestions/dont-suggest-doc-masked-impls/issue-88696.rs create mode 100644 tests/ui/suggestions/dont-suggest-doc-masked-impls/issue-88696.stderr diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index c19798213b70c..465cb9fbd51d7 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2006,6 +2006,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { || !trait_pred .skip_binder() .is_constness_satisfied_by(self.tcx.constness(def_id)) + || self.tcx.is_doc_masked(def_id.krate) { return None; } diff --git a/tests/ui/suggestions/dont-suggest-doc-masked-impls/auxiliary/masked-crate.rs b/tests/ui/suggestions/dont-suggest-doc-masked-impls/auxiliary/masked-crate.rs new file mode 100644 index 0000000000000..27f3345282074 --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-doc-masked-impls/auxiliary/masked-crate.rs @@ -0,0 +1,20 @@ +// derived from miniz_oxide + +pub enum MZStatus {} +pub enum MZError {} + +pub struct StreamResult; + +pub type MZResult = Result; + +impl core::convert::From for MZResult { + fn from(res: StreamResult) -> Self { + loop {} + } +} + +impl core::convert::From<&StreamResult> for MZResult { + fn from(res: &StreamResult) -> Self { + loop {} + } +} diff --git a/tests/ui/suggestions/dont-suggest-doc-masked-impls/issue-88696.rs b/tests/ui/suggestions/dont-suggest-doc-masked-impls/issue-88696.rs new file mode 100644 index 0000000000000..6c69f9b41abb3 --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-doc-masked-impls/issue-88696.rs @@ -0,0 +1,23 @@ +// aux-build:masked-crate.rs +// +// This test case should ensure that miniz_oxide isn't +// suggested, since it's not a direct dependency. + +#![feature(doc_masked)] + +#[doc(masked)] +extern crate masked_crate; + +fn a() -> Result { + Err(1) +} + +fn b() -> Result { + a().into() //~ERROR [E0277] +} + +fn main() { + let _ = dbg!(b()); + // make sure crate actually gets loaded + let _ = masked_crate::StreamResult; +} diff --git a/tests/ui/suggestions/dont-suggest-doc-masked-impls/issue-88696.stderr b/tests/ui/suggestions/dont-suggest-doc-masked-impls/issue-88696.stderr new file mode 100644 index 0000000000000..418250ca579fe --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-doc-masked-impls/issue-88696.stderr @@ -0,0 +1,11 @@ +error[E0277]: the trait bound `Result: From>` is not satisfied + --> $DIR/issue-88696.rs:16:9 + | +LL | a().into() + | ^^^^ the trait `From>` is not implemented for `Result` + | + = note: required for `Result` to implement `Into>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 622e7eb1349a61a7e826abee0f56ff6a55ea0ec2 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 28 Mar 2023 08:42:02 -0700 Subject: [PATCH 3/3] Add comments and move `get_sorted_masked_crates` into a function --- compiler/rustc_metadata/src/rmeta/decoder.rs | 6 +++ .../src/rmeta/decoder/cstore_impl.rs | 40 +++++++++++-------- compiler/rustc_middle/src/query/mod.rs | 8 ++++ .../src/traits/error_reporting/mod.rs | 4 ++ 4 files changed, 41 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 466a8836e4ac4..9f31e88c6026c 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1551,6 +1551,12 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { fn get_doc_masked_crates(self) -> Vec { let mut v: Vec = self.root.doc_masked_crates.decode(self).collect(); + // sort by crate num so that masked crates can use binary search + // see rustc_middle/ty/util.rs:is_doc_masked + // + // we need to do it now, rather than sorting at encode time, because + // the current crate num is based on the current crate, while encoded + // crate nums are based on the number when this dependency was compiled. v.sort_unstable(); v } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index a1af07d68b45f..57e751c63576d 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -497,23 +497,7 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { tcx.arena.alloc_from_iter(CStore::from_tcx(tcx).iter_crate_data().map(|(cnum, _)| cnum)) }, doc_masked_crates: |tcx, LocalCrate| { - let mut v: Vec = CStore::from_tcx(tcx) - .iter_crate_data() - .filter_map(|(cnum, cdata)| { - if let Some(extern_crate) = *cdata.extern_crate.lock() && - let ExternCrateSource::Extern(did) = extern_crate.src && - tcx - .get_attrs(did, sym::doc) - .filter_map(|attr| attr.meta_item_list()) - .any(|items| items.iter().any(|item| item.has_name(sym::masked))) { - Some(cnum) - } else { - None - } - }) - .collect(); - v.sort_unstable(); - tcx.arena.alloc_from_iter(v) + tcx.arena.alloc_from_iter(CStore::from_tcx(tcx).get_sorted_masked_crates(tcx)) }, ..*providers }; @@ -587,6 +571,28 @@ impl CStore { ) -> Span { self.get_crate_data(cnum).get_proc_macro_quoted_span(id, sess) } + + fn get_sorted_masked_crates(&self, tcx: TyCtxt<'_>) -> Vec { + let mut v: Vec = CStore::from_tcx(tcx) + .iter_crate_data() + .filter_map(|(cnum, cdata)| { + if let Some(extern_crate) = *cdata.extern_crate.lock() && + let ExternCrateSource::Extern(did) = extern_crate.src && + tcx + .get_attrs(did, sym::doc) + .filter_map(|attr| attr.meta_item_list()) + .any(|items| items.iter().any(|item| item.has_name(sym::masked))) { + Some(cnum) + } else { + None + } + }) + .collect(); + // sort by crate num so that masked crates can use binary search + // see rustc_middle/ty/util.rs:is_doc_masked + v.sort_unstable(); + v + } } impl CrateStore for CStore { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 5ecd79fee1edf..8804670bbc9a9 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1223,6 +1223,14 @@ rustc_queries! { desc { |tcx| "checking whether crate is `doc(masked)`" } } + /// Returns a list of crates declared [`#[doc(masked)]`][doc_masked] at import time. + /// + /// This query is used along with `ExternCrate::dependency_of` to derive the `is_doc_masked` + /// flag. It returns a sorted list of `CrateNum`s that can be binary searched (it doesn't use + /// `UnsortSet` because that would require declaring a new arena to intern the results, and + /// `#[doc(masked)]` is an unstable feature used by the standard library, so N=3). + /// + /// [doc_masked]: https://doc.rust-lang.org/nightly/unstable-book/language-features/doc-masked.html query doc_masked_crates(crate_num: CrateNum) -> &'tcx [CrateNum] { desc { |tcx| "list crates marked as #[doc(masked)] by given crate" } separate_provide_extern diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 465cb9fbd51d7..3ddcae15b0556 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2006,6 +2006,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { || !trait_pred .skip_binder() .is_constness_satisfied_by(self.tcx.constness(def_id)) + // FIXME: `#[doc(masked)]` prevents private dependencies of the standard + // library from showing up in the docs. It's probably not great using `#[doc]` + // attributes in the trait engine, and `masked` in particular doesn't have + // a good specification for its semantics. || self.tcx.is_doc_masked(def_id.krate) { return None;