From 848a766e24b799d27e7ae7479cd1f8c07047a53e Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 6 Jun 2020 13:09:05 -0400 Subject: [PATCH] Use the scope of the imported variable for resolution, not the current scope - Accept DefId in resolve_str_path_error This will probably break lots of internal invariants. --- src/librustc_resolve/lib.rs | 4 +- src/librustdoc/core.rs | 2 +- .../passes/collect_intra_doc_links.rs | 96 ++++++++++++++++++- 3 files changed, 95 insertions(+), 7 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 0f2559e4b19..686385e24ec 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2978,7 +2978,7 @@ pub fn resolve_str_path_error( span: Span, path_str: &str, ns: Namespace, - module_id: LocalDefId, + module_id: DefId, ) -> Result<(ast::Path, Res), ()> { let path = if path_str.starts_with("::") { ast::Path { @@ -2998,7 +2998,7 @@ pub fn resolve_str_path_error( .collect(), } }; - let module = self.get_module(module_id.to_def_id()); + let module = self.get_module(module_id); let parent_scope = &ParentScope::module(module); let res = self.resolve_ast_path(&path, ns, parent_scope).map_err(|_| ())?; Ok((path, res)) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 00315675faf..6a52974534f 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -430,7 +430,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt DUMMY_SP, extern_name, TypeNS, - LocalDefId { local_def_index: CRATE_DEF_INDEX }, + LocalDefId { local_def_index: CRATE_DEF_INDEX }.to_def_id(), ) .unwrap_or_else(|()| { panic!("Unable to resolve external crate {}", extern_name) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index f707c1a3e1a..fce7096a1af 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -62,7 +62,7 @@ fn variant_field( &self, path_str: &str, current_item: &Option, - module_id: LocalDefId, + module_id: DefId, ) -> Result<(Res, Option), ErrorKind> { let cx = self.cx; @@ -167,15 +167,103 @@ fn resolve( disambiguator: Option<&str>, ns: Namespace, current_item: &Option, - parent_id: Option, + mut parent_id: Option, extra_fragment: &Option, item_opt: Option<&Item>, ) -> Result<(Res, Option), ErrorKind> { + use rustc_hir::{ItemKind, UseKind}; + let cx = self.cx; + // In case this is a re-export, try to resolve the docs relative to the original module. + // Since we don't document `use` statements, + // we don't have to consider the case where an item is documented in both the original module and the current module. + let mut module_id = None; + if let Some(item) = item_opt { + if let ItemEnum::ImportItem(import) = &item.inner { + if let Import::Simple(_, source) = import { + if let Some(def_id) = source.did { + use crate::rustc_middle::ty::DefIdTree; + + //let mut current_id = def_id; + if cx.tcx.def_kind(def_id) == DefKind::Mod { + module_id = Some(def_id); + debug!("found parent module {:?} for use statement", def_id); + //break; + } else { + debug!( + "not a module: {:?} (maybe an associated item?)", + cx.tcx.def_kind(def_id) + ); + } + + /* + // For associated items, the parent module might be multiple nodes above + while let Some(parent) = cx.tcx.parent(current_id) { + if cx.tcx.def_kind(parent) == DefKind::Mod { + parent_id = Some(parent); + debug!("found parent module {:?} for use statement", parent); + break; + } + current_id = parent; + } + */ + } else { + debug!("no def id found"); + } + } else { + debug!("glob imports not handled for intra-doc links"); + } + } + /* + if let Some(reexport) = item.reexport { + use crate::rustc_middle::ty::DefIdTree; + + let mut current_id = reexport; + // For associated items, the parent module might be multiple nodes above + while let Some(parent) = cx.tcx.parent(current_id) { + if cx.tcx.def_kind(parent) == DefKind::Mod { + parent_id = Some(parent); + debug!("found parent module {:?} for use statement", parent); + break; + } + current_id = parent; + } + } + */ + /* + if let ItemKind::Use(path, use_kind) = item.kind { + if use_kind == UseKind::Single { + match path.res { + Res::Def(def_kind, def_id) => { + use crate::rustc_middle::ty::DefIdTree; + + let mut current_id = def_id; + // For associated items, the parent module might be multiple nodes above + while let Some(parent) = cx.tcx.parent(current_id) { + if cx.tcx.def_kind(parent) == DefKind::Mod { + parent_id = Some(parent); + debug!("found parent module {:?} for use statement", parent); + break; + } + current_id = parent; + } + } + _ => debug!("use {:?} was not a definition, not treating as cross-crate", item.name), + } + } else { + debug!("don't know how to resolve multiple imports for {:?}, not treating as cross-crate", path); + } + } + */ + } + // In case we're in a module, try to resolve the relative path. - if let Some(module_id) = parent_id.or(self.mod_ids.last().cloned()) { - let module_id = cx.tcx.hir().local_def_id(module_id); + if module_id.is_none() { + let id = parent_id.or(self.mod_ids.last().cloned()); + module_id = id.map(|id| cx.tcx.hir().local_def_id(id).to_def_id()); + } + if let Some(module_id) = module_id { let result = cx.enter_resolver(|resolver| { resolver.resolve_str_path_error(DUMMY_SP, &path_str, ns, module_id) }); -- GitLab