Skip to content

Commit cd9a2c0

Browse files
varkoryodaldevoid
andcommitted
Refactor GenericArgs to include const generics
Co-Authored-By: Gabriel Smith <[email protected]>
1 parent 29ed491 commit cd9a2c0

File tree

3 files changed

+70
-73
lines changed

3 files changed

+70
-73
lines changed

src/librustdoc/clean/auto_trait.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,13 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
444444
.expect("segments were empty");
445445

446446
let (old_input, old_output) = match last_segment.args {
447-
GenericArgs::AngleBracketed { types, .. } => (types, None),
447+
GenericArgs::AngleBracketed { args, .. } => {
448+
let types = args.iter().filter_map(|arg| match arg {
449+
GenericArg::Type(ty) => Some(ty.clone()),
450+
_ => None,
451+
}).collect();
452+
(types, None)
453+
}
448454
GenericArgs::Parenthesized { inputs, output, .. } => {
449455
(inputs, output)
450456
}

src/librustdoc/clean/mod.rs

+58-58
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use rustc::hir::{self, GenericArg, HirVec};
2121
use rustc::hir::def::{self, Def, CtorKind};
2222
use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
2323
use rustc::hir::map::DisambiguatedDefPathData;
24-
use rustc::ty::subst::{Kind, InternalSubsts, SubstsRef};
24+
use rustc::ty::subst::{Kind, InternalSubsts, SubstsRef, UnpackedKind};
2525
use rustc::ty::{self, DefIdTree, TyCtxt, Region, RegionVid, Ty, AdtKind};
2626
use rustc::ty::fold::TypeFolder;
2727
use rustc::ty::layout::VariantIdx;
@@ -1089,42 +1089,48 @@ impl Clean<GenericBound> for hir::GenericBound {
10891089
}
10901090
}
10911091

1092-
fn external_generic_args(cx: &DocContext<'_>, trait_did: Option<DefId>, has_self: bool,
1093-
bindings: Vec<TypeBinding>, substs: SubstsRef<'_>) -> GenericArgs {
1094-
let lifetimes = substs.regions().filter_map(|v| v.clean(cx)).collect();
1095-
let types = substs.types().skip(has_self as usize).collect::<Vec<_>>();
1092+
fn external_generic_args(
1093+
cx: &DocContext<'_>,
1094+
trait_did: Option<DefId>,
1095+
has_self: bool,
1096+
bindings: Vec<TypeBinding>,
1097+
substs: SubstsRef<'_>,
1098+
) -> GenericArgs {
1099+
let mut skip_self = has_self;
1100+
let mut first_ty_sty = None;
1101+
let args: Vec<_> = substs.iter().filter_map(|kind| match kind.unpack() {
1102+
UnpackedKind::Lifetime(lt) => {
1103+
lt.clean(cx).and_then(|lt| Some(GenericArg::Lifetime(lt)))
1104+
}
1105+
UnpackedKind::Type(_) if skip_self => {
1106+
skip_self = false;
1107+
None
1108+
}
1109+
UnpackedKind::Type(ty) => {
1110+
first_ty_sty = Some(&ty.sty);
1111+
Some(GenericArg::Type(ty.clean(cx)))
1112+
}
1113+
UnpackedKind::Const(ct) => Some(GenericArg::Const(ct.clean(cx))),
1114+
}).collect();
10961115

10971116
match trait_did {
10981117
// Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
10991118
Some(did) if cx.tcx.lang_items().fn_trait_kind(did).is_some() => {
1100-
assert_eq!(types.len(), 1);
1101-
let inputs = match types[0].sty {
1102-
ty::Tuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(),
1103-
_ => {
1104-
return GenericArgs::AngleBracketed {
1105-
lifetimes,
1106-
types: types.clean(cx),
1107-
bindings,
1108-
}
1109-
}
1119+
assert!(first_ty_sty.is_some());
1120+
let inputs = match first_ty_sty {
1121+
Some(ty::Tuple(ref tys)) => tys.iter().map(|t| t.clean(cx)).collect(),
1122+
_ => return GenericArgs::AngleBracketed { args, bindings },
11101123
};
11111124
let output = None;
11121125
// FIXME(#20299) return type comes from a projection now
11131126
// match types[1].sty {
11141127
// ty::Tuple(ref v) if v.is_empty() => None, // -> ()
11151128
// _ => Some(types[1].clean(cx))
11161129
// };
1117-
GenericArgs::Parenthesized {
1118-
inputs,
1119-
output,
1120-
}
1130+
GenericArgs::Parenthesized { inputs, output }
11211131
},
11221132
_ => {
1123-
GenericArgs::AngleBracketed {
1124-
lifetimes,
1125-
types: types.clean(cx),
1126-
bindings,
1127-
}
1133+
GenericArgs::AngleBracketed { args, bindings }
11281134
}
11291135
}
11301136
}
@@ -1462,7 +1468,7 @@ impl GenericParamDef {
14621468
}
14631469
}
14641470

1465-
impl<'tcx> Clean<GenericParamDef> for ty::GenericParamDef {
1471+
impl Clean<GenericParamDef> for ty::GenericParamDef {
14661472
fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef {
14671473
let (name, kind) = match self.kind {
14681474
ty::GenericParamDefKind::Lifetime => {
@@ -1484,7 +1490,10 @@ impl<'tcx> Clean<GenericParamDef> for ty::GenericParamDef {
14841490
})
14851491
}
14861492
ty::GenericParamDefKind::Const { .. } => {
1487-
unimplemented!() // FIXME(const_generics)
1493+
(self.name.clean(cx), GenericParamDefKind::Const {
1494+
did: self.def_id,
1495+
ty: cx.tcx.type_of(self.def_id).clean(cx),
1496+
})
14881497
}
14891498
};
14901499

@@ -1685,9 +1694,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
16851694
.flat_map(|param| match param.kind {
16861695
ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)),
16871696
ty::GenericParamDefKind::Type { .. } => None,
1688-
ty::GenericParamDefKind::Const { .. } => {
1689-
unimplemented!() // FIXME(const_generics)
1690-
}
1697+
ty::GenericParamDefKind::Const { .. } => Some(param.clean(cx)),
16911698
}).chain(simplify::ty_params(stripped_typarams).into_iter())
16921699
.collect(),
16931700
where_predicates: simplify::where_clauses(cx, where_predicates),
@@ -2365,12 +2372,15 @@ impl Type {
23652372
}
23662373
}
23672374

2368-
pub fn generics(&self) -> Option<&[Type]> {
2375+
pub fn generics(&self) -> Option<Vec<Type>> {
23692376
match *self {
23702377
ResolvedPath { ref path, .. } => {
23712378
path.segments.last().and_then(|seg| {
2372-
if let GenericArgs::AngleBracketed { ref types, .. } = seg.args {
2373-
Some(&**types)
2379+
if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
2380+
Some(args.iter().filter_map(|arg| match arg {
2381+
GenericArg::Type(ty) => Some(ty.clone()),
2382+
_ => None,
2383+
}).collect())
23742384
} else {
23752385
None
23762386
}
@@ -3267,8 +3277,7 @@ impl fmt::Display for GenericArg {
32673277
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
32683278
pub enum GenericArgs {
32693279
AngleBracketed {
3270-
lifetimes: Vec<Lifetime>,
3271-
types: Vec<Type>,
3280+
args: Vec<GenericArg>,
32723281
bindings: Vec<TypeBinding>,
32733282
},
32743283
Parenthesized {
@@ -3286,27 +3295,19 @@ impl Clean<GenericArgs> for hir::GenericArgs {
32863295
output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None }
32873296
}
32883297
} else {
3289-
let (mut lifetimes, mut types) = (vec![], vec![]);
3290-
let mut elided_lifetimes = true;
3291-
for arg in &self.args {
3292-
match arg {
3293-
GenericArg::Lifetime(lt) => {
3294-
if !lt.is_elided() {
3295-
elided_lifetimes = false;
3296-
}
3297-
lifetimes.push(lt.clean(cx));
3298-
}
3299-
GenericArg::Type(ty) => {
3300-
types.push(ty.clean(cx));
3301-
}
3302-
GenericArg::Const(..) => {
3303-
unimplemented!() // FIXME(const_generics)
3304-
}
3305-
}
3306-
}
3298+
let elide_lifetimes = self.args.iter().all(|arg| match arg {
3299+
hir::GenericArg::Lifetime(lt) => lt.is_elided(),
3300+
_ => true,
3301+
});
33073302
GenericArgs::AngleBracketed {
3308-
lifetimes: if elided_lifetimes { vec![] } else { lifetimes },
3309-
types,
3303+
args: self.args.iter().filter_map(|arg| match arg {
3304+
hir::GenericArg::Lifetime(lt) if !elide_lifetimes => {
3305+
Some(GenericArg::Lifetime(lt.clean(cx)))
3306+
}
3307+
hir::GenericArg::Lifetime(_) => None,
3308+
hir::GenericArg::Type(ty) => Some(GenericArg::Type(ty.clean(cx))),
3309+
hir::GenericArg::Const(ct) => Some(GenericArg::Const(ct.clean(cx))),
3310+
}).collect(),
33103311
bindings: self.bindings.clean(cx),
33113312
}
33123313
}
@@ -3358,9 +3359,8 @@ fn strip_path(path: &Path) -> Path {
33583359
PathSegment {
33593360
name: s.name.clone(),
33603361
args: GenericArgs::AngleBracketed {
3361-
lifetimes: Vec::new(),
3362-
types: Vec::new(),
3363-
bindings: Vec::new(),
3362+
args: vec![],
3363+
bindings: vec![],
33643364
}
33653365
}
33663366
}).collect();
@@ -3511,7 +3511,7 @@ impl Clean<Item> for doctree::Static {
35113511
}
35123512
}
35133513

3514-
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
3514+
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
35153515
pub struct Constant {
35163516
pub type_: Type,
35173517
pub expr: String,

src/librustdoc/html/format.rs

+5-14
Original file line numberDiff line numberDiff line change
@@ -306,32 +306,23 @@ impl fmt::Display for clean::GenericBound {
306306
impl fmt::Display for clean::GenericArgs {
307307
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
308308
match *self {
309-
clean::GenericArgs::AngleBracketed {
310-
ref lifetimes, ref types, ref bindings
311-
} => {
312-
if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() {
309+
clean::GenericArgs::AngleBracketed { ref args, ref bindings } => {
310+
if !args.is_empty() || !bindings.is_empty() {
313311
if f.alternate() {
314312
f.write_str("<")?;
315313
} else {
316314
f.write_str("&lt;")?;
317315
}
318316
let mut comma = false;
319-
for lifetime in lifetimes {
320-
if comma {
321-
f.write_str(", ")?;
322-
}
323-
comma = true;
324-
write!(f, "{}", *lifetime)?;
325-
}
326-
for ty in types {
317+
for arg in args {
327318
if comma {
328319
f.write_str(", ")?;
329320
}
330321
comma = true;
331322
if f.alternate() {
332-
write!(f, "{:#}", *ty)?;
323+
write!(f, "{:#}", *arg)?;
333324
} else {
334-
write!(f, "{}", *ty)?;
325+
write!(f, "{}", *arg)?;
335326
}
336327
}
337328
for binding in bindings {

0 commit comments

Comments
 (0)