Skip to content

Commit 17132ce

Browse files
authored
Rollup merge of rust-lang#82402 - jyn514:module-cache-refcell, r=GuillaumeGomez
Remove RefCell around `module_trait_cache` This builds on rust-lang#82018 and should not be merged before. ## Don't require a `DocContext` for `report_diagnostic` This is needed for the next commit, which needs mutable access to the `cx` from within the `decorate` closure. - Change `as_local_hir_id` to an associated function, since it only needs a `TyCtxt` - Change `source_span_for_markdown_range` to only take a `TyCtxt` ## Remove RefCell around module_trait_cache This is mostly just changing lots of functions from `&DocContext` to `&mut DocContext`.
2 parents 4c7e3ce + 675edd0 commit 17132ce

7 files changed

+56
-50
lines changed

src/librustdoc/core.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ crate struct DocContext<'tcx> {
7676
///
7777
/// See `collect_intra_doc_links::traits_implemented_by` for more details.
7878
/// `map<module, set<trait>>`
79-
crate module_trait_cache: RefCell<FxHashMap<DefId, FxHashSet<DefId>>>,
79+
crate module_trait_cache: FxHashMap<DefId, FxHashSet<DefId>>,
8080
/// This same cache is used throughout rustdoc, including in [`crate::html::render`].
8181
crate cache: Cache,
8282
/// Used by [`clean::inline`] to tell if an item has already been inlined.
@@ -169,13 +169,13 @@ impl<'tcx> DocContext<'tcx> {
169169

170170
/// Like `hir().local_def_id_to_hir_id()`, but skips calling it on fake DefIds.
171171
/// (This avoids a slice-index-out-of-bounds panic.)
172-
crate fn as_local_hir_id(&self, def_id: DefId) -> Option<HirId> {
172+
crate fn as_local_hir_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option<HirId> {
173173
if MAX_DEF_IDX.with(|m| {
174174
m.borrow().get(&def_id.krate).map(|&idx| idx <= def_id.index).unwrap_or(false)
175175
}) {
176176
None
177177
} else {
178-
def_id.as_local().map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id))
178+
def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
179179
}
180180
}
181181
}
@@ -450,7 +450,7 @@ crate fn run_global_ctxt(
450450
.cloned()
451451
.filter(|trait_def_id| tcx.trait_is_auto(*trait_def_id))
452452
.collect(),
453-
module_trait_cache: RefCell::new(FxHashMap::default()),
453+
module_trait_cache: FxHashMap::default(),
454454
cache: Cache::new(access_levels, render_options.document_private),
455455
inlined: FxHashSet::default(),
456456
output_format,
@@ -479,7 +479,7 @@ crate fn run_global_ctxt(
479479
https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation.html";
480480
tcx.struct_lint_node(
481481
crate::lint::MISSING_CRATE_LEVEL_DOCS,
482-
ctxt.as_local_hir_id(m.def_id).unwrap(),
482+
DocContext::as_local_hir_id(tcx, m.def_id).unwrap(),
483483
|lint| {
484484
let mut diag =
485485
lint.build("no documentation found for this crate's top-level module");

src/librustdoc/passes/check_code_block_syntax.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,12 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
4848
let buffer = buffer.borrow();
4949

5050
if buffer.has_errors || is_empty {
51-
let mut diag = if let Some(sp) =
52-
super::source_span_for_markdown_range(self.cx, &dox, &code_block.range, &item.attrs)
53-
{
51+
let mut diag = if let Some(sp) = super::source_span_for_markdown_range(
52+
self.cx.tcx,
53+
&dox,
54+
&code_block.range,
55+
&item.attrs,
56+
) {
5457
let (warning_message, suggest_using_text) = if buffer.has_errors {
5558
("could not parse code block as Rust code", true)
5659
} else {

src/librustdoc/passes/collect_intra_doc_links.rs

+34-33
Original file line numberDiff line numberDiff line change
@@ -484,21 +484,23 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
484484
/// Resolves a string as a path within a particular namespace. Returns an
485485
/// optional URL fragment in the case of variants and methods.
486486
fn resolve<'path>(
487-
&self,
487+
&mut self,
488488
path_str: &'path str,
489489
ns: Namespace,
490490
module_id: DefId,
491491
extra_fragment: &Option<String>,
492492
) -> Result<(Res, Option<String>), ErrorKind<'path>> {
493-
let cx = &self.cx;
493+
let tcx = self.cx.tcx;
494494

495495
if let Some(res) = self.resolve_path(path_str, ns, module_id) {
496496
match res {
497497
// FIXME(#76467): make this fallthrough to lookup the associated
498498
// item a separate function.
499499
Res::Def(DefKind::AssocFn | DefKind::AssocConst, _) => assert_eq!(ns, ValueNS),
500500
Res::Def(DefKind::AssocTy, _) => assert_eq!(ns, TypeNS),
501-
Res::Def(DefKind::Variant, _) => return handle_variant(cx, res, extra_fragment),
501+
Res::Def(DefKind::Variant, _) => {
502+
return handle_variant(self.cx, res, extra_fragment);
503+
}
502504
// Not a trait item; just return what we found.
503505
Res::Primitive(ty) => {
504506
if extra_fragment.is_some() {
@@ -565,13 +567,12 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
565567
) => {
566568
debug!("looking for associated item named {} for item {:?}", item_name, did);
567569
// Checks if item_name belongs to `impl SomeItem`
568-
let assoc_item = cx
569-
.tcx
570+
let assoc_item = tcx
570571
.inherent_impls(did)
571572
.iter()
572573
.flat_map(|&imp| {
573-
cx.tcx.associated_items(imp).find_by_name_and_namespace(
574-
cx.tcx,
574+
tcx.associated_items(imp).find_by_name_and_namespace(
575+
tcx,
575576
Ident::with_dummy_span(item_name),
576577
ns,
577578
imp,
@@ -587,7 +588,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
587588
// something like [`ambi_fn`](<SomeStruct as SomeTrait>::ambi_fn)
588589
.or_else(|| {
589590
let kind =
590-
resolve_associated_trait_item(did, module_id, item_name, ns, &self.cx);
591+
resolve_associated_trait_item(did, module_id, item_name, ns, self.cx);
591592
debug!("got associated item kind {:?}", kind);
592593
kind
593594
});
@@ -611,7 +612,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
611612
debug!("looking for variants or fields named {} for {:?}", item_name, did);
612613
// FIXME(jynelson): why is this different from
613614
// `variant_field`?
614-
match cx.tcx.type_of(did).kind() {
615+
match tcx.type_of(did).kind() {
615616
ty::Adt(def, _) => {
616617
let field = if def.is_enum() {
617618
def.all_fields().find(|item| item.ident.name == item_name)
@@ -652,10 +653,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
652653
None
653654
}
654655
}
655-
Res::Def(DefKind::Trait, did) => cx
656-
.tcx
656+
Res::Def(DefKind::Trait, did) => tcx
657657
.associated_items(did)
658-
.find_by_name_and_namespace(cx.tcx, Ident::with_dummy_span(item_name), ns, did)
658+
.find_by_name_and_namespace(tcx, Ident::with_dummy_span(item_name), ns, did)
659659
.map(|item| {
660660
let kind = match item.kind {
661661
ty::AssocKind::Const => "associatedconstant",
@@ -699,7 +699,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
699699
/// This returns the `Res` even if it was erroneous for some reason
700700
/// (such as having invalid URL fragments or being in the wrong namespace).
701701
fn check_full_res(
702-
&self,
702+
&mut self,
703703
ns: Namespace,
704704
path_str: &str,
705705
module_id: DefId,
@@ -733,7 +733,7 @@ fn resolve_associated_trait_item(
733733
module: DefId,
734734
item_name: Symbol,
735735
ns: Namespace,
736-
cx: &DocContext<'_>,
736+
cx: &mut DocContext<'_>,
737737
) -> Option<(ty::AssocKind, DefId)> {
738738
// FIXME: this should also consider blanket impls (`impl<T> X for T`). Unfortunately
739739
// `get_auto_trait_and_blanket_impls` is broken because the caching behavior is wrong. In the
@@ -758,10 +758,10 @@ fn resolve_associated_trait_item(
758758
///
759759
/// NOTE: this cannot be a query because more traits could be available when more crates are compiled!
760760
/// So it is not stable to serialize cross-crate.
761-
fn traits_implemented_by(cx: &DocContext<'_>, type_: DefId, module: DefId) -> FxHashSet<DefId> {
762-
let mut cache = cx.module_trait_cache.borrow_mut();
763-
let in_scope_traits = cache.entry(module).or_insert_with(|| {
764-
cx.enter_resolver(|resolver| {
761+
fn traits_implemented_by(cx: &mut DocContext<'_>, type_: DefId, module: DefId) -> FxHashSet<DefId> {
762+
let mut resolver = cx.resolver.borrow_mut();
763+
let in_scope_traits = cx.module_trait_cache.entry(module).or_insert_with(|| {
764+
resolver.access(|resolver| {
765765
let parent_scope = &ParentScope::module(resolver.get_module(module), resolver);
766766
resolver
767767
.traits_in_scope(None, parent_scope, SyntaxContext::root(), None)
@@ -771,13 +771,14 @@ fn traits_implemented_by(cx: &DocContext<'_>, type_: DefId, module: DefId) -> Fx
771771
})
772772
});
773773

774-
let ty = cx.tcx.type_of(type_);
774+
let tcx = cx.tcx;
775+
let ty = tcx.type_of(type_);
775776
let iter = in_scope_traits.iter().flat_map(|&trait_| {
776777
trace!("considering explicit impl for trait {:?}", trait_);
777778

778779
// Look at each trait implementation to see if it's an impl for `did`
779-
cx.tcx.find_map_relevant_impl(trait_, ty, |impl_| {
780-
let trait_ref = cx.tcx.impl_trait_ref(impl_).expect("this is not an inherent impl");
780+
tcx.find_map_relevant_impl(trait_, ty, |impl_| {
781+
let trait_ref = tcx.impl_trait_ref(impl_).expect("this is not an inherent impl");
781782
// Check if these are the same type.
782783
let impl_type = trait_ref.self_ty();
783784
trace!(
@@ -1146,7 +1147,7 @@ impl LinkCollector<'_, '_> {
11461147
suggest_disambiguator(resolved, diag, path_str, dox, sp, &ori_link.range);
11471148
};
11481149
report_diagnostic(
1149-
self.cx,
1150+
self.cx.tcx,
11501151
BROKEN_INTRA_DOC_LINKS,
11511152
&msg,
11521153
&item,
@@ -1220,7 +1221,7 @@ impl LinkCollector<'_, '_> {
12201221
&& !self.cx.tcx.features().intra_doc_pointers
12211222
{
12221223
let span = super::source_span_for_markdown_range(
1223-
self.cx,
1224+
self.cx.tcx,
12241225
dox,
12251226
&ori_link.range,
12261227
&item.attrs,
@@ -1308,7 +1309,7 @@ impl LinkCollector<'_, '_> {
13081309
/// After parsing the disambiguator, resolve the main part of the link.
13091310
// FIXME(jynelson): wow this is just so much
13101311
fn resolve_with_disambiguator(
1311-
&self,
1312+
&mut self,
13121313
key: &ResolutionInfo,
13131314
diag: DiagnosticInfo<'_>,
13141315
) -> Option<(Res, Option<String>)> {
@@ -1674,15 +1675,15 @@ impl Suggestion {
16741675
/// parameter of the callback will contain it, and the primary span of the diagnostic will be set
16751676
/// to it.
16761677
fn report_diagnostic(
1677-
cx: &DocContext<'_>,
1678+
tcx: TyCtxt<'_>,
16781679
lint: &'static Lint,
16791680
msg: &str,
16801681
item: &Item,
16811682
dox: &str,
16821683
link_range: &Range<usize>,
16831684
decorate: impl FnOnce(&mut DiagnosticBuilder<'_>, Option<rustc_span::Span>),
16841685
) {
1685-
let hir_id = match cx.as_local_hir_id(item.def_id) {
1686+
let hir_id = match DocContext::as_local_hir_id(tcx, item.def_id) {
16861687
Some(hir_id) => hir_id,
16871688
None => {
16881689
// If non-local, no need to check anything.
@@ -1694,10 +1695,10 @@ fn report_diagnostic(
16941695
let attrs = &item.attrs;
16951696
let sp = span_of_attrs(attrs).unwrap_or(item.source.span());
16961697

1697-
cx.tcx.struct_span_lint_hir(lint, hir_id, sp, |lint| {
1698+
tcx.struct_span_lint_hir(lint, hir_id, sp, |lint| {
16981699
let mut diag = lint.build(msg);
16991700

1700-
let span = super::source_span_for_markdown_range(cx, dox, link_range, attrs);
1701+
let span = super::source_span_for_markdown_range(tcx, dox, link_range, attrs);
17011702

17021703
if let Some(sp) = span {
17031704
diag.set_span(sp);
@@ -1732,7 +1733,7 @@ fn report_diagnostic(
17321733
/// handled earlier. For example, if passed `Item::Crate(std)` and `path_str`
17331734
/// `std::io::Error::x`, this will resolve `std::io::Error`.
17341735
fn resolution_failure(
1735-
collector: &LinkCollector<'_, '_>,
1736+
collector: &mut LinkCollector<'_, '_>,
17361737
item: &Item,
17371738
path_str: &str,
17381739
disambiguator: Option<Disambiguator>,
@@ -1742,7 +1743,7 @@ fn resolution_failure(
17421743
) {
17431744
let tcx = collector.cx.tcx;
17441745
report_diagnostic(
1745-
collector.cx,
1746+
tcx,
17461747
BROKEN_INTRA_DOC_LINKS,
17471748
&format!("unresolved link to `{}`", path_str),
17481749
item,
@@ -1973,7 +1974,7 @@ fn anchor_failure(
19731974
),
19741975
};
19751976

1976-
report_diagnostic(cx, BROKEN_INTRA_DOC_LINKS, &msg, item, dox, &link_range, |diag, sp| {
1977+
report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, item, dox, &link_range, |diag, sp| {
19771978
if let Some(sp) = sp {
19781979
diag.span_label(sp, "contains invalid anchor");
19791980
}
@@ -2013,7 +2014,7 @@ fn ambiguity_error(
20132014
}
20142015
}
20152016

2016-
report_diagnostic(cx, BROKEN_INTRA_DOC_LINKS, &msg, item, dox, &link_range, |diag, sp| {
2017+
report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, item, dox, &link_range, |diag, sp| {
20172018
if let Some(sp) = sp {
20182019
diag.span_label(sp, "ambiguous link");
20192020
} else {
@@ -2066,7 +2067,7 @@ fn privacy_error(cx: &DocContext<'_>, item: &Item, path_str: &str, dox: &str, li
20662067
let msg =
20672068
format!("public documentation for `{}` links to private item `{}`", item_name, path_str);
20682069

2069-
report_diagnostic(cx, PRIVATE_INTRA_DOC_LINKS, &msg, item, dox, &link.range, |diag, sp| {
2070+
report_diagnostic(cx.tcx, PRIVATE_INTRA_DOC_LINKS, &msg, item, dox, &link.range, |diag, sp| {
20702071
if let Some(sp) = sp {
20712072
diag.span_label(sp, "this item is private");
20722073
}

src/librustdoc/passes/doc_test_lints.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ crate fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> boo
8282
}
8383

8484
crate fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
85-
let hir_id = match cx.as_local_hir_id(item.def_id) {
85+
let hir_id = match DocContext::as_local_hir_id(cx.tcx, item.def_id) {
8686
Some(hir_id) => hir_id,
8787
None => {
8888
// If non-local, no need to check anything.

src/librustdoc/passes/html_tags.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,8 @@ fn extract_tags(
167167

168168
impl<'a, 'tcx> DocFolder for InvalidHtmlTagsLinter<'a, 'tcx> {
169169
fn fold_item(&mut self, item: Item) -> Option<Item> {
170-
let hir_id = match self.cx.as_local_hir_id(item.def_id) {
170+
let tcx = self.cx.tcx;
171+
let hir_id = match DocContext::as_local_hir_id(tcx, item.def_id) {
171172
Some(hir_id) => hir_id,
172173
None => {
173174
// If non-local, no need to check anything.
@@ -176,13 +177,13 @@ impl<'a, 'tcx> DocFolder for InvalidHtmlTagsLinter<'a, 'tcx> {
176177
};
177178
let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
178179
if !dox.is_empty() {
179-
let cx = &self.cx;
180180
let report_diag = |msg: &str, range: &Range<usize>| {
181-
let sp = match super::source_span_for_markdown_range(cx, &dox, range, &item.attrs) {
181+
let sp = match super::source_span_for_markdown_range(tcx, &dox, range, &item.attrs)
182+
{
182183
Some(sp) => sp,
183184
None => span_of_attrs(&item.attrs).unwrap_or(item.source.span()),
184185
};
185-
cx.tcx.struct_span_lint_hir(crate::lint::INVALID_HTML_TAGS, hir_id, sp, |lint| {
186+
tcx.struct_span_lint_hir(crate::lint::INVALID_HTML_TAGS, hir_id, sp, |lint| {
186187
lint.build(msg).emit()
187188
});
188189
};

src/librustdoc/passes/mod.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Contains information about "passes", used to modify crate information during the documentation
22
//! process.
33
4+
use rustc_middle::ty::TyCtxt;
45
use rustc_span::{InnerSpan, Span, DUMMY_SP};
56
use std::ops::Range;
67

@@ -167,7 +168,7 @@ crate fn span_of_attrs(attrs: &clean::Attributes) -> Option<Span> {
167168
/// attributes are not all sugared doc comments. It's difficult to calculate the correct span in
168169
/// that case due to escaping and other source features.
169170
crate fn source_span_for_markdown_range(
170-
cx: &DocContext<'_>,
171+
tcx: TyCtxt<'_>,
171172
markdown: &str,
172173
md_range: &Range<usize>,
173174
attrs: &clean::Attributes,
@@ -179,7 +180,7 @@ crate fn source_span_for_markdown_range(
179180
return None;
180181
}
181182

182-
let snippet = cx.sess().source_map().span_to_snippet(span_of_attrs(attrs)?).ok()?;
183+
let snippet = tcx.sess.source_map().span_to_snippet(span_of_attrs(attrs)?).ok()?;
183184

184185
let starting_line = markdown[..md_range.start].matches('\n').count();
185186
let ending_line = starting_line + markdown[md_range.start..md_range.end].matches('\n').count();

src/librustdoc/passes/non_autolinks.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ crate fn check_non_autolinks(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
6060

6161
impl<'a, 'tcx> DocFolder for NonAutolinksLinter<'a, 'tcx> {
6262
fn fold_item(&mut self, item: Item) -> Option<Item> {
63-
let hir_id = match self.cx.as_local_hir_id(item.def_id) {
63+
let hir_id = match DocContext::as_local_hir_id(self.cx.tcx, item.def_id) {
6464
Some(hir_id) => hir_id,
6565
None => {
6666
// If non-local, no need to check anything.
@@ -70,7 +70,7 @@ impl<'a, 'tcx> DocFolder for NonAutolinksLinter<'a, 'tcx> {
7070
let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
7171
if !dox.is_empty() {
7272
let report_diag = |cx: &DocContext<'_>, msg: &str, url: &str, range: Range<usize>| {
73-
let sp = super::source_span_for_markdown_range(cx, &dox, &range, &item.attrs)
73+
let sp = super::source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs)
7474
.or_else(|| span_of_attrs(&item.attrs))
7575
.unwrap_or(item.source.span());
7676
cx.tcx.struct_span_lint_hir(crate::lint::NON_AUTOLINKS, hir_id, sp, |lint| {

0 commit comments

Comments
 (0)