Rollup merge of #59170 - varkor:const-generics-rustdoc, r=QuietMisdreavus,eddyb

Add const generics to rustdoc

Split out from #53645. This work is a collaborative effort with @yodaldevoid.

The `FIXME`s are waiting on a refactor to `LazyConst`. I'll address these in a follow up, but I thought it would be better to implement the rest now to avoid bitrot.

r? @QuietMisdreavus
This commit is contained in:
Mazdak Farrokhzad 2019-03-22 19:31:18 +01:00 committed by GitHub
commit 4c79967760
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 156 additions and 117 deletions

View File

@ -591,12 +591,12 @@ impl<'a> State<'a> {
self.s.word(";")?; self.s.word(";")?;
self.end()?; // end the outer cbox self.end()?; // end the outer cbox
} }
hir::ItemKind::Fn(ref decl, header, ref typarams, body) => { hir::ItemKind::Fn(ref decl, header, ref param_names, body) => {
self.head("")?; self.head("")?;
self.print_fn(decl, self.print_fn(decl,
header, header,
Some(item.ident.name), Some(item.ident.name),
typarams, param_names,
&item.vis, &item.vis,
&[], &[],
Some(body))?; Some(body))?;

View File

@ -435,7 +435,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
let new_ty = match &poly_trait.trait_ { let new_ty = match &poly_trait.trait_ {
&Type::ResolvedPath { &Type::ResolvedPath {
ref path, ref path,
ref typarams, ref param_names,
ref did, ref did,
ref is_generic, ref is_generic,
} => { } => {
@ -444,7 +444,13 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
.expect("segments were empty"); .expect("segments were empty");
let (old_input, old_output) = match last_segment.args { let (old_input, old_output) = match last_segment.args {
GenericArgs::AngleBracketed { types, .. } => (types, None), GenericArgs::AngleBracketed { args, .. } => {
let types = args.iter().filter_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty.clone()),
_ => None,
}).collect();
(types, None)
}
GenericArgs::Parenthesized { inputs, output, .. } => { GenericArgs::Parenthesized { inputs, output, .. } => {
(inputs, output) (inputs, output)
} }
@ -469,7 +475,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
Type::ResolvedPath { Type::ResolvedPath {
path: new_path, path: new_path,
typarams: typarams.clone(), param_names: param_names.clone(),
did: did.clone(), did: did.clone(),
is_generic: *is_generic, is_generic: *is_generic,
} }
@ -669,7 +675,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
match **trait_ { match **trait_ {
Type::ResolvedPath { Type::ResolvedPath {
path: ref trait_path, path: ref trait_path,
ref typarams, ref param_names,
ref did, ref did,
ref is_generic, ref is_generic,
} => { } => {
@ -724,7 +730,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
PolyTrait { PolyTrait {
trait_: Type::ResolvedPath { trait_: Type::ResolvedPath {
path: new_trait_path, path: new_trait_path,
typarams: typarams.clone(), param_names: param_names.clone(),
did: did.clone(), did: did.clone(),
is_generic: *is_generic, is_generic: *is_generic,
}, },

View File

@ -17,11 +17,11 @@ use rustc::middle::resolve_lifetime as rl;
use rustc::middle::lang_items; use rustc::middle::lang_items;
use rustc::middle::stability; use rustc::middle::stability;
use rustc::mir::interpret::{GlobalId, ConstValue}; use rustc::mir::interpret::{GlobalId, ConstValue};
use rustc::hir::{self, GenericArg, HirVec}; use rustc::hir::{self, HirVec};
use rustc::hir::def::{self, Def, CtorKind}; use rustc::hir::def::{self, Def, CtorKind};
use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc::hir::map::DisambiguatedDefPathData; use rustc::hir::map::DisambiguatedDefPathData;
use rustc::ty::subst::{Kind, InternalSubsts, SubstsRef}; use rustc::ty::subst::{Kind, InternalSubsts, SubstsRef, UnpackedKind};
use rustc::ty::{self, DefIdTree, TyCtxt, Region, RegionVid, Ty, AdtKind}; use rustc::ty::{self, DefIdTree, TyCtxt, Region, RegionVid, Ty, AdtKind};
use rustc::ty::fold::TypeFolder; use rustc::ty::fold::TypeFolder;
use rustc::ty::layout::VariantIdx; use rustc::ty::layout::VariantIdx;
@ -1057,7 +1057,7 @@ impl GenericBound {
GenericBound::TraitBound(PolyTrait { GenericBound::TraitBound(PolyTrait {
trait_: ResolvedPath { trait_: ResolvedPath {
path, path,
typarams: None, param_names: None,
did, did,
is_generic: false, is_generic: false,
}, },
@ -1101,24 +1101,37 @@ impl Clean<GenericBound> for hir::GenericBound {
} }
} }
fn external_generic_args(cx: &DocContext<'_>, trait_did: Option<DefId>, has_self: bool, fn external_generic_args(
bindings: Vec<TypeBinding>, substs: SubstsRef<'_>) -> GenericArgs { cx: &DocContext<'_>,
let lifetimes = substs.regions().filter_map(|v| v.clean(cx)).collect(); trait_did: Option<DefId>,
let types = substs.types().skip(has_self as usize).collect::<Vec<_>>(); has_self: bool,
bindings: Vec<TypeBinding>,
substs: SubstsRef<'_>,
) -> GenericArgs {
let mut skip_self = has_self;
let mut ty_sty = None;
let args: Vec<_> = substs.iter().filter_map(|kind| match kind.unpack() {
UnpackedKind::Lifetime(lt) => {
lt.clean(cx).and_then(|lt| Some(GenericArg::Lifetime(lt)))
}
UnpackedKind::Type(_) if skip_self => {
skip_self = false;
None
}
UnpackedKind::Type(ty) => {
ty_sty = Some(&ty.sty);
Some(GenericArg::Type(ty.clean(cx)))
}
UnpackedKind::Const(ct) => Some(GenericArg::Const(ct.clean(cx))),
}).collect();
match trait_did { match trait_did {
// Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
Some(did) if cx.tcx.lang_items().fn_trait_kind(did).is_some() => { Some(did) if cx.tcx.lang_items().fn_trait_kind(did).is_some() => {
assert_eq!(types.len(), 1); assert!(ty_sty.is_some());
let inputs = match types[0].sty { let inputs = match ty_sty {
ty::Tuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(), Some(ty::Tuple(ref tys)) => tys.iter().map(|t| t.clean(cx)).collect(),
_ => { _ => return GenericArgs::AngleBracketed { args, bindings },
return GenericArgs::AngleBracketed {
lifetimes,
types: types.clean(cx),
bindings,
}
}
}; };
let output = None; let output = None;
// FIXME(#20299) return type comes from a projection now // FIXME(#20299) return type comes from a projection now
@ -1126,17 +1139,10 @@ fn external_generic_args(cx: &DocContext<'_>, trait_did: Option<DefId>, has_self
// ty::Tuple(ref v) if v.is_empty() => None, // -> () // ty::Tuple(ref v) if v.is_empty() => None, // -> ()
// _ => Some(types[1].clean(cx)) // _ => Some(types[1].clean(cx))
// }; // };
GenericArgs::Parenthesized { GenericArgs::Parenthesized { inputs, output }
inputs,
output,
}
}, },
_ => { _ => {
GenericArgs::AngleBracketed { GenericArgs::AngleBracketed { args, bindings }
lifetimes,
types: types.clean(cx),
bindings,
}
} }
} }
} }
@ -1188,7 +1194,7 @@ impl<'a, 'tcx> Clean<GenericBound> for (&'a ty::TraitRef<'tcx>, Vec<TypeBinding>
PolyTrait { PolyTrait {
trait_: ResolvedPath { trait_: ResolvedPath {
path, path,
typarams: None, param_names: None,
did: trait_ref.def_id, did: trait_ref.def_id,
is_generic: false, is_generic: false,
}, },
@ -1474,14 +1480,14 @@ impl GenericParamDef {
} }
} }
impl<'tcx> Clean<GenericParamDef> for ty::GenericParamDef { impl Clean<GenericParamDef> for ty::GenericParamDef {
fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef { fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef {
let (name, kind) = match self.kind { let (name, kind) = match self.kind {
ty::GenericParamDefKind::Lifetime => { ty::GenericParamDefKind::Lifetime => {
(self.name.to_string(), GenericParamDefKind::Lifetime) (self.name.to_string(), GenericParamDefKind::Lifetime)
} }
ty::GenericParamDefKind::Type { has_default, .. } => { ty::GenericParamDefKind::Type { has_default, .. } => {
cx.renderinfo.borrow_mut().external_typarams cx.renderinfo.borrow_mut().external_param_names
.insert(self.def_id, self.name.clean(cx)); .insert(self.def_id, self.name.clean(cx));
let default = if has_default { let default = if has_default {
Some(cx.tcx.type_of(self.def_id).clean(cx)) Some(cx.tcx.type_of(self.def_id).clean(cx))
@ -1496,7 +1502,10 @@ impl<'tcx> Clean<GenericParamDef> for ty::GenericParamDef {
}) })
} }
ty::GenericParamDefKind::Const { .. } => { ty::GenericParamDefKind::Const { .. } => {
unimplemented!() // FIXME(const_generics) (self.name.clean(cx), GenericParamDefKind::Const {
did: self.def_id,
ty: cx.tcx.type_of(self.def_id).clean(cx),
})
} }
}; };
@ -1697,9 +1706,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
.flat_map(|param| match param.kind { .flat_map(|param| match param.kind {
ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)), ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)),
ty::GenericParamDefKind::Type { .. } => None, ty::GenericParamDefKind::Type { .. } => None,
ty::GenericParamDefKind::Const { .. } => { ty::GenericParamDefKind::Const { .. } => Some(param.clean(cx)),
unimplemented!() // FIXME(const_generics)
}
}).chain(simplify::ty_params(stripped_typarams).into_iter()) }).chain(simplify::ty_params(stripped_typarams).into_iter())
.collect(), .collect(),
where_predicates: simplify::where_clauses(cx, where_predicates), where_predicates: simplify::where_clauses(cx, where_predicates),
@ -2260,7 +2267,7 @@ pub enum Type {
/// Structs/enums/traits (most that'd be an `hir::TyKind::Path`). /// Structs/enums/traits (most that'd be an `hir::TyKind::Path`).
ResolvedPath { ResolvedPath {
path: Path, path: Path,
typarams: Option<Vec<GenericBound>>, param_names: Option<Vec<GenericBound>>,
did: DefId, did: DefId,
/// `true` if is a `T::Name` path for associated types. /// `true` if is a `T::Name` path for associated types.
is_generic: bool, is_generic: bool,
@ -2381,12 +2388,15 @@ impl Type {
} }
} }
pub fn generics(&self) -> Option<&[Type]> { pub fn generics(&self) -> Option<Vec<Type>> {
match *self { match *self {
ResolvedPath { ref path, .. } => { ResolvedPath { ref path, .. } => {
path.segments.last().and_then(|seg| { path.segments.last().and_then(|seg| {
if let GenericArgs::AngleBracketed { ref types, .. } = seg.args { if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
Some(&**types) Some(args.iter().filter_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty.clone()),
_ => None,
}).collect())
} else { } else {
None None
} }
@ -2722,7 +2732,7 @@ impl Clean<Type> for hir::Ty {
} }
TyKind::TraitObject(ref bounds, ref lifetime) => { TyKind::TraitObject(ref bounds, ref lifetime) => {
match bounds[0].clean(cx).trait_ { match bounds[0].clean(cx).trait_ {
ResolvedPath { path, typarams: None, did, is_generic } => { ResolvedPath { path, param_names: None, did, is_generic } => {
let mut bounds: Vec<self::GenericBound> = bounds[1..].iter().map(|bound| { let mut bounds: Vec<self::GenericBound> = bounds[1..].iter().map(|bound| {
self::GenericBound::TraitBound(bound.clean(cx), self::GenericBound::TraitBound(bound.clean(cx),
hir::TraitBoundModifier::None) hir::TraitBoundModifier::None)
@ -2730,7 +2740,7 @@ impl Clean<Type> for hir::Ty {
if !lifetime.is_elided() { if !lifetime.is_elided() {
bounds.push(self::GenericBound::Outlives(lifetime.clean(cx))); bounds.push(self::GenericBound::Outlives(lifetime.clean(cx)));
} }
ResolvedPath { path, typarams: Some(bounds), did, is_generic, } ResolvedPath { path, param_names: Some(bounds), did, is_generic, }
} }
_ => Infer // shouldn't happen _ => Infer // shouldn't happen
} }
@ -2797,7 +2807,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
None, false, vec![], substs); None, false, vec![], substs);
ResolvedPath { ResolvedPath {
path, path,
typarams: None, param_names: None,
did, did,
is_generic: false, is_generic: false,
} }
@ -2808,7 +2818,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
None, false, vec![], InternalSubsts::empty()); None, false, vec![], InternalSubsts::empty());
ResolvedPath { ResolvedPath {
path: path, path: path,
typarams: None, param_names: None,
did: did, did: did,
is_generic: false, is_generic: false,
} }
@ -2829,8 +2839,8 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
inline::record_extern_fqn(cx, did, TypeKind::Trait); inline::record_extern_fqn(cx, did, TypeKind::Trait);
let mut typarams = vec![]; let mut param_names = vec![];
reg.clean(cx).map(|b| typarams.push(GenericBound::Outlives(b))); reg.clean(cx).map(|b| param_names.push(GenericBound::Outlives(b)));
for did in dids { for did in dids {
let empty = cx.tcx.intern_substs(&[]); let empty = cx.tcx.intern_substs(&[]);
let path = external_path(cx, &cx.tcx.item_name(did).as_str(), let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
@ -2839,13 +2849,13 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
let bound = GenericBound::TraitBound(PolyTrait { let bound = GenericBound::TraitBound(PolyTrait {
trait_: ResolvedPath { trait_: ResolvedPath {
path, path,
typarams: None, param_names: None,
did, did,
is_generic: false, is_generic: false,
}, },
generic_params: Vec::new(), generic_params: Vec::new(),
}, hir::TraitBoundModifier::None); }, hir::TraitBoundModifier::None);
typarams.push(bound); param_names.push(bound);
} }
let mut bindings = vec![]; let mut bindings = vec![];
@ -2860,7 +2870,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
false, bindings, substs); false, bindings, substs);
ResolvedPath { ResolvedPath {
path, path,
typarams: Some(typarams), param_names: Some(param_names),
did, did,
is_generic: false, is_generic: false,
} }
@ -2937,6 +2947,15 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
} }
} }
impl<'tcx> Clean<Constant> for ty::Const<'tcx> {
fn clean(&self, cx: &DocContext<'_>) -> Constant {
Constant {
type_: self.ty.clean(cx),
expr: format!("{:?}", self.val), // FIXME(const_generics)
}
}
}
impl Clean<Item> for hir::StructField { impl Clean<Item> for hir::StructField {
fn clean(&self, cx: &DocContext<'_>) -> Item { fn clean(&self, cx: &DocContext<'_>) -> Item {
let local_did = cx.tcx.hir().local_def_id_from_hir_id(self.hir_id); let local_did = cx.tcx.hir().local_def_id_from_hir_id(self.hir_id);
@ -3244,11 +3263,27 @@ impl Clean<Path> for hir::Path {
} }
} }
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
pub enum GenericArg {
Lifetime(Lifetime),
Type(Type),
Const(Constant),
}
impl fmt::Display for GenericArg {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
GenericArg::Lifetime(lt) => lt.fmt(f),
GenericArg::Type(ty) => ty.fmt(f),
GenericArg::Const(ct) => ct.fmt(f),
}
}
}
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)] #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
pub enum GenericArgs { pub enum GenericArgs {
AngleBracketed { AngleBracketed {
lifetimes: Vec<Lifetime>, args: Vec<GenericArg>,
types: Vec<Type>,
bindings: Vec<TypeBinding>, bindings: Vec<TypeBinding>,
}, },
Parenthesized { Parenthesized {
@ -3266,27 +3301,19 @@ impl Clean<GenericArgs> for hir::GenericArgs {
output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None } output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None }
} }
} else { } else {
let (mut lifetimes, mut types) = (vec![], vec![]); let elide_lifetimes = self.args.iter().all(|arg| match arg {
let mut elided_lifetimes = true; hir::GenericArg::Lifetime(lt) => lt.is_elided(),
for arg in &self.args { _ => true,
match arg { });
GenericArg::Lifetime(lt) => {
if !lt.is_elided() {
elided_lifetimes = false;
}
lifetimes.push(lt.clean(cx));
}
GenericArg::Type(ty) => {
types.push(ty.clean(cx));
}
GenericArg::Const(..) => {
unimplemented!() // FIXME(const_generics)
}
}
}
GenericArgs::AngleBracketed { GenericArgs::AngleBracketed {
lifetimes: if elided_lifetimes { vec![] } else { lifetimes }, args: self.args.iter().filter_map(|arg| match arg {
types, hir::GenericArg::Lifetime(lt) if !elide_lifetimes => {
Some(GenericArg::Lifetime(lt.clean(cx)))
}
hir::GenericArg::Lifetime(_) => None,
hir::GenericArg::Type(ty) => Some(GenericArg::Type(ty.clean(cx))),
hir::GenericArg::Const(ct) => Some(GenericArg::Const(ct.clean(cx))),
}).collect(),
bindings: self.bindings.clean(cx), bindings: self.bindings.clean(cx),
} }
} }
@ -3310,8 +3337,8 @@ impl Clean<PathSegment> for hir::PathSegment {
fn strip_type(ty: Type) -> Type { fn strip_type(ty: Type) -> Type {
match ty { match ty {
Type::ResolvedPath { path, typarams, did, is_generic } => { Type::ResolvedPath { path, param_names, did, is_generic } => {
Type::ResolvedPath { path: strip_path(&path), typarams, did, is_generic } Type::ResolvedPath { path: strip_path(&path), param_names, did, is_generic }
} }
Type::Tuple(inner_tys) => { Type::Tuple(inner_tys) => {
Type::Tuple(inner_tys.iter().map(|t| strip_type(t.clone())).collect()) Type::Tuple(inner_tys.iter().map(|t| strip_type(t.clone())).collect())
@ -3338,9 +3365,8 @@ fn strip_path(path: &Path) -> Path {
PathSegment { PathSegment {
name: s.name.clone(), name: s.name.clone(),
args: GenericArgs::AngleBracketed { args: GenericArgs::AngleBracketed {
lifetimes: Vec::new(), args: vec![],
types: Vec::new(), bindings: vec![],
bindings: Vec::new(),
} }
} }
}).collect(); }).collect();
@ -3491,7 +3517,7 @@ impl Clean<Item> for doctree::Static {
} }
} }
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
pub struct Constant { pub struct Constant {
pub type_: Type, pub type_: Type,
pub expr: String, pub expr: String,
@ -3971,7 +3997,7 @@ fn resolve_type(cx: &DocContext<'_>,
_ => false, _ => false,
}; };
let did = register_def(&*cx, path.def); let did = register_def(&*cx, path.def);
ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic } ResolvedPath { path: path, param_names: None, did: did, is_generic: is_generic }
} }
pub fn register_def(cx: &DocContext<'_>, def: Def) -> DefId { pub fn register_def(cx: &DocContext<'_>, def: Def) -> DefId {
@ -4397,9 +4423,9 @@ impl From<GenericBound> for SimpleBound {
match bound.clone() { match bound.clone() {
GenericBound::Outlives(l) => SimpleBound::Outlives(l), GenericBound::Outlives(l) => SimpleBound::Outlives(l),
GenericBound::TraitBound(t, mod_) => match t.trait_ { GenericBound::TraitBound(t, mod_) => match t.trait_ {
Type::ResolvedPath { path, typarams, .. } => { Type::ResolvedPath { path, param_names, .. } => {
SimpleBound::TraitBound(path.segments, SimpleBound::TraitBound(path.segments,
typarams param_names
.map_or_else(|| Vec::new(), |v| v.iter() .map_or_else(|| Vec::new(), |v| v.iter()
.map(|p| SimpleBound::from(p.clone())) .map(|p| SimpleBound::from(p.clone()))
.collect()), .collect()),

View File

@ -236,8 +236,16 @@ impl<'tcx> DocContext<'tcx> {
ty::GenericParamDefKind::Type { .. } => { ty::GenericParamDefKind::Type { .. } => {
args.push(hir::GenericArg::Type(self.ty_param_to_ty(param.clone()))); args.push(hir::GenericArg::Type(self.ty_param_to_ty(param.clone())));
} }
ty::GenericParamDefKind::Const { .. } => { ty::GenericParamDefKind::Const => {
unimplemented!() // FIXME(const_generics) args.push(hir::GenericArg::Const(hir::ConstArg {
value: hir::AnonConst {
hir_id: hir::DUMMY_HIR_ID,
body: hir::BodyId {
hir_id: hir::DUMMY_HIR_ID,
}
},
span: DUMMY_SP,
}))
} }
} }
} }

View File

@ -260,6 +260,14 @@ impl fmt::Display for clean::Lifetime {
} }
} }
impl fmt::Display for clean::Constant {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.expr, f)?;
f.write_str(": ")?;
fmt::Display::fmt(&self.type_, f)
}
}
impl fmt::Display for clean::PolyTrait { impl fmt::Display for clean::PolyTrait {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if !self.generic_params.is_empty() { if !self.generic_params.is_empty() {
@ -301,32 +309,23 @@ impl fmt::Display for clean::GenericBound {
impl fmt::Display for clean::GenericArgs { impl fmt::Display for clean::GenericArgs {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self { match *self {
clean::GenericArgs::AngleBracketed { clean::GenericArgs::AngleBracketed { ref args, ref bindings } => {
ref lifetimes, ref types, ref bindings if !args.is_empty() || !bindings.is_empty() {
} => {
if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() {
if f.alternate() { if f.alternate() {
f.write_str("<")?; f.write_str("<")?;
} else { } else {
f.write_str("&lt;")?; f.write_str("&lt;")?;
} }
let mut comma = false; let mut comma = false;
for lifetime in lifetimes { for arg in args {
if comma {
f.write_str(", ")?;
}
comma = true;
write!(f, "{}", *lifetime)?;
}
for ty in types {
if comma { if comma {
f.write_str(", ")?; f.write_str(", ")?;
} }
comma = true; comma = true;
if f.alternate() { if f.alternate() {
write!(f, "{:#}", *ty)?; write!(f, "{:#}", *arg)?;
} else { } else {
write!(f, "{}", *ty)?; write!(f, "{}", *arg)?;
} }
} }
for binding in bindings { for binding in bindings {
@ -522,8 +521,8 @@ fn primitive_link(f: &mut fmt::Formatter<'_>,
/// Helper to render type parameters /// Helper to render type parameters
fn tybounds(w: &mut fmt::Formatter<'_>, fn tybounds(w: &mut fmt::Formatter<'_>,
typarams: &Option<Vec<clean::GenericBound>>) -> fmt::Result { param_names: &Option<Vec<clean::GenericBound>>) -> fmt::Result {
match *typarams { match *param_names {
Some(ref params) => { Some(ref params) => {
for param in params { for param in params {
write!(w, " + ")?; write!(w, " + ")?;
@ -560,13 +559,13 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) ->
clean::Generic(ref name) => { clean::Generic(ref name) => {
f.write_str(name) f.write_str(name)
} }
clean::ResolvedPath{ did, ref typarams, ref path, is_generic } => { clean::ResolvedPath{ did, ref param_names, ref path, is_generic } => {
if typarams.is_some() { if param_names.is_some() {
f.write_str("dyn ")?; f.write_str("dyn ")?;
} }
// Paths like T::Output and Self::Output should be rendered with all segments // Paths like T::Output and Self::Output should be rendered with all segments
resolved_path(f, did, path, is_generic, use_absolute)?; resolved_path(f, did, path, is_generic, use_absolute)?;
tybounds(f, typarams) tybounds(f, param_names)
} }
clean::Infer => write!(f, "_"), clean::Infer => write!(f, "_"),
clean::Primitive(prim) => primitive_link(f, prim, prim.as_str()), clean::Primitive(prim) => primitive_link(f, prim, prim.as_str()),
@ -664,7 +663,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) ->
} }
} }
} }
clean::ResolvedPath { typarams: Some(ref v), .. } if !v.is_empty() => { clean::ResolvedPath { param_names: Some(ref v), .. } if !v.is_empty() => {
write!(f, "{}{}{}(", amp, lt, m)?; write!(f, "{}{}{}(", amp, lt, m)?;
fmt_type(&ty, f, use_absolute)?; fmt_type(&ty, f, use_absolute)?;
write!(f, ")") write!(f, ")")
@ -718,7 +717,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) ->
// the ugliness comes from inlining across crates where // the ugliness comes from inlining across crates where
// everything comes in as a fully resolved QPath (hard to // everything comes in as a fully resolved QPath (hard to
// look at). // look at).
box clean::ResolvedPath { did, ref typarams, .. } => { box clean::ResolvedPath { did, ref param_names, .. } => {
match href(did) { match href(did) {
Some((ref url, _, ref path)) if !f.alternate() => { Some((ref url, _, ref path)) if !f.alternate() => {
write!(f, write!(f,
@ -732,8 +731,8 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) ->
_ => write!(f, "{}", name)?, _ => write!(f, "{}", name)?,
} }
// FIXME: `typarams` are not rendered, and this seems bad? // FIXME: `param_names` are not rendered, and this seems bad?
drop(typarams); drop(param_names);
Ok(()) Ok(())
} }
_ => { _ => {
@ -772,7 +771,7 @@ fn fmt_impl(i: &clean::Impl,
fmt::Display::fmt(ty, f)?; fmt::Display::fmt(ty, f)?;
} else { } else {
match *ty { match *ty {
clean::ResolvedPath { typarams: None, ref path, is_generic: false, .. } => { clean::ResolvedPath { param_names: None, ref path, is_generic: false, .. } => {
let last = path.segments.last().unwrap(); let last = path.segments.last().unwrap();
fmt::Display::fmt(&last.name, f)?; fmt::Display::fmt(&last.name, f)?;
fmt::Display::fmt(&last.args, f)?; fmt::Display::fmt(&last.args, f)?;

View File

@ -271,7 +271,7 @@ pub struct Cache {
/// Mapping of typaram ids to the name of the type parameter. This is used /// Mapping of typaram ids to the name of the type parameter. This is used
/// when pretty-printing a type (so pretty-printing doesn't have to /// when pretty-printing a type (so pretty-printing doesn't have to
/// painfully maintain a context like this) /// painfully maintain a context like this)
pub typarams: FxHashMap<DefId, String>, pub param_names: FxHashMap<DefId, String>,
/// Maps a type ID to all known implementations for that type. This is only /// Maps a type ID to all known implementations for that type. This is only
/// recognized for intra-crate `ResolvedPath` types, and is used to print /// recognized for intra-crate `ResolvedPath` types, and is used to print
@ -368,7 +368,7 @@ pub struct Cache {
pub struct RenderInfo { pub struct RenderInfo {
pub inlined: FxHashSet<DefId>, pub inlined: FxHashSet<DefId>,
pub external_paths: crate::core::ExternalPaths, pub external_paths: crate::core::ExternalPaths,
pub external_typarams: FxHashMap<DefId, String>, pub external_param_names: FxHashMap<DefId, String>,
pub exact_paths: FxHashMap<DefId, Vec<String>>, pub exact_paths: FxHashMap<DefId, Vec<String>>,
pub access_levels: AccessLevels<DefId>, pub access_levels: AccessLevels<DefId>,
pub deref_trait_did: Option<DefId>, pub deref_trait_did: Option<DefId>,
@ -601,7 +601,7 @@ pub fn run(mut krate: clean::Crate,
let RenderInfo { let RenderInfo {
inlined: _, inlined: _,
external_paths, external_paths,
external_typarams, external_param_names,
exact_paths, exact_paths,
access_levels, access_levels,
deref_trait_did, deref_trait_did,
@ -635,7 +635,7 @@ pub fn run(mut krate: clean::Crate,
deref_mut_trait_did, deref_mut_trait_did,
owned_box_did, owned_box_did,
masked_crates: mem::replace(&mut krate.masked_crates, Default::default()), masked_crates: mem::replace(&mut krate.masked_crates, Default::default()),
typarams: external_typarams, param_names: external_param_names,
aliases: Default::default(), aliases: Default::default(),
}; };
@ -1751,7 +1751,7 @@ impl<'a> Cache {
clean::GenericParamDefKind::Lifetime => {} clean::GenericParamDefKind::Lifetime => {}
clean::GenericParamDefKind::Type { did, .. } | clean::GenericParamDefKind::Type { did, .. } |
clean::GenericParamDefKind::Const { did, .. } => { clean::GenericParamDefKind::Const { did, .. } => {
self.typarams.insert(did, param.name.clone()); self.param_names.insert(did, param.name.clone());
} }
} }
} }

View File

@ -1263,13 +1263,13 @@ impl<'a> State<'a> {
self.s.word(";")?; self.s.word(";")?;
self.end()?; // end the outer cbox self.end()?; // end the outer cbox
} }
ast::ItemKind::Fn(ref decl, header, ref typarams, ref body) => { ast::ItemKind::Fn(ref decl, header, ref param_names, ref body) => {
self.head("")?; self.head("")?;
self.print_fn( self.print_fn(
decl, decl,
header, header,
Some(item.ident), Some(item.ident),
typarams, param_names,
&item.vis &item.vis
)?; )?;
self.s.word(" ")?; self.s.word(" ")?;