From 8cc8133973d42abe273bb1d6b8a9e30fdae5f0c9 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 9 Aug 2019 02:16:45 +0300 Subject: [PATCH] Fix calls to resolver from rustdoc and HIR lowering Cleanup some surrounding code. Support resolution of intra doc links in unnamed block scopes. (Paths from rustdoc now use early resolution and no longer need results of late resolution like all the built ribs.) Fix one test hitting file path limits on Windows. --- src/librustc/hir/lowering.rs | 15 ++-- src/librustc_resolve/late.rs | 2 +- src/librustc_resolve/lib.rs | 69 +++++++++---------- .../passes/collect_intra_doc_links.rs | 21 +++--- ...nds-pick-original-type-alias-impl-trait.rs | 2 +- 5 files changed, 48 insertions(+), 61 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 493083c680a..42acbd1106b 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -37,7 +37,7 @@ use crate::hir::{self, ParamName}; use crate::hir::HirVec; use crate::hir::map::{DefKey, DefPathData, Definitions}; use crate::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; -use crate::hir::def::{Res, DefKind, PartialRes, PerNS}; +use crate::hir::def::{Namespace, Res, DefKind, PartialRes, PerNS}; use crate::hir::{GenericArg, ConstArg}; use crate::hir::ptr::P; use crate::lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES, @@ -148,13 +148,6 @@ pub struct LoweringContext<'a> { } pub trait Resolver { - /// Resolve a path generated by the lowerer when expanding `for`, `if let`, etc. - fn resolve_ast_path( - &mut self, - path: &ast::Path, - is_value: bool, - ) -> Res; - /// Obtain resolution for a `NodeId` with a single resolution. fn get_partial_res(&mut self, id: NodeId) -> Option; @@ -175,7 +168,7 @@ pub trait Resolver { span: Span, crate_root: Option, components: &[Symbol], - is_value: bool, + ns: Namespace, ) -> (ast::Path, Res); fn has_derives(&self, node_id: NodeId, derives: SpecialDerives) -> bool; @@ -5717,8 +5710,8 @@ impl<'a> LoweringContext<'a> { params: Option>, is_value: bool, ) -> hir::Path { - let (path, res) = self.resolver - .resolve_str_path(span, self.crate_root, components, is_value); + let ns = if is_value { Namespace::ValueNS } else { Namespace::TypeNS }; + let (path, res) = self.resolver.resolve_str_path(span, self.crate_root, components, ns); let mut segments: Vec<_> = path.segments.iter().map(|segment| { let res = self.expect_full_res(segment.id); diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 239042505d0..7cb11195ee0 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -541,7 +541,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { crate_lint: CrateLint, ) -> PathResult<'a> { self.r.resolve_path_with_ribs( - path, opt_ns, &self.parent_scope, record_used, path_span, crate_lint, &self.ribs + path, opt_ns, &self.parent_scope, record_used, path_span, crate_lint, Some(&self.ribs) ) } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 83dc40c097b..c5aabb5e068 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -987,26 +987,12 @@ impl<'a, 'b> ty::DefIdTree for &'a Resolver<'b> { /// This interface is used through the AST→HIR step, to embed full paths into the HIR. After that /// the resolver is no longer needed as all the relevant information is inline. impl<'a> hir::lowering::Resolver for Resolver<'a> { - fn resolve_ast_path( - &mut self, - path: &ast::Path, - is_value: bool, - ) -> Res { - match self.resolve_ast_path_inner(path, is_value) { - Ok(r) => r, - Err((span, error)) => { - self.report_error(span, error); - Res::Err - } - } - } - fn resolve_str_path( &mut self, span: Span, crate_root: Option, components: &[Symbol], - is_value: bool + ns: Namespace, ) -> (ast::Path, Res) { let root = if crate_root.is_some() { kw::PathRoot @@ -1025,7 +1011,14 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> { segments, }; - let res = self.resolve_ast_path(&path, is_value); + let parent_scope = &self.dummy_parent_scope(); + let res = match self.resolve_ast_path(&path, ns, parent_scope) { + Ok(res) => res, + Err((span, error)) => { + self.report_error(span, error); + Res::Err + } + }; (path, res) } @@ -1738,7 +1731,7 @@ impl<'a> Resolver<'a> { crate_lint: CrateLint, ) -> PathResult<'a> { self.resolve_path_with_ribs( - path, opt_ns, parent_scope, record_used, path_span, crate_lint, &Default::default() + path, opt_ns, parent_scope, record_used, path_span, crate_lint, None ) } @@ -1750,7 +1743,7 @@ impl<'a> Resolver<'a> { record_used: bool, path_span: Span, crate_lint: CrateLint, - ribs: &PerNS>>, + ribs: Option<&PerNS>>>, ) -> PathResult<'a> { let mut module = None; let mut allow_super = true; @@ -1864,16 +1857,17 @@ impl<'a> Resolver<'a> { self.resolve_ident_in_module( module, ident, ns, parent_scope, record_used, path_span ) - } else if opt_ns.is_none() || opt_ns == Some(MacroNS) { - assert!(ns == TypeNS); - let scopes = if opt_ns.is_none() { ScopeSet::Import(ns) } else { ScopeSet::Module }; + } else if ribs.is_none() || opt_ns.is_none() || opt_ns == Some(MacroNS) { + // FIXME: Decouple the import property from `ScopeSet`. + let is_import = opt_ns.is_none() || ns != TypeNS; + let scopes = if is_import { ScopeSet::Import(ns) } else { ScopeSet::Module }; self.early_resolve_ident_in_lexical_scope(ident, scopes, parent_scope, record_used, record_used, path_span) } else { let record_used_id = if record_used { crate_lint.node_id().or(Some(CRATE_NODE_ID)) } else { None }; match self.resolve_ident_in_lexical_scope( - ident, ns, parent_scope, record_used_id, path_span, &ribs[ns] + ident, ns, parent_scope, record_used_id, path_span, &ribs.unwrap()[ns] ) { // we found a locally-imported or available item/module Some(LexicalScopeBinding::Item(binding)) => Ok(binding), @@ -2639,8 +2633,10 @@ impl<'a> Resolver<'a> { /// isn't something that can be returned because it can't be made to live that long, /// and also it's a private type. Fortunately rustdoc doesn't need to know the error, /// just that an error occurred. - pub fn resolve_str_path_error(&mut self, span: Span, path_str: &str, is_value: bool) - -> Result<(ast::Path, Res), ()> { + // FIXME(Manishearth): intra-doc links won't get warned of epoch changes. + pub fn resolve_str_path_error( + &mut self, span: Span, path_str: &str, ns: Namespace, module_id: NodeId + ) -> Result<(ast::Path, Res), ()> { let path = if path_str.starts_with("::") { ast::Path { span, @@ -2661,28 +2657,31 @@ impl<'a> Resolver<'a> { .collect(), } }; - let res = self.resolve_ast_path_inner(&path, is_value).map_err(|_| ())?; + let module = self.block_map.get(&module_id).copied().unwrap_or_else(|| { + let def_id = self.definitions.local_def_id(module_id); + self.module_map.get(&def_id).copied().unwrap_or(self.graph_root) + }); + let parent_scope = &ParentScope { module, ..self.dummy_parent_scope() }; + let res = self.resolve_ast_path(&path, ns, parent_scope).map_err(|_| ())?; Ok((path, res)) } - /// Like `resolve_ast_path`, but takes a callback in case there was an error. - fn resolve_ast_path_inner( + // Resolve a path passed from rustdoc or HIR lowering. + fn resolve_ast_path( &mut self, path: &ast::Path, - is_value: bool, + ns: Namespace, + parent_scope: &ParentScope<'a>, ) -> Result)> { - let namespace = if is_value { ValueNS } else { TypeNS }; - let span = path.span; - let path = Segment::from_path(&path); - // FIXME(Manishearth): intra-doc links won't get warned of epoch changes. - let parent_scope = &self.dummy_parent_scope(); - match self.resolve_path(&path, Some(namespace), parent_scope, true, span, CrateLint::No) { + match self.resolve_path( + &Segment::from_path(path), Some(ns), parent_scope, true, path.span, CrateLint::No + ) { PathResult::Module(ModuleOrUniformRoot::Module(module)) => Ok(module.res().unwrap()), PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => Ok(path_res.base_res()), PathResult::NonModule(..) => { - Err((span, ResolutionError::FailedToResolve { + Err((path.span, ResolutionError::FailedToResolve { label: String::from("type-relative paths are not supported in this context"), suggestion: None, })) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 84cfdd790b7..5c9fac7eab4 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -61,15 +61,11 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { { let cx = self.cx; - // In case we're in a module, try to resolve the relative - // path. - if let Some(id) = parent_id.or(self.mod_ids.last().cloned()) { - // FIXME: `with_scope` requires the `NodeId` of a module. - let node_id = cx.tcx.hir().hir_to_node_id(id); + // 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().hir_to_node_id(module_id); let result = cx.enter_resolver(|resolver| { - resolver.with_scope(node_id, |resolver| { - resolver.resolve_str_path_error(DUMMY_SP, &path_str, ns == ValueNS) - }) + resolver.resolve_str_path_error(DUMMY_SP, &path_str, ns, module_id) }); let result = match result { Ok((_, Res::Err)) => Err(()), @@ -85,6 +81,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { Res::Def(DefKind::AssocTy, _) => false, Res::Def(DefKind::Variant, _) => return handle_variant(cx, res), // Not a trait item; just return what we found. + Res::PrimTy(..) => return Ok((res, Some(path_str.to_owned()))), _ => return Ok((res, None)) }; @@ -133,11 +130,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { .ok_or(()); } - // FIXME: `with_scope` requires the `NodeId` of a module. - let node_id = cx.tcx.hir().hir_to_node_id(id); - let (_, ty_res) = cx.enter_resolver(|resolver| resolver.with_scope(node_id, |resolver| { - resolver.resolve_str_path_error(DUMMY_SP, &path, false) - }))?; + let (_, ty_res) = cx.enter_resolver(|resolver| { + resolver.resolve_str_path_error(DUMMY_SP, &path, TypeNS, module_id) + })?; if let Res::Err = ty_res { return Err(()); } diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-type-alias-impl-trait.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-type-alias-impl-trait.rs index ae44b371f4f..877940c7403 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-type-alias-impl-trait.rs +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-type-alias-impl-trait.rs @@ -1,5 +1,5 @@ // edition:2018 -// build-pass (FIXME(62277): could be check-pass?) +// check-pass // revisions: migrate mir //[mir]compile-flags: -Z borrowck=mir