Skip to content

Commit

Permalink
Auto merge of #37954 - eddyb:rustdoc-2, r=alexcrichton
Browse files Browse the repository at this point in the history
rustdoc: link to cross-crate sources directly.

Fixes #37684 by implementing proper support for getting the `Span` of definitions across crates.
In rustdoc this is used to generate direct links to the original source instead of fragile redirects.

This functionality could be expanded further for making error reporting code more uniform and seamless across crates, although at the moment there is no actual source to print, only file/line/column information.

Closes #37870 which is also "fixes" #37684 by throwing away the builtin macro docs from libcore.
After this lands, #37727 could be reverted, although it doesn't matter much either way.
  • Loading branch information
bors committed Nov 30, 2016
2 parents 8e373b4 + 9001918 commit 3abaf43
Show file tree
Hide file tree
Showing 26 changed files with 296 additions and 325 deletions.
59 changes: 26 additions & 33 deletions src/librustc/hir/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -760,47 +760,40 @@ impl<'ast> Map<'ast> {
}
}

pub fn opt_span(&self, id: NodeId) -> Option<Span> {
let sp = match self.find(id) {
Some(NodeItem(item)) => item.span,
Some(NodeForeignItem(foreign_item)) => foreign_item.span,
Some(NodeTraitItem(trait_method)) => trait_method.span,
Some(NodeImplItem(ref impl_item)) => impl_item.span,
Some(NodeVariant(variant)) => variant.span,
Some(NodeField(field)) => field.span,
Some(NodeExpr(expr)) => expr.span,
Some(NodeStmt(stmt)) => stmt.span,
Some(NodeTy(ty)) => ty.span,
Some(NodeTraitRef(tr)) => tr.path.span,
Some(NodeLocal(pat)) => pat.span,
Some(NodePat(pat)) => pat.span,
Some(NodeBlock(block)) => block.span,
Some(NodeStructCtor(_)) => self.expect_item(self.get_parent(id)).span,
Some(NodeTyParam(ty_param)) => ty_param.span,
Some(NodeVisibility(&Visibility::Restricted { ref path, .. })) => path.span,
_ => return None,
};
Some(sp)
}

pub fn span(&self, id: NodeId) -> Span {
self.read(id); // reveals span from node
self.opt_span(id)
.unwrap_or_else(|| bug!("AstMap.span: could not find span for id {:?}", id))
match self.find_entry(id) {
Some(EntryItem(_, item)) => item.span,
Some(EntryForeignItem(_, foreign_item)) => foreign_item.span,
Some(EntryTraitItem(_, trait_method)) => trait_method.span,
Some(EntryImplItem(_, impl_item)) => impl_item.span,
Some(EntryVariant(_, variant)) => variant.span,
Some(EntryField(_, field)) => field.span,
Some(EntryExpr(_, expr)) => expr.span,
Some(EntryStmt(_, stmt)) => stmt.span,
Some(EntryTy(_, ty)) => ty.span,
Some(EntryTraitRef(_, tr)) => tr.path.span,
Some(EntryLocal(_, pat)) => pat.span,
Some(EntryPat(_, pat)) => pat.span,
Some(EntryBlock(_, block)) => block.span,
Some(EntryStructCtor(_, _)) => self.expect_item(self.get_parent(id)).span,
Some(EntryLifetime(_, lifetime)) => lifetime.span,
Some(EntryTyParam(_, ty_param)) => ty_param.span,
Some(EntryVisibility(_, &Visibility::Restricted { ref path, .. })) => path.span,
Some(EntryVisibility(_, v)) => bug!("unexpected Visibility {:?}", v),

Some(RootCrate) => self.krate().span,
Some(RootInlinedParent(parent)) => parent.body.span,
Some(NotPresent) | None => {
bug!("hir::map::Map::span: id not in map: {:?}", id)
}
}
}

pub fn span_if_local(&self, id: DefId) -> Option<Span> {
self.as_local_node_id(id).map(|id| self.span(id))
}

pub fn def_id_span(&self, def_id: DefId, fallback: Span) -> Span {
if let Some(node_id) = self.as_local_node_id(def_id) {
self.opt_span(node_id).unwrap_or(fallback)
} else {
fallback
}
}

pub fn node_to_string(&self, id: NodeId) -> String {
node_id_to_string(self, id, true)
}
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/middle/cstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ pub struct ExternCrate {
pub trait CrateStore<'tcx> {
// item info
fn describe_def(&self, def: DefId) -> Option<Def>;
fn def_span(&self, sess: &Session, def: DefId) -> Span;
fn stability(&self, def: DefId) -> Option<attr::Stability>;
fn deprecation(&self, def: DefId) -> Option<attr::Deprecation>;
fn visibility(&self, def: DefId) -> ty::Visibility;
Expand Down Expand Up @@ -404,6 +405,7 @@ pub struct DummyCrateStore;
impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
// item info
fn describe_def(&self, def: DefId) -> Option<Def> { bug!("describe_def") }
fn def_span(&self, sess: &Session, def: DefId) -> Span { bug!("def_span") }
fn stability(&self, def: DefId) -> Option<attr::Stability> { bug!("stability") }
fn deprecation(&self, def: DefId) -> Option<attr::Deprecation> { bug!("deprecation") }
fn visibility(&self, def: DefId) -> ty::Visibility { bug!("visibility") }
Expand Down
10 changes: 2 additions & 8 deletions src/librustc/ty/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,10 +283,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
expected.ty,
found.ty));

match
self.map.as_local_node_id(expected.def_id)
.and_then(|node_id| self.map.opt_span(node_id))
{
match self.map.span_if_local(expected.def_id) {
Some(span) => {
db.span_note(span, "a default was defined here...");
}
Expand All @@ -300,10 +297,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
expected.origin_span,
"...that was applied to an unconstrained type variable here");

match
self.map.as_local_node_id(found.def_id)
.and_then(|node_id| self.map.opt_span(node_id))
{
match self.map.span_if_local(found.def_id) {
Some(span) => {
db.span_note(span, "a second default was defined here...");
}
Expand Down
8 changes: 8 additions & 0 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2360,6 +2360,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
}

pub fn def_span(self, def_id: DefId) -> Span {
if let Some(id) = self.map.as_local_node_id(def_id) {
self.map.span(id)
} else {
self.sess.cstore.def_span(&self.sess, def_id)
}
}

pub fn item_name(self, id: DefId) -> ast::Name {
if let Some(id) = self.map.as_local_node_id(id) {
self.map.name(id)
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_borrowck/borrowck/fragments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,8 +496,8 @@ fn add_fragment_siblings_for_extension<'a, 'tcx>(this: &MoveData<'tcx>,
},

ref ty => {
let opt_span = origin_id.and_then(|id|tcx.map.opt_span(id));
span_bug!(opt_span.unwrap_or(DUMMY_SP),
let span = origin_id.map_or(DUMMY_SP, |id| tcx.map.span(id));
span_bug!(span,
"type {:?} ({:?}) is not fragmentable",
parent_ty, ty);
}
Expand Down
6 changes: 1 addition & 5 deletions src/librustc_driver/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1006,11 +1006,7 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
got {:?}",
node);

// Point to what was found, if there's an accessible span.
match tcx.map.opt_span(nodeid) {
Some(sp) => tcx.sess.span_fatal(sp, &message),
None => tcx.sess.fatal(&message),
}
tcx.sess.span_fatal(tcx.map.span(nodeid), &message)
}
}
}
Expand Down
20 changes: 14 additions & 6 deletions src/librustc_metadata/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use syntax::ast;
use syntax::attr;
use syntax::parse::new_parser_from_source_str;
use syntax::symbol::Symbol;
use syntax_pos::mk_sp;
use syntax_pos::{mk_sp, Span};
use rustc::hir::svh::Svh;
use rustc_back::target::Target;
use rustc::hir;
Expand All @@ -43,6 +43,11 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
self.get_crate_data(def.krate).get_def(def.index)
}

fn def_span(&self, sess: &Session, def: DefId) -> Span {
self.dep_graph.read(DepNode::MetaData(def));
self.get_crate_data(def.krate).get_span(def.index, sess)
}

fn stability(&self, def: DefId) -> Option<attr::Stability> {
self.dep_graph.read(DepNode::MetaData(def));
self.get_crate_data(def.krate).get_stability(def.index)
Expand Down Expand Up @@ -383,20 +388,23 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
let local_span = mk_sp(lo, parser.prev_span.hi);

// Mark the attrs as used
for attr in &def.attrs {
let attrs = data.get_item_attrs(id.index);
for attr in &attrs {
attr::mark_used(attr);
}

let name = data.def_key(id.index).disambiguated_data.data
.get_opt_name().expect("no name in load_macro");
sess.imported_macro_spans.borrow_mut()
.insert(local_span, (def.name.as_str().to_string(), def.span));
.insert(local_span, (name.to_string(), data.get_span(id.index, sess)));

LoadedMacro::MacroRules(ast::MacroDef {
ident: ast::Ident::with_empty_ctxt(def.name),
ident: ast::Ident::with_empty_ctxt(name),
id: ast::DUMMY_NODE_ID,
span: local_span,
imported_from: None, // FIXME
allow_internal_unstable: attr::contains_name(&def.attrs, "allow_internal_unstable"),
attrs: def.attrs,
allow_internal_unstable: attr::contains_name(&attrs, "allow_internal_unstable"),
attrs: attrs,
body: body,
})
}
Expand Down
39 changes: 28 additions & 11 deletions src/librustc_metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use rustc::middle::cstore::{InlinedItem, LinkagePreference};
use rustc::hir::def::{self, Def, CtorKind};
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc::middle::lang_items;
use rustc::session::Session;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::subst::Substs;

Expand All @@ -47,8 +48,9 @@ use syntax_pos::{self, Span, BytePos, Pos};

pub struct DecodeContext<'a, 'tcx: 'a> {
opaque: opaque::Decoder<'a>,
tcx: Option<TyCtxt<'a, 'tcx, 'tcx>>,
cdata: Option<&'a CrateMetadata>,
sess: Option<&'a Session>,
tcx: Option<TyCtxt<'a, 'tcx, 'tcx>>,
from_id_range: IdRange,
to_id_range: IdRange,

Expand All @@ -61,22 +63,21 @@ pub struct DecodeContext<'a, 'tcx: 'a> {
/// Abstract over the various ways one can create metadata decoders.
pub trait Metadata<'a, 'tcx>: Copy {
fn raw_bytes(self) -> &'a [u8];
fn cdata(self) -> Option<&'a CrateMetadata> {
None
}
fn tcx(self) -> Option<TyCtxt<'a, 'tcx, 'tcx>> {
None
}
fn cdata(self) -> Option<&'a CrateMetadata> { None }
fn sess(self) -> Option<&'a Session> { None }
fn tcx(self) -> Option<TyCtxt<'a, 'tcx, 'tcx>> { None }

fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> {
let id_range = IdRange {
min: NodeId::from_u32(u32::MIN),
max: NodeId::from_u32(u32::MAX),
};
let tcx = self.tcx();
DecodeContext {
opaque: opaque::Decoder::new(self.raw_bytes(), pos),
cdata: self.cdata(),
tcx: self.tcx(),
sess: self.sess().or(tcx.map(|tcx| tcx.sess)),
tcx: tcx,
from_id_range: id_range,
to_id_range: id_range,
last_filemap_index: 0,
Expand Down Expand Up @@ -104,6 +105,18 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadata {
}
}

impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, &'a Session) {
fn raw_bytes(self) -> &'a [u8] {
self.0.raw_bytes()
}
fn cdata(self) -> Option<&'a CrateMetadata> {
Some(self.0)
}
fn sess(self) -> Option<&'a Session> {
Some(&self.1)
}
}

impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'a, 'tcx, 'tcx>) {
fn raw_bytes(self) -> &'a [u8] {
self.0.raw_bytes()
Expand Down Expand Up @@ -280,8 +293,8 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
let lo = BytePos::decode(self)?;
let hi = BytePos::decode(self)?;

let tcx = if let Some(tcx) = self.tcx {
tcx
let sess = if let Some(sess) = self.sess {
sess
} else {
return Ok(syntax_pos::mk_sp(lo, hi));
};
Expand All @@ -299,7 +312,7 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
(lo, hi)
};

let imported_filemaps = self.cdata().imported_filemaps(&tcx.sess.codemap());
let imported_filemaps = self.cdata().imported_filemaps(&sess.codemap());
let filemap = {
// Optimize for the case that most spans within a translated item
// originate from the same filemap.
Expand Down Expand Up @@ -537,6 +550,10 @@ impl<'a, 'tcx> CrateMetadata {
}
}

pub fn get_span(&self, index: DefIndex, sess: &Session) -> Span {
self.entry(index).span.decode((self, sess))
}

pub fn get_trait_def(&self,
item_id: DefIndex,
tcx: TyCtxt<'a, 'tcx, 'tcx>)
Expand Down
Loading

0 comments on commit 3abaf43

Please sign in to comment.