Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement RFC 1946 - intra-rustdoc links #47046

Merged
merged 46 commits into from
Jan 23, 2018
Merged
Show file tree
Hide file tree
Changes from 45 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
473fcfd
new function to pull the links from a chunk of markdown
QuietMisdreavus Dec 21, 2017
5db40f7
add RenderType to DocContext
QuietMisdreavus Dec 21, 2017
d9c1a17
give render_text a generic return type
QuietMisdreavus Dec 21, 2017
76f8316
add a rustc_resolve::Resolver to DocContext
QuietMisdreavus Dec 21, 2017
c3d0d5a
resolve paths when cleaning docs
QuietMisdreavus Dec 22, 2017
31ca232
abort documenting on resolution errors
QuietMisdreavus Dec 25, 2017
f7a8a97
DRY std_path
Manishearth Dec 25, 2017
d18b344
Move resolve arenas/crate loader outside of the core of phase_2_confi…
Manishearth Dec 25, 2017
fe0c100
Split out creation of the resolver arena in phase_2_configure_and_expand
Manishearth Dec 25, 2017
dae2e22
Make correct resolver available in rustdoc
Manishearth Dec 25, 2017
e8dd5df
Add LinkReplacer pass for pulldown
Manishearth Dec 28, 2017
611866f
cleanup
QuietMisdreavus Dec 28, 2017
9d5b1ae
add intra-links support to hoedown
QuietMisdreavus Dec 28, 2017
ef4587b
fix error_index_generator
QuietMisdreavus Dec 28, 2017
c4a4d3a
parse path ambiguity markers
QuietMisdreavus Dec 28, 2017
30fca09
add basic test for rustdoc intra links
QuietMisdreavus Dec 28, 2017
f951d74
Don't return early and discard the link in hoedown mode
Manishearth Dec 29, 2017
140e77f
Make resolve_hir_path and resolve_str_path fallible
Manishearth Dec 29, 2017
d6dcc47
Handle errors for intra doc link path lookup
Manishearth Dec 29, 2017
8166b59
Use correct item for links in modules
Manishearth Jan 1, 2018
4f10f67
Handle relative paths
Manishearth Jan 1, 2018
191e5b0
Exit early for non-linky things
Manishearth Jan 1, 2018
c0af897
Fix tidy
Manishearth Jan 3, 2018
383d169
Fix unit tests
Manishearth Jan 3, 2018
d6dd902
Register definitions
Manishearth Jan 6, 2018
7ac48d7
Resolve foreign macros
Manishearth Jan 6, 2018
00ce770
Store a list of local macros on the resolver; use for resolving intra…
Manishearth Jan 6, 2018
a3d71d7
add a macro to the intra-links test
QuietMisdreavus Jan 7, 2018
4a20fb4
use @ instead of space for link ambiguity markers
QuietMisdreavus Jan 8, 2018
eca3c55
add ambiguity markers to the intra-links test
QuietMisdreavus Jan 8, 2018
1a62b17
clean module docs while its module ID is still on the stack
QuietMisdreavus Jan 8, 2018
b31bb09
resolve module docs based on inner/outer attributes
QuietMisdreavus Jan 8, 2018
afe3e27
value-namespace items require a marker, so emit an error
QuietMisdreavus Jan 8, 2018
28805fd
Better error message
Manishearth Jan 9, 2018
d44910c
Use the registered def id (makes enum variants link to the enum page …
Manishearth Jan 9, 2018
6a1a449
Error only in the case of overlap
Manishearth Jan 10, 2018
869dd91
Allow function@, value@, macro@
Manishearth Jan 19, 2018
5762fa4
Allow macros to be resolved with ambiguous idents too
Manishearth Jan 19, 2018
6256bff
Move the figuring out of the 'kind' of def out into functions
Manishearth Jan 19, 2018
fbd2d16
Add ambiguity errors for macros
Manishearth Jan 19, 2018
7739bb2
Move resolve() into a function
Manishearth Jan 19, 2018
4ced272
Move macro_resolve() into a function
Manishearth Jan 19, 2018
dc54752
Review fixes
Manishearth Jan 22, 2018
fe93ada
Update to new commonmark arg
Manishearth Jan 22, 2018
cfc9f5a
Temporary fix missing escape_href in hoedown_link by copying pulldown…
Manishearth Jan 22, 2018
63811b6
don't process code blocks when scanning for links
QuietMisdreavus Jan 22, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 6 additions & 10 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,11 @@ pub trait Resolver {
/// We must keep the set of definitions up to date as we add nodes that weren't in the AST.
/// This should only return `None` during testing.
fn definitions(&mut self) -> &mut Definitions;

/// Given suffix ["b","c","d"], creates a HIR path for `[::crate_root]::b::c::d` and resolves
/// it based on `is_value`.
fn resolve_str_path(&mut self, span: Span, crate_root: Option<&str>,
components: &[&str], is_value: bool) -> hir::Path;
}

#[derive(Clone, Copy, Debug)]
Expand Down Expand Up @@ -3625,16 +3630,7 @@ impl<'a> LoweringContext<'a> {
/// `fld.cx.use_std`, and `::core::b::c::d` otherwise.
/// The path is also resolved according to `is_value`.
fn std_path(&mut self, span: Span, components: &[&str], is_value: bool) -> hir::Path {
let mut path = hir::Path {
span,
def: Def::Err,
segments: iter::once(keywords::CrateRoot.name()).chain({
self.crate_root.into_iter().chain(components.iter().cloned()).map(Symbol::intern)
}).map(hir::PathSegment::from_name).collect(),
};

self.resolver.resolve_hir_path(&mut path, is_value);
path
self.resolver.resolve_str_path(span, self.crate_root, components, is_value)
}

fn signal_block_expr(&mut self,
Expand Down
83 changes: 60 additions & 23 deletions src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use rustc::util::common::{ErrorReported, time};
use rustc_allocator as allocator;
use rustc_borrowck as borrowck;
use rustc_incremental;
use rustc_resolve::{MakeGlobMap, Resolver};
use rustc_resolve::{MakeGlobMap, Resolver, ResolverArenas};
use rustc_metadata::creader::CrateLoader;
use rustc_metadata::cstore::{self, CStore};
use rustc_trans_utils::trans_crate::TransCrate;
Expand Down Expand Up @@ -139,6 +139,7 @@ pub fn compile_input(trans: Box<TransCrate>,

let crate_name =
::rustc_trans_utils::link::find_crate_name(Some(sess), &krate.attrs, input);

let ExpansionResult { expanded_crate, defs, analysis, resolutions, mut hir_forest } = {
phase_2_configure_and_expand(
sess,
Expand Down Expand Up @@ -562,6 +563,12 @@ pub struct ExpansionResult {
pub hir_forest: hir_map::Forest,
}

pub struct InnerExpansionResult<'a> {
pub expanded_crate: ast::Crate,
pub resolver: Resolver<'a>,
pub hir_forest: hir_map::Forest,
}

/// Run the "early phases" of the compiler: initial `cfg` processing,
/// loading compiler plugins (including those from `addl_plugins`),
/// syntax expansion, secondary `cfg` expansion, synthesis of a test
Expand All @@ -578,6 +585,55 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
make_glob_map: MakeGlobMap,
after_expand: F)
-> Result<ExpansionResult, CompileIncomplete>
where F: FnOnce(&ast::Crate) -> CompileResult {
// Currently, we ignore the name resolution data structures for the purposes of dependency
// tracking. Instead we will run name resolution and include its output in the hash of each
// item, much like we do for macro expansion. In other words, the hash reflects not just
// its contents but the results of name resolution on those contents. Hopefully we'll push
// this back at some point.
let mut crate_loader = CrateLoader::new(sess, &cstore, &crate_name);
let resolver_arenas = Resolver::arenas();
let result = phase_2_configure_and_expand_inner(sess, cstore, krate, registry, crate_name,
addl_plugins, make_glob_map, &resolver_arenas,
&mut crate_loader, after_expand);
match result {
Ok(InnerExpansionResult {expanded_crate, resolver, hir_forest}) => {
Ok(ExpansionResult {
expanded_crate,
defs: resolver.definitions,
hir_forest,
resolutions: Resolutions {
freevars: resolver.freevars,
export_map: resolver.export_map,
trait_map: resolver.trait_map,
maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
maybe_unused_extern_crates: resolver.maybe_unused_extern_crates,
},

analysis: ty::CrateAnalysis {
access_levels: Rc::new(AccessLevels::default()),
name: crate_name.to_string(),
glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { None },
},
})
}
Err(x) => Err(x)
}
}

/// Same as phase_2_configure_and_expand, but doesn't let you keep the resolver
/// around
pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
cstore: &'a CStore,
krate: ast::Crate,
registry: Option<Registry>,
crate_name: &str,
addl_plugins: Option<Vec<String>>,
make_glob_map: MakeGlobMap,
resolver_arenas: &'a ResolverArenas<'a>,
crate_loader: &'a mut CrateLoader,
after_expand: F)
-> Result<InnerExpansionResult<'a>, CompileIncomplete>
where F: FnOnce(&ast::Crate) -> CompileResult,
{
let time_passes = sess.time_passes();
Expand Down Expand Up @@ -666,19 +722,12 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
return Err(CompileIncomplete::Stopped);
}

// Currently, we ignore the name resolution data structures for the purposes of dependency
// tracking. Instead we will run name resolution and include its output in the hash of each
// item, much like we do for macro expansion. In other words, the hash reflects not just
// its contents but the results of name resolution on those contents. Hopefully we'll push
// this back at some point.
let mut crate_loader = CrateLoader::new(sess, &cstore, crate_name);
let resolver_arenas = Resolver::arenas();
let mut resolver = Resolver::new(sess,
cstore,
&krate,
crate_name,
make_glob_map,
&mut crate_loader,
crate_loader,
&resolver_arenas);
resolver.whitelisted_legacy_custom_derives = whitelisted_legacy_custom_derives;
syntax_ext::register_builtins(&mut resolver, syntax_exts, sess.features.borrow().quote);
Expand Down Expand Up @@ -855,21 +904,9 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
syntax::ext::hygiene::clear_markings();
}

Ok(ExpansionResult {
Ok(InnerExpansionResult {
expanded_crate: krate,
defs: resolver.definitions,
analysis: ty::CrateAnalysis {
access_levels: Rc::new(AccessLevels::default()),
name: crate_name.to_string(),
glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { None },
},
resolutions: Resolutions {
freevars: resolver.freevars,
export_map: resolver.export_map,
trait_map: resolver.trait_map,
maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
maybe_unused_extern_crates: resolver.maybe_unused_extern_crates,
},
resolver,
hir_forest,
})
}
Expand Down
89 changes: 75 additions & 14 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ use std::cell::{Cell, RefCell};
use std::cmp;
use std::collections::BTreeSet;
use std::fmt;
use std::iter;
use std::mem::replace;
use std::rc::Rc;

Expand Down Expand Up @@ -1320,6 +1321,7 @@ pub struct Resolver<'a> {
crate_loader: &'a mut CrateLoader,
macro_names: FxHashSet<Ident>,
global_macros: FxHashMap<Name, &'a NameBinding<'a>>,
pub all_macros: FxHashMap<Name, Def>,
lexical_macro_resolutions: Vec<(Ident, &'a Cell<LegacyScope<'a>>)>,
macro_map: FxHashMap<DefId, Rc<SyntaxExtension>>,
macro_defs: FxHashMap<Mark, DefId>,
Expand Down Expand Up @@ -1407,6 +1409,71 @@ impl<'a, 'b: 'a> ty::DefIdTree for &'a Resolver<'b> {

impl<'a> hir::lowering::Resolver for Resolver<'a> {
fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool) {
self.resolve_hir_path_cb(path, is_value,
|resolver, span, error| resolve_error(resolver, span, error))
}

fn resolve_str_path(&mut self, span: Span, crate_root: Option<&str>,
components: &[&str], is_value: bool) -> hir::Path {
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> {
self.def_map.get(&id).cloned()
}

fn definitions(&mut self) -> &mut Definitions {
&mut self.definitions
}
}

impl<'a> Resolver<'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,
/// and also it's a private type. Fortunately rustdoc doesn't need to know the error,
/// just that an error occured.
pub fn resolve_str_path_error(&mut self, span: Span, path_str: &str, is_value: bool)
-> Result<hir::Path, ()> {
use std::iter;
let mut errored = false;

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 {
Err(())
} else {
Ok(path)
}
}

/// resolve_hir_path, but takes a callback in case there was an error
fn resolve_hir_path_cb<F>(&mut self, path: &mut hir::Path, is_value: bool, error_callback: F)
where F: for<'c, 'b> FnOnce(&'c mut Resolver, Span, ResolutionError<'b>)
{
let namespace = if is_value { ValueNS } else { TypeNS };
let hir::Path { ref segments, span, ref mut def } = *path;
let path: Vec<SpannedIdent> = segments.iter()
Expand All @@ -1418,24 +1485,16 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> {
*def = path_res.base_def(),
PathResult::NonModule(..) => match self.resolve_path(&path, None, true, span) {
PathResult::Failed(span, msg, _) => {
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
error_callback(self, span, ResolutionError::FailedToResolve(&msg));
}
_ => {}
},
PathResult::Indeterminate => unreachable!(),
PathResult::Failed(span, msg, _) => {
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
error_callback(self, span, ResolutionError::FailedToResolve(&msg));
}
}
}

fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution> {
self.def_map.get(&id).cloned()
}

fn definitions(&mut self) -> &mut Definitions {
&mut self.definitions
}
}

impl<'a> Resolver<'a> {
Expand Down Expand Up @@ -1538,6 +1597,7 @@ impl<'a> Resolver<'a> {
crate_loader,
macro_names: FxHashSet(),
global_macros: FxHashMap(),
all_macros: FxHashMap(),
lexical_macro_resolutions: Vec::new(),
macro_map: FxHashMap(),
macro_exports: Vec::new(),
Expand Down Expand Up @@ -1833,8 +1893,8 @@ impl<'a> Resolver<'a> {
// generate a fake "implementation scope" containing all the
// implementations thus found, for compatibility with old resolve pass.

fn with_scope<F>(&mut self, id: NodeId, f: F)
where F: FnOnce(&mut Resolver)
pub fn with_scope<F, T>(&mut self, id: NodeId, f: F) -> T
where F: FnOnce(&mut Resolver) -> T
{
let id = self.definitions.local_def_id(id);
let module = self.module_map.get(&id).cloned(); // clones a reference
Expand All @@ -1845,13 +1905,14 @@ impl<'a> Resolver<'a> {
self.ribs[TypeNS].push(Rib::new(ModuleRibKind(module)));

self.finalize_current_module_macro_resolutions();
f(self);
let ret = f(self);

self.current_module = orig_module;
self.ribs[ValueNS].pop();
self.ribs[TypeNS].pop();
ret
} else {
f(self);
f(self)
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/librustc_resolve/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ impl<'a> Resolver<'a> {
def
}

fn resolve_macro_to_def_inner(&mut self, scope: Mark, path: &ast::Path,
pub fn resolve_macro_to_def_inner(&mut self, scope: Mark, path: &ast::Path,
kind: MacroKind, force: bool)
-> Result<Def, Determinacy> {
let ast::Path { ref segments, span } = *path;
Expand Down Expand Up @@ -755,8 +755,9 @@ impl<'a> Resolver<'a> {
*legacy_scope = LegacyScope::Binding(self.arenas.alloc_legacy_binding(LegacyBinding {
parent: Cell::new(*legacy_scope), ident: ident, def_id: def_id, span: item.span,
}));
let def = Def::Macro(def_id, MacroKind::Bang);
self.all_macros.insert(ident.name, def);
if attr::contains_name(&item.attrs, "macro_export") {
let def = Def::Macro(def_id, MacroKind::Bang);
self.macro_exports.push(Export {
ident: ident.modern(),
def: def,
Expand Down
6 changes: 5 additions & 1 deletion src/librustdoc/clean/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,11 @@ pub fn record_extern_fqn(cx: &DocContext, did: DefId, kind: clean::TypeKind) {
None
}
});
let fqn = once(crate_name).chain(relative).collect();
let fqn = if let clean::TypeKind::Macro = kind {
vec![crate_name, relative.last().unwrap()]
} else {
once(crate_name).chain(relative).collect()
};
cx.renderinfo.borrow_mut().external_paths.insert(did, (fqn, kind));
}

Expand Down
Loading