Refactor GenericArgs
to include const generics
Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
This commit is contained in:
parent
29ed491743
commit
cd9a2c0b54
@ -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)
|
||||
}
|
||||
|
@ -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<DefId>, has_self: bool,
|
||||
bindings: Vec<TypeBinding>, substs: SubstsRef<'_>) -> GenericArgs {
|
||||
let lifetimes = substs.regions().filter_map(|v| v.clean(cx)).collect();
|
||||
let types = substs.types().skip(has_self as usize).collect::<Vec<_>>();
|
||||
fn external_generic_args(
|
||||
cx: &DocContext<'_>,
|
||||
trait_did: Option<DefId>,
|
||||
has_self: bool,
|
||||
bindings: Vec<TypeBinding>,
|
||||
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<DefId>, 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<GenericParamDef> for ty::GenericParamDef {
|
||||
impl Clean<GenericParamDef> 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<Vec<Type>> {
|
||||
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<Lifetime>,
|
||||
types: Vec<Type>,
|
||||
args: Vec<GenericArg>,
|
||||
bindings: Vec<TypeBinding>,
|
||||
},
|
||||
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,
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user