From cd9a2c0b54ee50135fbeb4d83c00f713114f7f67 Mon Sep 17 00:00:00 2001 From: varkor Date: Wed, 13 Mar 2019 23:39:56 +0000 Subject: [PATCH] Refactor `GenericArgs` to include const generics Co-Authored-By: Gabriel Smith --- src/librustdoc/clean/auto_trait.rs | 8 +- src/librustdoc/clean/mod.rs | 116 ++++++++++++++--------------- src/librustdoc/html/format.rs | 19 ++--- 3 files changed, 70 insertions(+), 73 deletions(-) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 23b5794fb1e..adbe73b165e 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -444,7 +444,13 @@ fn make_final_bounds<'b, 'c, 'cx>( .expect("segments were empty"); 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, .. } => { (inputs, output) } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8581c40c843..50210bcb85d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -21,7 +21,7 @@ use rustc::hir::def::{self, Def, CtorKind}; use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; 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::fold::TypeFolder; use rustc::ty::layout::VariantIdx; @@ -1089,24 +1089,37 @@ fn clean(&self, cx: &DocContext<'_>) -> GenericBound { } } -fn external_generic_args(cx: &DocContext<'_>, trait_did: Option, has_self: bool, - bindings: Vec, substs: SubstsRef<'_>) -> GenericArgs { - let lifetimes = substs.regions().filter_map(|v| v.clean(cx)).collect(); - let types = substs.types().skip(has_self as usize).collect::>(); +fn external_generic_args( + cx: &DocContext<'_>, + trait_did: Option, + has_self: bool, + bindings: Vec, + substs: SubstsRef<'_>, +) -> GenericArgs { + let mut skip_self = has_self; + let mut first_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) => { + first_ty_sty = Some(&ty.sty); + Some(GenericArg::Type(ty.clean(cx))) + } + UnpackedKind::Const(ct) => Some(GenericArg::Const(ct.clean(cx))), + }).collect(); match trait_did { // 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() => { - assert_eq!(types.len(), 1); - let inputs = match types[0].sty { - ty::Tuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(), - _ => { - return GenericArgs::AngleBracketed { - lifetimes, - types: types.clean(cx), - bindings, - } - } + assert!(first_ty_sty.is_some()); + let inputs = match first_ty_sty { + Some(ty::Tuple(ref tys)) => tys.iter().map(|t| t.clean(cx)).collect(), + _ => return GenericArgs::AngleBracketed { args, bindings }, }; let output = None; // FIXME(#20299) return type comes from a projection now @@ -1114,17 +1127,10 @@ fn external_generic_args(cx: &DocContext<'_>, trait_did: Option, has_self // ty::Tuple(ref v) if v.is_empty() => None, // -> () // _ => Some(types[1].clean(cx)) // }; - GenericArgs::Parenthesized { - inputs, - output, - } + GenericArgs::Parenthesized { inputs, output } }, _ => { - GenericArgs::AngleBracketed { - lifetimes, - types: types.clean(cx), - bindings, - } + GenericArgs::AngleBracketed { args, bindings } } } } @@ -1462,7 +1468,7 @@ pub fn is_synthetic_type_param(&self) -> bool { } } -impl<'tcx> Clean for ty::GenericParamDef { +impl Clean for ty::GenericParamDef { fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef { let (name, kind) = match self.kind { ty::GenericParamDefKind::Lifetime => { @@ -1484,7 +1490,10 @@ fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef { }) } 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), + }) } }; @@ -1685,9 +1694,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Generics { .flat_map(|param| match param.kind { ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)), ty::GenericParamDefKind::Type { .. } => None, - ty::GenericParamDefKind::Const { .. } => { - unimplemented!() // FIXME(const_generics) - } + ty::GenericParamDefKind::Const { .. } => Some(param.clean(cx)), }).chain(simplify::ty_params(stripped_typarams).into_iter()) .collect(), where_predicates: simplify::where_clauses(cx, where_predicates), @@ -2365,12 +2372,15 @@ pub fn is_self_type(&self) -> bool { } } - pub fn generics(&self) -> Option<&[Type]> { + pub fn generics(&self) -> Option> { match *self { ResolvedPath { ref path, .. } => { path.segments.last().and_then(|seg| { - if let GenericArgs::AngleBracketed { ref types, .. } = seg.args { - Some(&**types) + if let GenericArgs::AngleBracketed { ref args, .. } = seg.args { + Some(args.iter().filter_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty.clone()), + _ => None, + }).collect()) } else { None } @@ -3267,8 +3277,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)] pub enum GenericArgs { AngleBracketed { - lifetimes: Vec, - types: Vec, + args: Vec, bindings: Vec, }, Parenthesized { @@ -3286,27 +3295,19 @@ fn clean(&self, cx: &DocContext<'_>) -> GenericArgs { output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None } } } else { - let (mut lifetimes, mut types) = (vec![], vec![]); - let mut elided_lifetimes = true; - for arg in &self.args { - 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) - } - } - } + let elide_lifetimes = self.args.iter().all(|arg| match arg { + hir::GenericArg::Lifetime(lt) => lt.is_elided(), + _ => true, + }); GenericArgs::AngleBracketed { - lifetimes: if elided_lifetimes { vec![] } else { lifetimes }, - types, + args: self.args.iter().filter_map(|arg| match arg { + 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), } } @@ -3358,9 +3359,8 @@ fn strip_path(path: &Path) -> Path { PathSegment { name: s.name.clone(), args: GenericArgs::AngleBracketed { - lifetimes: Vec::new(), - types: Vec::new(), - bindings: Vec::new(), + args: vec![], + bindings: vec![], } } }).collect(); @@ -3511,7 +3511,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item { } } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)] pub struct Constant { pub type_: Type, pub expr: String, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 2cba3c58889..116839edc2f 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -306,32 +306,23 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { impl fmt::Display for clean::GenericArgs { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { - clean::GenericArgs::AngleBracketed { - ref lifetimes, ref types, ref bindings - } => { - if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() { + clean::GenericArgs::AngleBracketed { ref args, ref bindings } => { + if !args.is_empty() || !bindings.is_empty() { if f.alternate() { f.write_str("<")?; } else { f.write_str("<")?; } let mut comma = false; - for lifetime in lifetimes { - if comma { - f.write_str(", ")?; - } - comma = true; - write!(f, "{}", *lifetime)?; - } - for ty in types { + for arg in args { if comma { f.write_str(", ")?; } comma = true; if f.alternate() { - write!(f, "{:#}", *ty)?; + write!(f, "{:#}", *arg)?; } else { - write!(f, "{}", *ty)?; + write!(f, "{}", *arg)?; } } for binding in bindings {