From 9295454ff58cd11b00499d25d1a17b34e8fd7182 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Sun, 18 May 2014 16:56:13 +0300 Subject: [PATCH] rustdoc: fix fallout from using ptr::P. --- src/librustdoc/clean/mod.rs | 30 ++++---- src/librustdoc/core.rs | 95 ++++++++++++-------------- src/librustdoc/doctree.rs | 11 ++- src/librustdoc/test.rs | 12 ++-- src/librustdoc/visit_ast.rs | 133 ++++++++++++++++-------------------- 5 files changed, 127 insertions(+), 154 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c1a91f26dbf..e6fcbbe9b6f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -20,6 +20,7 @@ use syntax::attr::{AttributeMethods, AttrMetaMethods}; use syntax::codemap::Pos; use syntax::parse::token::InternedString; use syntax::parse::token; +use syntax::ptr::P; use rustc::back::link; use rustc::driver::driver; @@ -34,7 +35,6 @@ use rustc::middle::stability; use std::rc::Rc; use std::u32; -use std::gc::{Gc, GC}; use core::DocContext; use doctree; @@ -67,7 +67,7 @@ impl, U> Clean> for VecPerParamSpace { } } -impl, U> Clean for Gc { +impl, U> Clean for P { fn clean(&self, cx: &DocContext) -> U { (**self).clean(cx) } @@ -408,7 +408,7 @@ impl Clean for ast::MetaItem { impl Clean for ast::Attribute { fn clean(&self, cx: &DocContext) -> Attribute { - self.desugar_doc().node.value.clean(cx) + self.with_desugared_doc(|a| a.node.value.clean(cx)) } } @@ -430,12 +430,12 @@ impl attr::AttrMetaMethods for Attribute { _ => None, } } - fn meta_item_list<'a>(&'a self) -> Option<&'a [Gc]> { None } + fn meta_item_list<'a>(&'a self) -> Option<&'a [P]> { None } } impl<'a> attr::AttrMetaMethods for &'a Attribute { fn name(&self) -> InternedString { (**self).name() } fn value_str(&self) -> Option { (**self).value_str() } - fn meta_item_list<'a>(&'a self) -> Option<&'a [Gc]> { None } + fn meta_item_list<'a>(&'a self) -> Option<&'a [P]> { None } } #[deriving(Clone, Encodable, Decodable, PartialEq)] @@ -758,10 +758,10 @@ impl Clean for ast::ExplicitSelf_ { match *self { ast::SelfStatic => SelfStatic, ast::SelfValue(_) => SelfValue, - ast::SelfRegion(lt, mt, _) => { + ast::SelfRegion(ref lt, ref mt, _) => { SelfBorrowed(lt.clean(cx), mt.clean(cx)) } - ast::SelfExplicit(typ, _) => SelfExplicit(typ.clean(cx)), + ast::SelfExplicit(ref typ, _) => SelfExplicit(typ.clean(cx)), } } } @@ -1189,11 +1189,11 @@ impl Clean for ast::Ty { TyRptr(ref l, ref m) => BorrowedRef {lifetime: l.clean(cx), mutability: m.mutbl.clean(cx), type_: box m.ty.clean(cx)}, - TyBox(ty) => Managed(box ty.clean(cx)), - TyUniq(ty) => Unique(box ty.clean(cx)), - TyVec(ty) => Vector(box ty.clean(cx)), - TyFixedLengthVec(ty, ref e) => FixedVector(box ty.clean(cx), - e.span.to_src(cx)), + TyBox(ref ty) => Managed(box ty.clean(cx)), + TyUniq(ref ty) => Unique(box ty.clean(cx)), + TyVec(ref ty) => Vector(box ty.clean(cx)), + TyFixedLengthVec(ref ty, ref e) => FixedVector(box ty.clean(cx), + e.span.to_src(cx)), TyTup(ref tys) => Tuple(tys.clean(cx)), TyPath(ref p, ref tpbs, id) => { resolve_type(cx, p.clean(cx), tpbs.clean(cx), id) @@ -1799,7 +1799,7 @@ impl Clean> for ast::ViewItem { remaining, b.clone()); let path = syntax::codemap::dummy_spanned(path); - ret.push(convert(&ast::ViewItemUse(box(GC) path))); + ret.push(convert(&ast::ViewItemUse(P(path)))); } } ast::ViewPathSimple(ident, _, id) => { @@ -1985,8 +1985,8 @@ fn name_from_pat(p: &ast::Pat) -> String { }, PatTup(ref elts) => format!("({})", elts.iter().map(|p| name_from_pat(&**p)) .collect::>().connect(", ")), - PatBox(p) => name_from_pat(&*p), - PatRegion(p) => name_from_pat(&*p), + PatBox(ref p) => name_from_pat(&**p), + PatRegion(ref p) => name_from_pat(&**p), PatLit(..) => { warn!("tried to get argument name from PatLit, \ which is silly in function arguments"); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index a8cd9f18d60..ddb4b994ca3 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -8,18 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc; -use rustc::{driver, middle}; +use rustc::driver::{config, driver, session}; use rustc::middle::{privacy, ty}; use rustc::lint; use rustc::back::link; -use syntax::ast; +use syntax::{ast, ast_map, codemap, diagnostic}; use syntax::parse::token; -use syntax; +use syntax::ptr::P; use std::cell::RefCell; -use std::gc::GC; use std::os; use std::collections::{HashMap, HashSet}; use arena::TypedArena; @@ -30,15 +28,15 @@ use clean::Clean; /// Are we generating documentation (`Typed`) or tests (`NotTyped`)? pub enum MaybeTyped<'tcx> { - Typed(middle::ty::ctxt<'tcx>), - NotTyped(driver::session::Session) + Typed(ty::ctxt<'tcx>), + NotTyped(session::Session) } pub type ExternalPaths = RefCell, clean::TypeKind)>>>; pub struct DocContext<'tcx> { - pub krate: ast::Crate, + pub krate: &'tcx ast::Crate, pub maybe_typed: MaybeTyped<'tcx>, pub src: Path, pub external_paths: ExternalPaths, @@ -49,7 +47,7 @@ pub struct DocContext<'tcx> { } impl<'tcx> DocContext<'tcx> { - pub fn sess<'a>(&'a self) -> &'a driver::session::Session { + pub fn sess<'a>(&'a self) -> &'a session::Session { match self.maybe_typed { Typed(ref tcx) => &tcx.sess, NotTyped(ref sess) => sess @@ -80,64 +78,60 @@ pub struct CrateAnalysis { pub type Externs = HashMap>; -/// Parses, resolves, and typechecks the given crate -fn get_ast_and_resolve<'tcx>(cpath: &Path, libs: Vec, cfgs: Vec, - externs: Externs, triple: Option, - type_arena: &'tcx TypedArena) - -> (DocContext<'tcx>, CrateAnalysis) { - use syntax::codemap::dummy_spanned; - use rustc::driver::driver::{FileInput, - phase_1_parse_input, - phase_2_configure_and_expand, - phase_3_run_analysis_passes}; - use rustc::driver::config::build_configuration; +pub fn run_core(libs: Vec, cfgs: Vec, externs: Externs, + cpath: &Path, triple: Option) + -> (clean::Crate, CrateAnalysis) { - let input = FileInput(cpath.clone()); + // Parse, resolve, and typecheck the given crate. + + let input = driver::FileInput(cpath.clone()); let warning_lint = lint::builtin::WARNINGS.name_lower(); - let sessopts = driver::config::Options { + let sessopts = config::Options { maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()), addl_lib_search_paths: RefCell::new(libs), - crate_types: vec!(driver::config::CrateTypeRlib), + crate_types: vec!(config::CrateTypeRlib), lint_opts: vec!((warning_lint, lint::Allow)), externs: externs, - target_triple: triple.unwrap_or(driver::driver::host_triple().to_string()), - ..rustc::driver::config::basic_options().clone() + target_triple: triple.unwrap_or(driver::host_triple().to_string()), + ..config::basic_options().clone() }; - let codemap = syntax::codemap::CodeMap::new(); - let diagnostic_handler = syntax::diagnostic::default_handler(syntax::diagnostic::Auto, None); + let codemap = codemap::CodeMap::new(); + let diagnostic_handler = diagnostic::default_handler(diagnostic::Auto, None); let span_diagnostic_handler = - syntax::diagnostic::mk_span_handler(diagnostic_handler, codemap); + diagnostic::mk_span_handler(diagnostic_handler, codemap); - let sess = driver::session::build_session_(sessopts, - Some(cpath.clone()), - span_diagnostic_handler); + let sess = session::build_session_(sessopts, + Some(cpath.clone()), + span_diagnostic_handler); - let mut cfg = build_configuration(&sess); + let mut cfg = config::build_configuration(&sess); for cfg_ in cfgs.move_iter() { let cfg_ = token::intern_and_get_ident(cfg_.as_slice()); - cfg.push(box(GC) dummy_spanned(ast::MetaWord(cfg_))); + cfg.push(P(codemap::dummy_spanned(ast::MetaWord(cfg_)))); } - let krate = phase_1_parse_input(&sess, cfg, &input); + let krate = driver::phase_1_parse_input(&sess, cfg, &input); let name = link::find_crate_name(Some(&sess), krate.attrs.as_slice(), &input); - let (krate, ast_map) - = phase_2_configure_and_expand(&sess, krate, name.as_slice(), None) - .expect("phase_2_configure_and_expand aborted in rustdoc!"); + let krate = driver::phase_2_configure_and_expand(&sess, krate, name.as_slice(), None) + .expect("phase_2_configure_and_expand aborted in rustdoc!"); - let driver::driver::CrateAnalysis { + let mut forest = ast_map::Forest::new(krate); + let ast_map = driver::assign_node_ids_and_map(&sess, &mut forest); + + let type_arena = TypedArena::new(); + let driver::CrateAnalysis { exported_items, public_items, ty_cx, .. - } = phase_3_run_analysis_passes(sess, &krate, ast_map, type_arena, name); + } = driver::phase_3_run_analysis_passes(sess, ast_map, &type_arena, name); - debug!("crate: {:?}", krate); - (DocContext { - krate: krate, + let ctxt = DocContext { + krate: ty_cx.map.krate(), maybe_typed: Typed(ty_cx), src: cpath.clone(), external_traits: RefCell::new(Some(HashMap::new())), @@ -145,26 +139,21 @@ fn get_ast_and_resolve<'tcx>(cpath: &Path, libs: Vec, cfgs: Vec, external_paths: RefCell::new(Some(HashMap::new())), inlined: RefCell::new(Some(HashSet::new())), populated_crate_impls: RefCell::new(HashSet::new()), - }, CrateAnalysis { + }; + debug!("crate: {:?}", ctxt.krate); + + let analysis = CrateAnalysis { exported_items: exported_items, public_items: public_items, external_paths: RefCell::new(None), external_traits: RefCell::new(None), external_typarams: RefCell::new(None), inlined: RefCell::new(None), - }) -} - -pub fn run_core(libs: Vec, cfgs: Vec, externs: Externs, - path: &Path, triple: Option) - -> (clean::Crate, CrateAnalysis) { - let type_arena = TypedArena::new(); - let (ctxt, analysis) = get_ast_and_resolve(path, libs, cfgs, externs, - triple, &type_arena); + }; let krate = { let mut v = RustdocVisitor::new(&ctxt, Some(&analysis)); - v.visit(&ctxt.krate); + v.visit(ctxt.krate); v.clean(&ctxt) }; diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 4d2cf852b8a..72964609049 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -16,8 +16,7 @@ use syntax::codemap::Span; use syntax::ast; use syntax::attr; use syntax::ast::{Ident, NodeId}; - -use std::gc::Gc; +use syntax::ptr::P; pub struct Module { pub name: Option, @@ -130,7 +129,7 @@ pub struct Function { } pub struct Typedef { - pub ty: ast::P, + pub ty: P, pub gen: ast::Generics, pub name: Ident, pub id: ast::NodeId, @@ -141,9 +140,9 @@ pub struct Typedef { } pub struct Static { - pub type_: ast::P, + pub type_: P, pub mutability: ast::Mutability, - pub expr: Gc, + pub expr: P, pub name: Ident, pub attrs: Vec, pub vis: ast::Visibility, @@ -167,7 +166,7 @@ pub struct Trait { pub struct Impl { pub generics: ast::Generics, pub trait_: Option, - pub for_: ast::P, + pub for_: P, pub items: Vec, pub attrs: Vec, pub whence: Span, diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 0eb0a9afd75..b7c602d9d73 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -11,7 +11,6 @@ use std::cell::RefCell; use std::char; use std::dynamic_lib::DynamicLibrary; -use std::gc::GC; use std::io::{Command, TempDir}; use std::io; use std::os; @@ -28,6 +27,7 @@ use syntax::ast; use syntax::codemap::{CodeMap, dummy_spanned}; use syntax::diagnostic; use syntax::parse::token; +use syntax::ptr::P; use core; use clean; @@ -67,15 +67,15 @@ pub fn run(input: &str, let mut cfg = config::build_configuration(&sess); cfg.extend(cfgs.move_iter().map(|cfg_| { let cfg_ = token::intern_and_get_ident(cfg_.as_slice()); - box(GC) dummy_spanned(ast::MetaWord(cfg_)) + P(dummy_spanned(ast::MetaWord(cfg_))) })); let krate = driver::phase_1_parse_input(&sess, cfg, &input); - let (krate, _) = driver::phase_2_configure_and_expand(&sess, krate, - "rustdoc-test", None) + let krate = driver::phase_2_configure_and_expand(&sess, krate, + "rustdoc-test", None) .expect("phase_2_configure_and_expand aborted in rustdoc!"); let ctx = core::DocContext { - krate: krate, + krate: &krate, maybe_typed: core::NotTyped(sess), src: input_path, external_paths: RefCell::new(Some(HashMap::new())), @@ -86,7 +86,7 @@ pub fn run(input: &str, }; let mut v = RustdocVisitor::new(&ctx, None); - v.visit(&ctx.krate); + v.visit(ctx.krate); let mut krate = v.clean(&ctx); match crate_name { Some(name) => krate.name = name, diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 79576cac20a..a9e0c9cb260 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -18,11 +18,10 @@ use syntax::ast_map; use syntax::attr; use syntax::attr::AttrMetaMethods; use syntax::codemap::Span; +use syntax::ptr::P; use rustc::middle::stability; -use std::gc::{Gc, GC}; - use core; use doctree::*; @@ -57,13 +56,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } pub fn visit(&mut self, krate: &ast::Crate) { - self.attrs = krate.attrs.iter().map(|x| (*x).clone()).collect(); + self.attrs = krate.attrs.clone(); self.module = self.visit_mod_contents(krate.span, - krate.attrs - .iter() - .map(|x| *x) - .collect(), + krate.attrs.clone(), ast::Public, ast::CRATE_NODE_ID, &krate.module, @@ -74,51 +70,50 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { self.module.is_crate = true; } - pub fn visit_struct_def(&mut self, item: &ast::Item, sd: Gc, + pub fn visit_struct_def(&mut self, item: &ast::Item, + name: ast::Ident, sd: &ast::StructDef, generics: &ast::Generics) -> Struct { debug!("Visiting struct"); let struct_type = struct_type_from_def(&*sd); Struct { id: item.id, struct_type: struct_type, - name: item.ident, + name: name, vis: item.vis, stab: self.stability(item.id), - attrs: item.attrs.iter().map(|x| *x).collect(), + attrs: item.attrs.clone(), generics: generics.clone(), - fields: sd.fields.iter().map(|x| (*x).clone()).collect(), + fields: sd.fields.clone(), whence: item.span } } - pub fn visit_enum_def(&mut self, it: &ast::Item, def: &ast::EnumDef, + pub fn visit_enum_def(&mut self, it: &ast::Item, + name: ast::Ident, def: &ast::EnumDef, params: &ast::Generics) -> Enum { debug!("Visiting enum"); - let mut vars: Vec = Vec::new(); - for x in def.variants.iter() { - vars.push(Variant { - name: x.node.name, - attrs: x.node.attrs.iter().map(|x| *x).collect(), - vis: x.node.vis, - stab: self.stability(x.node.id), - id: x.node.id, - kind: x.node.kind.clone(), - whence: x.span, - }); - } Enum { - name: it.ident, - variants: vars, + name: name, + variants: def.variants.iter().map(|v| Variant { + name: v.node.name, + attrs: v.node.attrs.clone(), + vis: v.node.vis, + stab: self.stability(v.node.id), + id: v.node.id, + kind: v.node.kind.clone(), + whence: v.span, + }).collect(), vis: it.vis, stab: self.stability(it.id), generics: params.clone(), - attrs: it.attrs.iter().map(|x| *x).collect(), + attrs: it.attrs.clone(), id: it.id, whence: it.span, } } - pub fn visit_fn(&mut self, item: &ast::Item, fd: &ast::FnDecl, + pub fn visit_fn(&mut self, item: &ast::Item, + name: ast::Ident, fd: &ast::FnDecl, fn_style: &ast::FnStyle, _abi: &abi::Abi, gen: &ast::Generics) -> Function { debug!("Visiting fn"); @@ -126,9 +121,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { id: item.id, vis: item.vis, stab: self.stability(item.id), - attrs: item.attrs.iter().map(|x| *x).collect(), + attrs: item.attrs.clone(), decl: fd.clone(), - name: item.ident, + name: name, whence: item.span, generics: gen.clone(), fn_style: *fn_style, @@ -150,7 +145,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { om.stab = self.stability(id); om.id = id; for i in m.items.iter() { - self.visit_item(&**i, &mut om); + self.visit_item(&**i, None, &mut om); } om } @@ -169,7 +164,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { }); let item = match item.node { ast::ViewItemUse(ref vpath) => { - match self.visit_view_path(*vpath, om, please_inline) { + match self.visit_view_path(&**vpath, om, please_inline) { None => return, Some(path) => { ast::ViewItem { @@ -184,9 +179,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { om.view_items.push(item); } - fn visit_view_path(&mut self, path: Gc, + fn visit_view_path(&mut self, path: &ast::ViewPath, om: &mut Module, - please_inline: bool) -> Option> { + please_inline: bool) -> Option> { match path.node { ast::ViewPathSimple(dst, _, id) => { if self.resolve_id(id, Some(dst), false, om, please_inline) { @@ -203,10 +198,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } if mine.len() == 0 { return None } - return Some(box(GC) ::syntax::codemap::Spanned { + return Some(P(::syntax::codemap::Spanned { node: ast::ViewPathList(p.clone(), mine, b.clone()), span: path.span, - }) + })) } // these are feature gated anyway @@ -216,7 +211,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } } } - return Some(path); + Some(P(path.clone())) } fn resolve_id(&mut self, id: ast::NodeId, renamed: Option, @@ -236,15 +231,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { match tcx.map.get(def.node) { ast_map::NodeItem(it) => { - let it = match renamed { - Some(ident) => { - box(GC) ast::Item { - ident: ident, - ..(*it).clone() - } - } - None => it, - }; if glob { match it.node { ast::ItemMod(ref m) => { @@ -252,13 +238,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { self.visit_view_item(vi, om); } for i in m.items.iter() { - self.visit_item(&**i, om); + self.visit_item(&**i, None, om); } } _ => { fail!("glob not mapped to a module"); } } } else { - self.visit_item(&*it, om); + self.visit_item(it, renamed, om); } true } @@ -266,47 +252,46 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } } - pub fn visit_item(&mut self, item: &ast::Item, om: &mut Module) { + pub fn visit_item(&mut self, item: &ast::Item, + renamed: Option, om: &mut Module) { debug!("Visiting item {:?}", item); + let name = renamed.unwrap_or(item.ident); match item.node { ast::ItemMod(ref m) => { om.mods.push(self.visit_mod_contents(item.span, - item.attrs - .iter() - .map(|x| *x) - .collect(), + item.attrs.clone(), item.vis, item.id, m, - Some(item.ident))); + Some(name))); }, ast::ItemEnum(ref ed, ref gen) => - om.enums.push(self.visit_enum_def(item, ed, gen)), - ast::ItemStruct(sd, ref gen) => - om.structs.push(self.visit_struct_def(item, sd, gen)), + om.enums.push(self.visit_enum_def(item, name, ed, gen)), + ast::ItemStruct(ref sd, ref gen) => + om.structs.push(self.visit_struct_def(item, name, &**sd, gen)), ast::ItemFn(ref fd, ref pur, ref abi, ref gen, _) => - om.fns.push(self.visit_fn(item, &**fd, pur, abi, gen)), - ast::ItemTy(ty, ref gen) => { + om.fns.push(self.visit_fn(item, name, &**fd, pur, abi, gen)), + ast::ItemTy(ref ty, ref gen) => { let t = Typedef { - ty: ty, + ty: ty.clone(), gen: gen.clone(), - name: item.ident, + name: name, id: item.id, - attrs: item.attrs.iter().map(|x| *x).collect(), + attrs: item.attrs.clone(), whence: item.span, vis: item.vis, stab: self.stability(item.id), }; om.typedefs.push(t); }, - ast::ItemStatic(ty, ref mut_, ref exp) => { + ast::ItemStatic(ref ty, ref mut_, ref exp) => { let s = Static { - type_: ty, + type_: ty.clone(), mutability: mut_.clone(), expr: exp.clone(), id: item.id, - name: item.ident, - attrs: item.attrs.iter().map(|x| *x).collect(), + name: name, + attrs: item.attrs.clone(), whence: item.span, vis: item.vis, stab: self.stability(item.id), @@ -315,25 +300,25 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { }, ast::ItemTrait(ref gen, _, ref b, ref items) => { let t = Trait { - name: item.ident, - items: items.iter().map(|x| (*x).clone()).collect(), + name: name, + items: items.clone(), generics: gen.clone(), bounds: b.iter().map(|x| (*x).clone()).collect(), id: item.id, - attrs: item.attrs.iter().map(|x| *x).collect(), + attrs: item.attrs.clone(), whence: item.span, vis: item.vis, stab: self.stability(item.id), }; om.traits.push(t); }, - ast::ItemImpl(ref gen, ref tr, ty, ref items) => { + ast::ItemImpl(ref gen, ref tr, ref ty, ref items) => { let i = Impl { generics: gen.clone(), trait_: tr.clone(), - for_: ty, - items: items.iter().map(|x| *x).collect(), - attrs: item.attrs.iter().map(|x| *x).collect(), + for_: ty.clone(), + items: items.clone(), + attrs: item.attrs.clone(), id: item.id, whence: item.span, vis: item.vis, @@ -354,7 +339,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { fn visit_macro(&self, item: &ast::Item) -> Macro { Macro { id: item.id, - attrs: item.attrs.iter().map(|x| *x).collect(), + attrs: item.attrs.clone(), name: item.ident, whence: item.span, stab: self.stability(item.id),