Refactor GenericArgs to include const generics

Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
This commit is contained in:
varkor 2019-03-13 23:39:56 +00:00
parent 29ed491743
commit cd9a2c0b54
3 changed files with 70 additions and 73 deletions

View File

@ -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)
}

View File

@ -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,

View File

@ -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("&lt;")?;
}
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 {