Skip to content

Commit 7effbeb

Browse files
committed
Handle relative paths
1 parent 08a89b3 commit 7effbeb

File tree

3 files changed

+61
-43
lines changed

3 files changed

+61
-43
lines changed

src/librustc_resolve/lib.rs

+36-28
Original file line numberDiff line numberDiff line change
@@ -1413,25 +1413,6 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> {
14131413

14141414
fn resolve_str_path(&mut self, span: Span, crate_root: Option<&str>,
14151415
components: &[&str], is_value: bool) -> hir::Path {
1416-
self.resolve_str_path_cb(span, crate_root, components, is_value,
1417-
|resolver, span, error| resolve_error(resolver, span, error))
1418-
}
1419-
1420-
fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution> {
1421-
self.def_map.get(&id).cloned()
1422-
}
1423-
1424-
fn definitions(&mut self) -> &mut Definitions {
1425-
&mut self.definitions
1426-
}
1427-
}
1428-
1429-
impl<'a> Resolver<'a> {
1430-
/// resolve_str_path, but takes a callback in case there was an error
1431-
fn resolve_str_path_cb<F>(&mut self, span: Span, crate_root: Option<&str>,
1432-
components: &[&str], is_value: bool, error_callback: F) -> hir::Path
1433-
where F: for<'b, 'c> FnOnce(&'c mut Resolver, Span, ResolutionError<'b>)
1434-
{
14351416
use std::iter;
14361417
let mut path = hir::Path {
14371418
span,
@@ -1441,19 +1422,45 @@ impl<'a> Resolver<'a> {
14411422
}).map(hir::PathSegment::from_name).collect(),
14421423
};
14431424

1444-
self.resolve_hir_path_cb(&mut path, is_value, error_callback);
1425+
self.resolve_hir_path(&mut path, is_value);
14451426
path
14461427
}
14471428

1429+
fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution> {
1430+
self.def_map.get(&id).cloned()
1431+
}
1432+
1433+
fn definitions(&mut self) -> &mut Definitions {
1434+
&mut self.definitions
1435+
}
1436+
}
1437+
1438+
impl<'a> Resolver<'a> {
14481439
/// Rustdoc uses this to resolve things in a recoverable way. ResolutionError<'a>
14491440
/// isn't something that can be returned because it can't be made to live that long,
14501441
/// and also it's a private type. Fortunately rustdoc doesn't need to know the error,
14511442
/// just that an error occured.
1452-
pub fn resolve_str_path_error(&mut self, span: Span, crate_root: Option<&str>,
1453-
components: &[&str], is_value: bool) -> Result<hir::Path, ()> {
1443+
pub fn resolve_str_path_error(&mut self, span: Span, path_str: &str, is_value: bool) -> Result<hir::Path, ()> {
1444+
use std::iter;
14541445
let mut errored = false;
1455-
let path = self.resolve_str_path_cb(span, crate_root, components, is_value,
1456-
|_, _, _| errored = true);
1446+
1447+
let mut path = if path_str.starts_with("::") {
1448+
hir::Path {
1449+
span,
1450+
def: Def::Err,
1451+
segments: iter::once(keywords::CrateRoot.name()).chain({
1452+
path_str.split("::").skip(1).map(Symbol::intern)
1453+
}).map(hir::PathSegment::from_name).collect(),
1454+
}
1455+
} else {
1456+
hir::Path {
1457+
span,
1458+
def: Def::Err,
1459+
segments: path_str.split("::").map(Symbol::intern)
1460+
.map(hir::PathSegment::from_name).collect(),
1461+
}
1462+
};
1463+
self.resolve_hir_path_cb(&mut path, is_value, |_, _, _| errored = true);
14571464
if errored || path.def == Def::Err {
14581465
Err(())
14591466
} else {
@@ -1874,8 +1881,8 @@ impl<'a> Resolver<'a> {
18741881
// generate a fake "implementation scope" containing all the
18751882
// implementations thus found, for compatibility with old resolve pass.
18761883

1877-
fn with_scope<F>(&mut self, id: NodeId, f: F)
1878-
where F: FnOnce(&mut Resolver)
1884+
pub fn with_scope<F, T>(&mut self, id: NodeId, f: F) -> T
1885+
where F: FnOnce(&mut Resolver) -> T
18791886
{
18801887
let id = self.definitions.local_def_id(id);
18811888
let module = self.module_map.get(&id).cloned(); // clones a reference
@@ -1886,13 +1893,14 @@ impl<'a> Resolver<'a> {
18861893
self.ribs[TypeNS].push(Rib::new(ModuleRibKind(module)));
18871894

18881895
self.finalize_current_module_macro_resolutions();
1889-
f(self);
1896+
let ret = f(self);
18901897

18911898
self.current_module = orig_module;
18921899
self.ribs[ValueNS].pop();
18931900
self.ribs[TypeNS].pop();
1901+
ret
18941902
} else {
1895-
f(self);
1903+
f(self)
18961904
}
18971905
}
18981906

src/librustdoc/clean/mod.rs

+21-15
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,11 @@ impl Clean<Item> for doctree::Module {
473473
"".to_string()
474474
};
475475

476+
// maintain a stack of mod ids
477+
// we could also pass this down through clean()
478+
// but that might complicate things.
479+
cx.mod_ids.borrow_mut().push(self.id);
480+
476481
let mut items: Vec<Item> = vec![];
477482
items.extend(self.extern_crates.iter().map(|x| x.clean(cx)));
478483
items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
@@ -490,6 +495,8 @@ impl Clean<Item> for doctree::Module {
490495
items.extend(self.macros.iter().map(|x| x.clean(cx)));
491496
items.extend(self.def_traits.iter().map(|x| x.clean(cx)));
492497

498+
cx.mod_ids.borrow_mut().pop();
499+
493500
// determine if we should display the inner contents or
494501
// the outer `mod` item for the source code.
495502
let whence = {
@@ -849,21 +856,20 @@ impl Clean<Attributes> for [ast::Attribute] {
849856
link.trim()
850857
};
851858

852-
if !path_str.starts_with("::") {
853-
// FIXME (misdreavus): can only support absolute paths because of limitations
854-
// in Resolver. this may, with a lot of effort, figure out how to resolve paths
855-
// within scopes, but the one use of `resolve_hir_path` i found in the HIR
856-
// lowering code itself used an absolute path. we're brushing up against some
857-
// structural limitations in the compiler already, but this may be a design one
858-
// as well >_>
859-
continue;
860-
}
861-
862-
// This allocation could be avoided if resolve_str_path could take an iterator;
863-
// but it can't because that would break object safety. This can still be
864-
// fixed.
865-
let components = path_str.split("::").skip(1).collect::<Vec<_>>();
866-
let resolve = |is_val| cx.resolver.borrow_mut().resolve_str_path_error(DUMMY_SP, None, &components, is_val);
859+
let resolve = |is_val| {
860+
// In case we're in a module, try to resolve the relative
861+
// path
862+
if let Some(id) = cx.mod_ids.borrow().last() {
863+
cx.resolver.borrow_mut()
864+
.with_scope(*id, |resolver| {
865+
resolver.resolve_str_path_error(DUMMY_SP, &path_str, is_val)
866+
})
867+
} else {
868+
// FIXME(Manishearth) this branch doesn't seem to ever be hit, really
869+
cx.resolver.borrow_mut()
870+
.resolve_str_path_error(DUMMY_SP, &path_str, is_val)
871+
}
872+
};
867873

868874
if let Some(is_value) = is_value {
869875
if let Ok(path) = resolve(is_value) {

src/librustdoc/core.rs

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use rustc_resolve as resolve;
2424
use rustc_metadata::creader::CrateLoader;
2525
use rustc_metadata::cstore::CStore;
2626

27+
use syntax::ast::NodeId;
2728
use syntax::codemap;
2829
use syntax::feature_gate::UnstableFeatures;
2930
use errors;
@@ -48,6 +49,8 @@ pub type ExternalPaths = FxHashMap<DefId, (Vec<String>, clean::TypeKind)>;
4849
pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> {
4950
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
5051
pub resolver: &'a RefCell<resolve::Resolver<'rcx>>,
52+
/// The stack of module NodeIds up till this point
53+
pub mod_ids: RefCell<Vec<NodeId>>,
5154
pub populated_all_crate_impls: Cell<bool>,
5255
// Note that external items for which `doc(hidden)` applies to are shown as
5356
// non-reachable while local items aren't. This is because we're reusing
@@ -243,6 +246,7 @@ pub fn run_core(search_paths: SearchPaths,
243246
render_type,
244247
ty_substs: Default::default(),
245248
lt_substs: Default::default(),
249+
mod_ids: Default::default(),
246250
};
247251
debug!("crate: {:?}", tcx.hir.krate());
248252

0 commit comments

Comments
 (0)