Handle relative paths
This commit is contained in:
parent
8166b59c74
commit
4f10f676d9
@ -1413,8 +1413,17 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> {
|
|||||||
|
|
||||||
fn resolve_str_path(&mut self, span: Span, crate_root: Option<&str>,
|
fn resolve_str_path(&mut self, span: Span, crate_root: Option<&str>,
|
||||||
components: &[&str], is_value: bool) -> hir::Path {
|
components: &[&str], is_value: bool) -> hir::Path {
|
||||||
self.resolve_str_path_cb(span, crate_root, components, is_value,
|
use std::iter;
|
||||||
|resolver, span, error| resolve_error(resolver, span, error))
|
let mut path = hir::Path {
|
||||||
|
span,
|
||||||
|
def: Def::Err,
|
||||||
|
segments: iter::once(keywords::CrateRoot.name()).chain({
|
||||||
|
crate_root.into_iter().chain(components.iter().cloned()).map(Symbol::intern)
|
||||||
|
}).map(hir::PathSegment::from_name).collect(),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.resolve_hir_path(&mut path, is_value);
|
||||||
|
path
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution> {
|
fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution> {
|
||||||
@ -1427,33 +1436,31 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Resolver<'a> {
|
impl<'a> Resolver<'a> {
|
||||||
/// resolve_str_path, but takes a callback in case there was an error
|
|
||||||
fn resolve_str_path_cb<F>(&mut self, span: Span, crate_root: Option<&str>,
|
|
||||||
components: &[&str], is_value: bool, error_callback: F) -> hir::Path
|
|
||||||
where F: for<'b, 'c> FnOnce(&'c mut Resolver, Span, ResolutionError<'b>)
|
|
||||||
{
|
|
||||||
use std::iter;
|
|
||||||
let mut path = hir::Path {
|
|
||||||
span,
|
|
||||||
def: Def::Err,
|
|
||||||
segments: iter::once(keywords::CrateRoot.name()).chain({
|
|
||||||
crate_root.into_iter().chain(components.iter().cloned()).map(Symbol::intern)
|
|
||||||
}).map(hir::PathSegment::from_name).collect(),
|
|
||||||
};
|
|
||||||
|
|
||||||
self.resolve_hir_path_cb(&mut path, is_value, error_callback);
|
|
||||||
path
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Rustdoc uses this to resolve things in a recoverable way. ResolutionError<'a>
|
/// Rustdoc uses this to resolve things in a recoverable way. ResolutionError<'a>
|
||||||
/// isn't something that can be returned because it can't be made to live that long,
|
/// 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,
|
/// and also it's a private type. Fortunately rustdoc doesn't need to know the error,
|
||||||
/// just that an error occured.
|
/// just that an error occured.
|
||||||
pub fn resolve_str_path_error(&mut self, span: Span, crate_root: Option<&str>,
|
pub fn resolve_str_path_error(&mut self, span: Span, path_str: &str, is_value: bool) -> Result<hir::Path, ()> {
|
||||||
components: &[&str], is_value: bool) -> Result<hir::Path, ()> {
|
use std::iter;
|
||||||
let mut errored = false;
|
let mut errored = false;
|
||||||
let path = self.resolve_str_path_cb(span, crate_root, components, is_value,
|
|
||||||
|_, _, _| errored = true);
|
let mut path = if path_str.starts_with("::") {
|
||||||
|
hir::Path {
|
||||||
|
span,
|
||||||
|
def: Def::Err,
|
||||||
|
segments: iter::once(keywords::CrateRoot.name()).chain({
|
||||||
|
path_str.split("::").skip(1).map(Symbol::intern)
|
||||||
|
}).map(hir::PathSegment::from_name).collect(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hir::Path {
|
||||||
|
span,
|
||||||
|
def: Def::Err,
|
||||||
|
segments: path_str.split("::").map(Symbol::intern)
|
||||||
|
.map(hir::PathSegment::from_name).collect(),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
self.resolve_hir_path_cb(&mut path, is_value, |_, _, _| errored = true);
|
||||||
if errored || path.def == Def::Err {
|
if errored || path.def == Def::Err {
|
||||||
Err(())
|
Err(())
|
||||||
} else {
|
} else {
|
||||||
@ -1883,8 +1890,8 @@ impl<'a> Resolver<'a> {
|
|||||||
// generate a fake "implementation scope" containing all the
|
// generate a fake "implementation scope" containing all the
|
||||||
// implementations thus found, for compatibility with old resolve pass.
|
// implementations thus found, for compatibility with old resolve pass.
|
||||||
|
|
||||||
fn with_scope<F>(&mut self, id: NodeId, f: F)
|
pub fn with_scope<F, T>(&mut self, id: NodeId, f: F) -> T
|
||||||
where F: FnOnce(&mut Resolver)
|
where F: FnOnce(&mut Resolver) -> T
|
||||||
{
|
{
|
||||||
let id = self.definitions.local_def_id(id);
|
let id = self.definitions.local_def_id(id);
|
||||||
let module = self.module_map.get(&id).cloned(); // clones a reference
|
let module = self.module_map.get(&id).cloned(); // clones a reference
|
||||||
@ -1895,13 +1902,14 @@ impl<'a> Resolver<'a> {
|
|||||||
self.ribs[TypeNS].push(Rib::new(ModuleRibKind(module)));
|
self.ribs[TypeNS].push(Rib::new(ModuleRibKind(module)));
|
||||||
|
|
||||||
self.finalize_current_module_macro_resolutions();
|
self.finalize_current_module_macro_resolutions();
|
||||||
f(self);
|
let ret = f(self);
|
||||||
|
|
||||||
self.current_module = orig_module;
|
self.current_module = orig_module;
|
||||||
self.ribs[ValueNS].pop();
|
self.ribs[ValueNS].pop();
|
||||||
self.ribs[TypeNS].pop();
|
self.ribs[TypeNS].pop();
|
||||||
|
ret
|
||||||
} else {
|
} else {
|
||||||
f(self);
|
f(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,6 +472,11 @@ impl Clean<Item> for doctree::Module {
|
|||||||
"".to_string()
|
"".to_string()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// maintain a stack of mod ids
|
||||||
|
// we could also pass this down through clean()
|
||||||
|
// but that might complicate things.
|
||||||
|
cx.mod_ids.borrow_mut().push(self.id);
|
||||||
|
|
||||||
let mut items: Vec<Item> = vec![];
|
let mut items: Vec<Item> = vec![];
|
||||||
items.extend(self.extern_crates.iter().map(|x| x.clean(cx)));
|
items.extend(self.extern_crates.iter().map(|x| x.clean(cx)));
|
||||||
items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
|
items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
|
||||||
@ -488,6 +493,8 @@ impl Clean<Item> for doctree::Module {
|
|||||||
items.extend(self.impls.iter().flat_map(|x| x.clean(cx)));
|
items.extend(self.impls.iter().flat_map(|x| x.clean(cx)));
|
||||||
items.extend(self.macros.iter().map(|x| x.clean(cx)));
|
items.extend(self.macros.iter().map(|x| x.clean(cx)));
|
||||||
|
|
||||||
|
cx.mod_ids.borrow_mut().pop();
|
||||||
|
|
||||||
// determine if we should display the inner contents or
|
// determine if we should display the inner contents or
|
||||||
// the outer `mod` item for the source code.
|
// the outer `mod` item for the source code.
|
||||||
let whence = {
|
let whence = {
|
||||||
@ -847,21 +854,20 @@ impl Clean<Attributes> for [ast::Attribute] {
|
|||||||
link.trim()
|
link.trim()
|
||||||
};
|
};
|
||||||
|
|
||||||
if !path_str.starts_with("::") {
|
let resolve = |is_val| {
|
||||||
// FIXME (misdreavus): can only support absolute paths because of limitations
|
// In case we're in a module, try to resolve the relative
|
||||||
// in Resolver. this may, with a lot of effort, figure out how to resolve paths
|
// path
|
||||||
// within scopes, but the one use of `resolve_hir_path` i found in the HIR
|
if let Some(id) = cx.mod_ids.borrow().last() {
|
||||||
// lowering code itself used an absolute path. we're brushing up against some
|
cx.resolver.borrow_mut()
|
||||||
// structural limitations in the compiler already, but this may be a design one
|
.with_scope(*id, |resolver| {
|
||||||
// as well >_>
|
resolver.resolve_str_path_error(DUMMY_SP, &path_str, is_val)
|
||||||
continue;
|
})
|
||||||
}
|
} else {
|
||||||
|
// FIXME(Manishearth) this branch doesn't seem to ever be hit, really
|
||||||
// This allocation could be avoided if resolve_str_path could take an iterator;
|
cx.resolver.borrow_mut()
|
||||||
// but it can't because that would break object safety. This can still be
|
.resolve_str_path_error(DUMMY_SP, &path_str, is_val)
|
||||||
// fixed.
|
}
|
||||||
let components = path_str.split("::").skip(1).collect::<Vec<_>>();
|
};
|
||||||
let resolve = |is_val| cx.resolver.borrow_mut().resolve_str_path_error(DUMMY_SP, None, &components, is_val);
|
|
||||||
|
|
||||||
if let Some(is_value) = is_value {
|
if let Some(is_value) = is_value {
|
||||||
if let Ok(path) = resolve(is_value) {
|
if let Ok(path) = resolve(is_value) {
|
||||||
|
@ -23,6 +23,7 @@ use rustc_resolve as resolve;
|
|||||||
use rustc_metadata::creader::CrateLoader;
|
use rustc_metadata::creader::CrateLoader;
|
||||||
use rustc_metadata::cstore::CStore;
|
use rustc_metadata::cstore::CStore;
|
||||||
|
|
||||||
|
use syntax::ast::NodeId;
|
||||||
use syntax::codemap;
|
use syntax::codemap;
|
||||||
use syntax::feature_gate::UnstableFeatures;
|
use syntax::feature_gate::UnstableFeatures;
|
||||||
use errors;
|
use errors;
|
||||||
@ -47,6 +48,8 @@ pub type ExternalPaths = FxHashMap<DefId, (Vec<String>, clean::TypeKind)>;
|
|||||||
pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> {
|
pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> {
|
||||||
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
pub resolver: &'a RefCell<resolve::Resolver<'rcx>>,
|
pub resolver: &'a RefCell<resolve::Resolver<'rcx>>,
|
||||||
|
/// The stack of module NodeIds up till this point
|
||||||
|
pub mod_ids: RefCell<Vec<NodeId>>,
|
||||||
pub populated_all_crate_impls: Cell<bool>,
|
pub populated_all_crate_impls: Cell<bool>,
|
||||||
// Note that external items for which `doc(hidden)` applies to are shown as
|
// Note that external items for which `doc(hidden)` applies to are shown as
|
||||||
// non-reachable while local items aren't. This is because we're reusing
|
// non-reachable while local items aren't. This is because we're reusing
|
||||||
@ -243,6 +246,7 @@ pub fn run_core(search_paths: SearchPaths,
|
|||||||
render_type,
|
render_type,
|
||||||
ty_substs: Default::default(),
|
ty_substs: Default::default(),
|
||||||
lt_substs: Default::default(),
|
lt_substs: Default::default(),
|
||||||
|
mod_ids: Default::default(),
|
||||||
};
|
};
|
||||||
debug!("crate: {:?}", tcx.hir.krate());
|
debug!("crate: {:?}", tcx.hir.krate());
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user