Auto merge of #38449 - eddyb:lazy-10, r=nikomatsakis
[10/n] Split constants and functions' arguments into disjoint bodies. _This is part of a series ([prev](https://github.com/rust-lang/rust/pull/38053) | [next]()) of patches designed to rework rustc into an out-of-order on-demand pipeline model for both better feature support (e.g. [MIR-based](https://github.com/solson/miri) early constant evaluation) and incremental execution of compiler passes (e.g. type-checking), with beneficial consequences to IDE support as well. If any motivation is unclear, please ask for additional PR description clarifications or code comments._ <hr> Finishes the signature-body split started in #37918, namely: * `trait` items are separated just like `impl` items were, for uniformity, closing #37712 * `static`s, `const`s (including associated ones), `enum` discriminants and array lengths get bodies * even the count in "repeat expressions", i.e. `n` in `[x; n]`, which fixes #24414 * arguments' patterns are moved to the bodies, with the types staying in `FnDecl` * `&self` now desugars to `self: &Self` instead of `self: &_` (similarly for other `self` forms) * `astconv`'s and metadata's (for rustdoc) informative uses are explicitly ignored for the purposes of the dep graph. this could be fixed in the future by hashing the exact information being extracted about the arguments as opposed to generating a dependency on *the whole body*
This commit is contained in:
commit
4ecc85beb3
124 changed files with 2284 additions and 2761 deletions
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
//! Support for inlining external documentation into the current AST.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::io;
|
||||
use std::iter::once;
|
||||
|
||||
use syntax::ast;
|
||||
|
|
@ -17,12 +19,9 @@ use rustc::hir;
|
|||
|
||||
use rustc::hir::def::{Def, CtorKind};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::print as pprust;
|
||||
use rustc::ty;
|
||||
use rustc::util::nodemap::FxHashSet;
|
||||
|
||||
use rustc_const_eval::lookup_const_by_id;
|
||||
|
||||
use core::{DocContext, DocAccessLevels};
|
||||
use doctree;
|
||||
use clean::{self, GetDefId};
|
||||
|
|
@ -345,8 +344,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
|
|||
match item.kind {
|
||||
ty::AssociatedKind::Const => {
|
||||
let default = if item.defaultness.has_value() {
|
||||
Some(pprust::expr_to_string(
|
||||
lookup_const_by_id(tcx, item.def_id, None).unwrap().0))
|
||||
Some(print_inlined_const(cx, item.def_id))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
@ -476,17 +474,33 @@ fn build_module(cx: &DocContext, did: DefId) -> clean::Module {
|
|||
}
|
||||
}
|
||||
|
||||
fn build_const(cx: &DocContext, did: DefId) -> clean::Constant {
|
||||
let (expr, ty) = lookup_const_by_id(cx.tcx, did, None).unwrap_or_else(|| {
|
||||
panic!("expected lookup_const_by_id to succeed for {:?}", did);
|
||||
});
|
||||
debug!("converting constant expr {:?} to snippet", expr);
|
||||
let sn = pprust::expr_to_string(expr);
|
||||
debug!("got snippet {}", sn);
|
||||
struct InlinedConst {
|
||||
nested_bodies: BTreeMap<hir::BodyId, hir::Body>
|
||||
}
|
||||
|
||||
impl hir::print::PpAnn for InlinedConst {
|
||||
fn nested(&self, state: &mut hir::print::State, nested: hir::print::Nested)
|
||||
-> io::Result<()> {
|
||||
if let hir::print::Nested::Body(body) = nested {
|
||||
state.print_expr(&self.nested_bodies[&body].value)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn print_inlined_const(cx: &DocContext, did: DefId) -> String {
|
||||
let body = cx.tcx.sess.cstore.maybe_get_item_body(cx.tcx, did).unwrap();
|
||||
let inlined = InlinedConst {
|
||||
nested_bodies: cx.tcx.sess.cstore.item_body_nested_bodies(did)
|
||||
};
|
||||
hir::print::to_string(&inlined, |s| s.print_expr(&body.value))
|
||||
}
|
||||
|
||||
fn build_const(cx: &DocContext, did: DefId) -> clean::Constant {
|
||||
clean::Constant {
|
||||
type_: ty.map(|t| t.clean(cx)).unwrap_or_else(|| cx.tcx.item_type(did).clean(cx)),
|
||||
expr: sn
|
||||
type_: cx.tcx.item_type(did).clean(cx),
|
||||
expr: print_inlined_const(cx, did)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ use rustc::middle::resolve_lifetime::DefRegion::*;
|
|||
use rustc::middle::lang_items;
|
||||
use rustc::hir::def::{Def, CtorKind};
|
||||
use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||
use rustc::hir::print as pprust;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{self, AdtKind};
|
||||
use rustc::middle::stability;
|
||||
|
|
@ -1030,22 +1029,14 @@ pub struct Method {
|
|||
pub abi: Abi,
|
||||
}
|
||||
|
||||
impl Clean<Method> for hir::MethodSig {
|
||||
impl<'a> Clean<Method> for (&'a hir::MethodSig, hir::BodyId) {
|
||||
fn clean(&self, cx: &DocContext) -> Method {
|
||||
let decl = FnDecl {
|
||||
inputs: Arguments {
|
||||
values: self.decl.inputs.clean(cx),
|
||||
},
|
||||
output: self.decl.output.clean(cx),
|
||||
variadic: false,
|
||||
attrs: Attributes::default()
|
||||
};
|
||||
Method {
|
||||
generics: self.generics.clean(cx),
|
||||
unsafety: self.unsafety,
|
||||
constness: self.constness,
|
||||
decl: decl,
|
||||
abi: self.abi
|
||||
generics: self.0.generics.clean(cx),
|
||||
unsafety: self.0.unsafety,
|
||||
constness: self.0.constness,
|
||||
decl: (&*self.0.decl, self.1).clean(cx),
|
||||
abi: self.0.abi
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1058,25 +1049,6 @@ pub struct TyMethod {
|
|||
pub abi: Abi,
|
||||
}
|
||||
|
||||
impl Clean<TyMethod> for hir::MethodSig {
|
||||
fn clean(&self, cx: &DocContext) -> TyMethod {
|
||||
let decl = FnDecl {
|
||||
inputs: Arguments {
|
||||
values: self.decl.inputs.clean(cx),
|
||||
},
|
||||
output: self.decl.output.clean(cx),
|
||||
variadic: false,
|
||||
attrs: Attributes::default()
|
||||
};
|
||||
TyMethod {
|
||||
unsafety: self.unsafety.clone(),
|
||||
decl: decl,
|
||||
generics: self.generics.clean(cx),
|
||||
abi: self.abi
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub struct Function {
|
||||
pub decl: FnDecl,
|
||||
|
|
@ -1097,7 +1069,7 @@ impl Clean<Item> for doctree::Function {
|
|||
deprecation: self.depr.clean(cx),
|
||||
def_id: cx.tcx.map.local_def_id(self.id),
|
||||
inner: FunctionItem(Function {
|
||||
decl: self.decl.clean(cx),
|
||||
decl: (&self.decl, self.body).clean(cx),
|
||||
generics: self.generics.clean(cx),
|
||||
unsafety: self.unsafety,
|
||||
constness: self.constness,
|
||||
|
|
@ -1130,14 +1102,47 @@ pub struct Arguments {
|
|||
pub values: Vec<Argument>,
|
||||
}
|
||||
|
||||
impl Clean<FnDecl> for hir::FnDecl {
|
||||
impl<'a> Clean<Arguments> for (&'a [P<hir::Ty>], &'a [Spanned<ast::Name>]) {
|
||||
fn clean(&self, cx: &DocContext) -> Arguments {
|
||||
Arguments {
|
||||
values: self.0.iter().enumerate().map(|(i, ty)| {
|
||||
let mut name = self.1.get(i).map(|n| n.node.to_string())
|
||||
.unwrap_or(String::new());
|
||||
if name.is_empty() {
|
||||
name = "_".to_string();
|
||||
}
|
||||
Argument {
|
||||
name: name,
|
||||
type_: ty.clean(cx),
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Clean<Arguments> for (&'a [P<hir::Ty>], hir::BodyId) {
|
||||
fn clean(&self, cx: &DocContext) -> Arguments {
|
||||
let body = cx.tcx.map.body(self.1);
|
||||
|
||||
Arguments {
|
||||
values: self.0.iter().enumerate().map(|(i, ty)| {
|
||||
Argument {
|
||||
name: name_from_pat(&body.arguments[i].pat),
|
||||
type_: ty.clean(cx),
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, A: Copy> Clean<FnDecl> for (&'a hir::FnDecl, A)
|
||||
where (&'a [P<hir::Ty>], A): Clean<Arguments>
|
||||
{
|
||||
fn clean(&self, cx: &DocContext) -> FnDecl {
|
||||
FnDecl {
|
||||
inputs: Arguments {
|
||||
values: self.inputs.clean(cx),
|
||||
},
|
||||
output: self.output.clean(cx),
|
||||
variadic: self.variadic,
|
||||
inputs: (&self.0.inputs[..], self.1).clean(cx),
|
||||
output: self.0.output.clean(cx),
|
||||
variadic: self.0.variadic,
|
||||
attrs: Attributes::default()
|
||||
}
|
||||
}
|
||||
|
|
@ -1159,7 +1164,6 @@ impl<'a, 'tcx> Clean<FnDecl> for (DefId, &'a ty::PolyFnSig<'tcx>) {
|
|||
values: sig.skip_binder().inputs().iter().map(|t| {
|
||||
Argument {
|
||||
type_: t.clean(cx),
|
||||
id: ast::CRATE_NODE_ID,
|
||||
name: names.next().map_or("".to_string(), |name| name.to_string()),
|
||||
}
|
||||
}).collect(),
|
||||
|
|
@ -1172,7 +1176,6 @@ impl<'a, 'tcx> Clean<FnDecl> for (DefId, &'a ty::PolyFnSig<'tcx>) {
|
|||
pub struct Argument {
|
||||
pub type_: Type,
|
||||
pub name: String,
|
||||
pub id: ast::NodeId,
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
|
||||
|
|
@ -1184,26 +1187,17 @@ pub enum SelfTy {
|
|||
|
||||
impl Argument {
|
||||
pub fn to_self(&self) -> Option<SelfTy> {
|
||||
if self.name == "self" {
|
||||
match self.type_ {
|
||||
Infer => Some(SelfValue),
|
||||
BorrowedRef{ref lifetime, mutability, ref type_} if **type_ == Infer => {
|
||||
Some(SelfBorrowed(lifetime.clone(), mutability))
|
||||
}
|
||||
_ => Some(SelfExplicit(self.type_.clone()))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
if self.name != "self" {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clean<Argument> for hir::Arg {
|
||||
fn clean(&self, cx: &DocContext) -> Argument {
|
||||
Argument {
|
||||
name: name_from_pat(&*self.pat),
|
||||
type_: (self.ty.clean(cx)),
|
||||
id: self.id
|
||||
if self.type_.is_self_type() {
|
||||
return Some(SelfValue);
|
||||
}
|
||||
match self.type_ {
|
||||
BorrowedRef{ref lifetime, mutability, ref type_} if type_.is_self_type() => {
|
||||
Some(SelfBorrowed(lifetime.clone(), mutability))
|
||||
}
|
||||
_ => Some(SelfExplicit(self.type_.clone()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1269,17 +1263,22 @@ impl Clean<PolyTrait> for hir::PolyTraitRef {
|
|||
impl Clean<Item> for hir::TraitItem {
|
||||
fn clean(&self, cx: &DocContext) -> Item {
|
||||
let inner = match self.node {
|
||||
hir::ConstTraitItem(ref ty, ref default) => {
|
||||
hir::TraitItemKind::Const(ref ty, default) => {
|
||||
AssociatedConstItem(ty.clean(cx),
|
||||
default.as_ref().map(|e| pprust::expr_to_string(&e)))
|
||||
default.map(|e| print_const_expr(cx, e)))
|
||||
}
|
||||
hir::MethodTraitItem(ref sig, Some(_)) => {
|
||||
MethodItem(sig.clean(cx))
|
||||
hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
|
||||
MethodItem((sig, body).clean(cx))
|
||||
}
|
||||
hir::MethodTraitItem(ref sig, None) => {
|
||||
TyMethodItem(sig.clean(cx))
|
||||
hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref names)) => {
|
||||
TyMethodItem(TyMethod {
|
||||
unsafety: sig.unsafety.clone(),
|
||||
decl: (&*sig.decl, &names[..]).clean(cx),
|
||||
generics: sig.generics.clean(cx),
|
||||
abi: sig.abi
|
||||
})
|
||||
}
|
||||
hir::TypeTraitItem(ref bounds, ref default) => {
|
||||
hir::TraitItemKind::Type(ref bounds, ref default) => {
|
||||
AssociatedTypeItem(bounds.clean(cx), default.clean(cx))
|
||||
}
|
||||
};
|
||||
|
|
@ -1299,12 +1298,12 @@ impl Clean<Item> for hir::TraitItem {
|
|||
impl Clean<Item> for hir::ImplItem {
|
||||
fn clean(&self, cx: &DocContext) -> Item {
|
||||
let inner = match self.node {
|
||||
hir::ImplItemKind::Const(ref ty, ref expr) => {
|
||||
hir::ImplItemKind::Const(ref ty, expr) => {
|
||||
AssociatedConstItem(ty.clean(cx),
|
||||
Some(pprust::expr_to_string(expr)))
|
||||
Some(print_const_expr(cx, expr)))
|
||||
}
|
||||
hir::ImplItemKind::Method(ref sig, _) => {
|
||||
MethodItem(sig.clean(cx))
|
||||
hir::ImplItemKind::Method(ref sig, body) => {
|
||||
MethodItem((sig, body).clean(cx))
|
||||
}
|
||||
hir::ImplItemKind::Type(ref ty) => TypedefItem(Typedef {
|
||||
type_: ty.clean(cx),
|
||||
|
|
@ -1353,11 +1352,13 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem {
|
|||
};
|
||||
let self_arg_ty = *fty.sig.input(0).skip_binder();
|
||||
if self_arg_ty == self_ty {
|
||||
decl.inputs.values[0].type_ = Infer;
|
||||
decl.inputs.values[0].type_ = Generic(String::from("Self"));
|
||||
} else if let ty::TyRef(_, mt) = self_arg_ty.sty {
|
||||
if mt.ty == self_ty {
|
||||
match decl.inputs.values[0].type_ {
|
||||
BorrowedRef{ref mut type_, ..} => **type_ = Infer,
|
||||
BorrowedRef{ref mut type_, ..} => {
|
||||
**type_ = Generic(String::from("Self"))
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
@ -1568,6 +1569,13 @@ impl Type {
|
|||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_self_type(&self) -> bool {
|
||||
match *self {
|
||||
Generic(ref name) => name == "Self",
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetDefId for Type {
|
||||
|
|
@ -1677,11 +1685,12 @@ impl Clean<Type> for hir::Ty {
|
|||
BorrowedRef {lifetime: l.clean(cx), mutability: m.mutbl.clean(cx),
|
||||
type_: box m.ty.clean(cx)},
|
||||
TySlice(ref ty) => Vector(box ty.clean(cx)),
|
||||
TyArray(ref ty, ref e) => {
|
||||
TyArray(ref ty, e) => {
|
||||
use rustc_const_math::{ConstInt, ConstUsize};
|
||||
use rustc_const_eval::eval_const_expr;
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
|
||||
let e = &cx.tcx.map.body(e).value;
|
||||
let n = match eval_const_expr(cx.tcx, e) {
|
||||
ConstVal::Integral(ConstInt::Usize(u)) => match u {
|
||||
ConstUsize::Us16(u) => u.to_string(),
|
||||
|
|
@ -2332,7 +2341,7 @@ impl Clean<BareFunctionDecl> for hir::BareFnTy {
|
|||
type_params: Vec::new(),
|
||||
where_predicates: Vec::new()
|
||||
},
|
||||
decl: self.decl.clean(cx),
|
||||
decl: (&*self.decl, &[][..]).clean(cx),
|
||||
abi: self.abi,
|
||||
}
|
||||
}
|
||||
|
|
@ -2362,7 +2371,7 @@ impl Clean<Item> for doctree::Static {
|
|||
inner: StaticItem(Static {
|
||||
type_: self.type_.clean(cx),
|
||||
mutability: self.mutability.clean(cx),
|
||||
expr: pprust::expr_to_string(&self.expr),
|
||||
expr: print_const_expr(cx, self.expr),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
|
@ -2386,7 +2395,7 @@ impl Clean<Item> for doctree::Constant {
|
|||
deprecation: self.depr.clean(cx),
|
||||
inner: ConstantItem(Constant {
|
||||
type_: self.type_.clean(cx),
|
||||
expr: pprust::expr_to_string(&self.expr),
|
||||
expr: print_const_expr(cx, self.expr),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
|
@ -2630,9 +2639,9 @@ impl Clean<Vec<Item>> for hir::ForeignMod {
|
|||
impl Clean<Item> for hir::ForeignItem {
|
||||
fn clean(&self, cx: &DocContext) -> Item {
|
||||
let inner = match self.node {
|
||||
hir::ForeignItemFn(ref decl, ref generics) => {
|
||||
hir::ForeignItemFn(ref decl, ref names, ref generics) => {
|
||||
ForeignFunctionItem(Function {
|
||||
decl: decl.clean(cx),
|
||||
decl: (&**decl, &names[..]).clean(cx),
|
||||
generics: generics.clean(cx),
|
||||
unsafety: hir::Unsafety::Unsafe,
|
||||
abi: Abi::Rust,
|
||||
|
|
@ -2714,6 +2723,10 @@ fn name_from_pat(p: &hir::Pat) -> String {
|
|||
}
|
||||
}
|
||||
|
||||
fn print_const_expr(cx: &DocContext, body: hir::BodyId) -> String {
|
||||
cx.tcx.map.node_to_pretty_string(body.node_id)
|
||||
}
|
||||
|
||||
/// Given a type Path, resolve it to a Type using the TyCtxt
|
||||
fn resolve_type(cx: &DocContext,
|
||||
path: Path,
|
||||
|
|
|
|||
|
|
@ -156,6 +156,7 @@ pub struct Function {
|
|||
pub whence: Span,
|
||||
pub generics: hir::Generics,
|
||||
pub abi: abi::Abi,
|
||||
pub body: hir::BodyId,
|
||||
}
|
||||
|
||||
pub struct Typedef {
|
||||
|
|
@ -174,7 +175,7 @@ pub struct Typedef {
|
|||
pub struct Static {
|
||||
pub type_: P<hir::Ty>,
|
||||
pub mutability: hir::Mutability,
|
||||
pub expr: P<hir::Expr>,
|
||||
pub expr: hir::BodyId,
|
||||
pub name: Name,
|
||||
pub attrs: hir::HirVec<ast::Attribute>,
|
||||
pub vis: hir::Visibility,
|
||||
|
|
@ -186,7 +187,7 @@ pub struct Static {
|
|||
|
||||
pub struct Constant {
|
||||
pub type_: P<hir::Ty>,
|
||||
pub expr: P<hir::Expr>,
|
||||
pub expr: hir::BodyId,
|
||||
pub name: Name,
|
||||
pub attrs: hir::HirVec<ast::Attribute>,
|
||||
pub vis: hir::Visibility,
|
||||
|
|
|
|||
|
|
@ -502,7 +502,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> {
|
|||
|
||||
fn visit_item(&mut self, item: &'hir hir::Item) {
|
||||
let name = if let hir::ItemImpl(.., ref ty, _) = item.node {
|
||||
hir::print::ty_to_string(ty)
|
||||
self.map.node_to_pretty_string(ty.id)
|
||||
} else {
|
||||
item.name.to_string()
|
||||
};
|
||||
|
|
|
|||
|
|
@ -157,7 +157,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||
unsafety: &hir::Unsafety,
|
||||
constness: hir::Constness,
|
||||
abi: &abi::Abi,
|
||||
gen: &hir::Generics) -> Function {
|
||||
gen: &hir::Generics,
|
||||
body: hir::BodyId) -> Function {
|
||||
debug!("Visiting fn");
|
||||
Function {
|
||||
id: item.id,
|
||||
|
|
@ -172,6 +173,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||
unsafety: *unsafety,
|
||||
constness: constness,
|
||||
abi: *abi,
|
||||
body: body,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -410,9 +412,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||
om.structs.push(self.visit_variant_data(item, name, sd, gen)),
|
||||
hir::ItemUnion(ref sd, ref gen) =>
|
||||
om.unions.push(self.visit_union_data(item, name, sd, gen)),
|
||||
hir::ItemFn(ref fd, ref unsafety, constness, ref abi, ref gen, _) =>
|
||||
hir::ItemFn(ref fd, ref unsafety, constness, ref abi, ref gen, body) =>
|
||||
om.fns.push(self.visit_fn(item, name, &**fd, unsafety,
|
||||
constness, abi, gen)),
|
||||
constness, abi, gen, body)),
|
||||
hir::ItemTy(ref ty, ref gen) => {
|
||||
let t = Typedef {
|
||||
ty: ty.clone(),
|
||||
|
|
@ -456,11 +458,14 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||
};
|
||||
om.constants.push(s);
|
||||
},
|
||||
hir::ItemTrait(unsafety, ref gen, ref b, ref items) => {
|
||||
hir::ItemTrait(unsafety, ref gen, ref b, ref item_ids) => {
|
||||
let items = item_ids.iter()
|
||||
.map(|ti| self.cx.tcx.map.trait_item(ti.id).clone())
|
||||
.collect();
|
||||
let t = Trait {
|
||||
unsafety: unsafety,
|
||||
name: name,
|
||||
items: items.clone(),
|
||||
items: items,
|
||||
generics: gen.clone(),
|
||||
bounds: b.iter().cloned().collect(),
|
||||
id: item.id,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue