use crate::ast::*;
pub(crate) fn expand_splat_elems(ty: Ty) -> Ty {
let Ty { span, kind } = ty;
match kind {
TyKind::Tuple(t) => {
let (flat, decl) = t.0.into_iter().fold((vec![], None), |(mut flat, decl), e| {
if matches!(e.kind, TyKind::Splat(_)) {
let (mut es, d) = splat_expand(e);
flat.append(&mut es);
(flat, merge_decls(decl, d))
} else {
flat.push(expand_splat_elems(e));
(flat, decl)
}
});
let tuple = TyTuple(flat).to_ty().with_span(span);
match decl {
Some(d) => TyWithType(d, tuple.into()).to_ty().with_span(span),
None => tuple,
}
}
TyKind::Group(g) => TyGroup(Box::new(expand_splat_elems(*g.0))).to_ty().with_span(span),
TyKind::WithCode(wc) => {
let inner = wc.0.map(|e| expand_splat_elems(*e).into());
TyWithCode(inner, wc.1).to_ty().with_span(span)
}
TyKind::WithType(wt) => {
TyWithType(wt.0, Box::new(expand_splat_elems(*wt.1))).to_ty().with_span(span)
}
TyKind::WithTrait(wt) => {
let (tp, decl) = expand_tp(wt.0.1);
let trait_ty = TyTrait(wt.0.0, tp);
let inner = Box::new(expand_splat_elems(*wt.1));
match decl {
Some(d) => TyWithType(d, Box::new(TyWithTrait(trait_ty, inner).to_ty()))
.to_ty()
.with_span(span),
None => TyWithTrait(trait_ty, inner).to_ty().with_span(span),
}
}
TyKind::WithWhere(ww) => {
let inner = ww.0.map(|e| expand_splat_elems(*e).into());
TyWithWhere(inner, ww.1).to_ty().with_span(span)
}
TyKind::WithImpl(wi) => {
let inner = wi.0.map(|e| expand_splat_elems(*e).into());
TyWithImpl(inner, wi.1).to_ty().with_span(span)
}
TyKind::WithPrefix(wp) => {
let inner = wp.1.map(|e| expand_splat_elems(*e).into());
TyWithPrefix(wp.0, inner).to_ty().with_span(span)
}
TyKind::WithAttr(wa) => {
let inner = wa.1.map(|e| expand_splat_elems(*e).into());
TyWithAttr(wa.0, inner).to_ty().with_span(span)
}
TyKind::Generic(g) => {
let (tp, decl) = expand_tp(g.1);
let generic = TyGeneric(Box::new(expand_splat_elems(*g.0)), tp).to_ty().with_span(span);
match decl {
Some(d) => TyWithType(d, Box::new(generic)).to_ty().with_span(span),
None => generic,
}
}
TyKind::Trait(t) => {
let (tp, decl) = expand_tp(t.1);
let trait_ty = TyTrait(t.0, tp).to_ty().with_span(span);
match decl {
Some(d) => TyWithType(d, Box::new(trait_ty)).to_ty().with_span(span),
None => trait_ty,
}
}
other => Ty { span, kind: other },
}
}
fn expand_tp(tp: TyTypeParam) -> (TyTypeParam, Option<TyTypeParam>) {
let (flat, decl) = flat_splat_params(tp.params);
let params = flat
.into_iter()
.map(|(name, bound)| {
let name = expand_splat_elems(*name);
let bound = bound.map(expand_splat_elems);
(Box::new(name), bound)
})
.collect();
let bindings = tp
.bindings
.into_iter()
.map(|(n, v)| (Box::new(expand_splat_elems(*n)), Box::new(expand_splat_elems(*v))))
.collect();
(TyTypeParam { params, bindings }, decl)
}