1
Fork 0

Refactor generic parameters in rustdoc/clean

This commit is contained in:
varkor 2018-05-27 16:56:01 +01:00
parent 80b381e041
commit f457b3d10a
21 changed files with 296 additions and 367 deletions

View file

@ -654,8 +654,8 @@ pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
}
pub fn walk_generic_args<'v, V: Visitor<'v>>(visitor: &mut V,
_path_span: Span,
generic_args: &'v GenericArgs) {
_path_span: Span,
generic_args: &'v GenericArgs) {
walk_list!(visitor, visit_generic_arg, &generic_args.args);
walk_list!(visitor, visit_assoc_type_binding, &generic_args.bindings);
}

View file

@ -382,17 +382,9 @@ impl<'a> LoweringContext<'a> {
let item_lifetimes = match self.lctx.items.get(&item.id).unwrap().node {
hir::Item_::ItemImpl(_, _, _, ref generics, ..)
| hir::Item_::ItemTrait(_, _, ref generics, ..) => {
generics.params
.iter()
.filter_map(|param| match param.kind {
hir::GenericParamKind::Lifetime { .. } => {
Some(param.clone())
}
_ => None,
})
.collect::<Vec<_>>()
generics.params.clone()
}
_ => Vec::new(),
_ => HirVec::new(),
};
self.lctx.with_parent_impl_lifetime_defs(&item_lifetimes, |this| {
@ -766,16 +758,15 @@ impl<'a> LoweringContext<'a> {
// This is used to track which lifetimes have already been defined, and
// which are new in-band lifetimes that need to have a definition created
// for them.
fn with_in_scope_lifetime_defs<'l, T, F>(
&mut self,
params: impl Iterator<Item = &'l GenericParamAST>,
f: F,
) -> T
fn with_in_scope_lifetime_defs<T, F>(&mut self, params: &Vec<GenericParamAST>, f: F) -> T
where
F: FnOnce(&mut LoweringContext) -> T,
{
let old_len = self.in_scope_lifetimes.len();
let lt_def_names = params.map(|param| param.ident.name);
let lt_def_names = params.iter().filter_map(|param| match param.kind {
GenericParamKindAST::Lifetime { .. } => Some(param.ident.name),
_ => None,
});
self.in_scope_lifetimes.extend(lt_def_names);
let res = f(self);
@ -789,12 +780,17 @@ impl<'a> LoweringContext<'a> {
// This should only be used with generics that have already had their
// in-band lifetimes added. In practice, this means that this function is
// only used when lowering a child item of a trait or impl.
fn with_parent_impl_lifetime_defs<T, F>(&mut self, params: &[hir::GenericParam], f: F) -> T
where
fn with_parent_impl_lifetime_defs<T, F>(&mut self,
params: &HirVec<hir::GenericParam>,
f: F
) -> T where
F: FnOnce(&mut LoweringContext) -> T,
{
let old_len = self.in_scope_lifetimes.len();
let lt_def_names = params.iter().map(|param| param.name());
let lt_def_names = params.iter().filter_map(|param| match param.kind {
hir::GenericParamKind::Lifetime { .. } => Some(param.name()),
_ => None,
});
self.in_scope_lifetimes.extend(lt_def_names);
let res = f(self);
@ -820,10 +816,7 @@ impl<'a> LoweringContext<'a> {
F: FnOnce(&mut LoweringContext) -> T,
{
let (in_band_defs, (mut lowered_generics, res)) = self.with_in_scope_lifetime_defs(
generics.params.iter().filter_map(|param| match param.kind {
GenericParamKindAST::Lifetime { .. } => Some(param),
_ => None,
}),
&generics.params,
|this| {
let itctx = ImplTraitContext::Universal(parent_id);
this.collect_in_band_defs(parent_id, anonymous_lifetime_mode, |this| {
@ -1051,16 +1044,12 @@ impl<'a> LoweringContext<'a> {
}
fn lower_generic_arg(&mut self,
p: &ast::GenericArgAST,
arg: &ast::GenericArgAST,
itctx: ImplTraitContext)
-> hir::GenericArg {
match p {
ast::GenericArgAST::Lifetime(lt) => {
GenericArg::Lifetime(self.lower_lifetime(&lt))
}
ast::GenericArgAST::Type(ty) => {
GenericArg::Type(self.lower_ty(&ty, itctx))
}
match arg {
ast::GenericArgAST::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(&lt)),
ast::GenericArgAST::Type(ty) => GenericArg::Type(self.lower_ty(&ty, itctx)),
}
}
@ -1079,10 +1068,7 @@ impl<'a> LoweringContext<'a> {
hir::TyRptr(lifetime, self.lower_mt(mt, itctx))
}
TyKind::BareFn(ref f) => self.with_in_scope_lifetime_defs(
f.generic_params.iter().filter_map(|param| match param.kind {
GenericParamKindAST::Lifetime { .. } => Some(param),
_ => None,
}),
&f.generic_params,
|this| {
this.with_anonymous_lifetime_mode(
AnonymousLifetimeMode::PassThrough,
@ -1946,6 +1932,15 @@ impl<'a> LoweringContext<'a> {
}
}
fn lower_generic_params(
&mut self,
params: &Vec<GenericParamAST>,
add_bounds: &NodeMap<Vec<TyParamBound>>,
itctx: ImplTraitContext,
) -> hir::HirVec<hir::GenericParam> {
params.iter().map(|param| self.lower_generic_param(param, add_bounds, itctx)).collect()
}
fn lower_generic_param(&mut self,
param: &GenericParamAST,
add_bounds: &NodeMap<Vec<TyParamBound>>,
@ -1986,10 +1981,9 @@ impl<'a> LoweringContext<'a> {
let mut bounds = self.lower_bounds(bounds, itctx);
let add_bounds = add_bounds.get(&param.id).map_or(&[][..], |x| &x);
if !add_bounds.is_empty() {
bounds = bounds
.into_iter()
.chain(self.lower_bounds(add_bounds, itctx).into_iter())
.collect();
bounds = bounds.into_iter()
.chain(self.lower_bounds(add_bounds, itctx).into_iter())
.collect();
}
hir::GenericParam {
@ -2005,7 +1999,7 @@ impl<'a> LoweringContext<'a> {
synthetic: param.attrs.iter()
.filter(|attr| attr.check_name("rustc_synthetic"))
.map(|_| hir::SyntheticTyParamKind::ImplTrait)
.nth(0),
.next(),
attrs: self.lower_attrs(&param.attrs),
}
}
@ -2013,15 +2007,6 @@ impl<'a> LoweringContext<'a> {
}
}
fn lower_generic_params(
&mut self,
params: &Vec<GenericParamAST>,
add_bounds: &NodeMap<Vec<TyParamBound>>,
itctx: ImplTraitContext,
) -> hir::HirVec<hir::GenericParam> {
params.iter().map(|param| self.lower_generic_param(param, add_bounds, itctx)).collect()
}
fn lower_generics(
&mut self,
generics: &Generics,
@ -2107,10 +2092,7 @@ impl<'a> LoweringContext<'a> {
span,
}) => {
self.with_in_scope_lifetime_defs(
bound_generic_params.iter().filter_map(|param| match param.kind {
GenericParamKindAST::Lifetime { .. } => Some(param),
_ => None,
}),
&bound_generic_params,
|this| {
hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
bound_generic_params: this.lower_generic_params(
@ -2203,13 +2185,7 @@ impl<'a> LoweringContext<'a> {
let bound_generic_params =
self.lower_generic_params(&p.bound_generic_params, &NodeMap(), itctx);
let trait_ref = self.with_parent_impl_lifetime_defs(
&bound_generic_params
.iter()
.filter_map(|param| match param.kind {
hir::GenericParamKind::Lifetime { .. } => Some(param.clone()),
_ => None,
})
.collect::<Vec<_>>(),
&bound_generic_params,
|this| this.lower_trait_ref(&p.trait_ref, itctx),
);
@ -2426,10 +2402,7 @@ impl<'a> LoweringContext<'a> {
);
let new_impl_items = self.with_in_scope_lifetime_defs(
ast_generics.params.iter().filter_map(|param| match param.kind {
GenericParamKindAST::Lifetime { .. } => Some(param),
_ => None,
}),
&ast_generics.params,
|this| {
impl_items
.iter()

View file

@ -176,12 +176,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
GenericParamKindAST::Lifetime { .. } => DefPathData::LifetimeParam(name),
GenericParamKindAST::Type { .. } => DefPathData::TypeParam(name),
};
self.create_def(
param.id,
def_path_data,
REGULAR_SPACE,
param.ident.span
);
self.create_def(param.id, def_path_data, REGULAR_SPACE, param.ident.span);
visit::walk_generic_param(self, param);
}

View file

@ -974,11 +974,9 @@ impl<'hir> Map<'hir> {
Some(NodeField(ref f)) => Some(&f.attrs[..]),
Some(NodeExpr(ref e)) => Some(&*e.attrs),
Some(NodeStmt(ref s)) => Some(s.node.attrs()),
Some(NodeGenericParam(param)) => {
match param.kind {
GenericParamKind::Type { ref attrs, .. } => Some(&attrs[..]),
_ => bug!("unexpected non-type NodeGenericParam")
}
Some(NodeGenericParam(param)) => match param.kind {
GenericParamKind::Type { ref attrs, .. } => Some(&attrs[..]),
_ => bug!("unexpected non-type NodeGenericParam")
}
// unit/tuple structs take the attributes straight from
// the struct definition.

View file

@ -1270,13 +1270,10 @@ impl<'a> State<'a> {
self.print_name(segment.name)?;
segment.with_generic_args(|generic_args| {
if !generic_args.args.is_empty() ||
!generic_args.bindings.is_empty()
{
self.print_generic_args(&generic_args, segment.infer_types, true)
} else {
Ok(())
if !generic_args.args.is_empty() || !generic_args.bindings.is_empty() {
return self.print_generic_args(&generic_args, segment.infer_types, true);
}
Ok(())
})?;
self.print_call_post(base_args)
}
@ -1642,8 +1639,7 @@ impl<'a> State<'a> {
segment.name != keywords::DollarCrate.name() {
self.print_name(segment.name)?;
segment.with_generic_args(|generic_args| {
self.print_generic_args(generic_args,
segment.infer_types,
self.print_generic_args(generic_args, segment.infer_types,
colons_before_params)
})?;
}

View file

@ -1036,21 +1036,19 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
// Get the `hir::TyParam` to verify whether it already has any bounds.
// We do this to avoid suggesting code that ends up as `T: 'a'b`,
// instead we suggest `T: 'a + 'b` in that case.
let has_lifetimes =
if let hir_map::NodeGenericParam(ref param) = hir.get(id) {
let mut has_bounds = false;
if let hir_map::NodeGenericParam(ref param) = hir.get(id) {
match param.kind {
GenericParamKind::Type { ref bounds, .. } => {
!bounds.is_empty()
has_bounds = !bounds.is_empty();
}
_ => bug!("unexpected non-type NodeGenericParam"),
}
} else {
false
};
}
let sp = hir.span(id);
// `sp` only covers `T`, change it so that it covers
// `T:` when appropriate
let sp = if has_lifetimes {
let sp = if has_bounds {
sp.to(self.tcx
.sess
.codemap()
@ -1058,7 +1056,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
} else {
sp
};
(sp, has_lifetimes)
(sp, has_bounds)
})
} else {
None

View file

@ -81,6 +81,18 @@ pub enum Region {
Free(DefId, /* lifetime decl */ DefId),
}
fn new_region(hir_map: &Map, param: &hir::GenericParam)
-> (hir::LifetimeName, DefId, LifetimeDefOrigin) {
let def_id = hir_map.local_def_id(param.id);
let (name, origin) = match param.kind {
GenericParamKind::Lifetime { name, in_band, .. } => {
(name, LifetimeDefOrigin::from_is_in_band(in_band))
}
_ => bug!("expected a lifetime param"),
};
(name, def_id, origin)
}
impl Region {
fn early(
hir_map: &Map,
@ -89,26 +101,14 @@ impl Region {
) -> (hir::LifetimeName, Region) {
let i = *index;
*index += 1;
let def_id = hir_map.local_def_id(param.id);
let (name, origin) = match param.kind {
GenericParamKind::Lifetime { name, in_band, .. } => {
(name, LifetimeDefOrigin::from_is_in_band(in_band))
}
_ => bug!("expected a lifetime param"),
};
let (name, def_id, origin) = new_region(hir_map, param);
debug!("Region::early: index={} def_id={:?}", i, def_id);
(name, Region::EarlyBound(i, def_id, origin))
}
fn late(hir_map: &Map, param: &hir::GenericParam) -> (hir::LifetimeName, Region) {
let depth = ty::INNERMOST;
let def_id = hir_map.local_def_id(param.id);
let (name, origin) = match param.kind {
GenericParamKind::Lifetime { name, in_band, .. } => {
(name, LifetimeDefOrigin::from_is_in_band(in_band))
}
_ => bug!("expected a lifetime param"),
};
let (name, def_id, origin) = new_region(hir_map, param);
debug!(
"Region::late: def={:?} depth={:?} def_id={:?} origin={:?}",
def,
@ -580,15 +580,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
let was_in_fn_syntax = self.is_in_fn_syntax;
self.is_in_fn_syntax = true;
let scope = Scope::Binder {
lifetimes: c.generic_params
.iter()
.filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => {
Some(Region::late(&self.tcx.hir, param))
}
_ => None,
})
.collect(),
lifetimes: c.generic_params.iter().filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => {
Some(Region::late(&self.tcx.hir, param))
}
_ => None,
}).collect(),
s: self.scope,
next_early_index,
track_lifetime_uses: true,
@ -770,19 +767,15 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
let mut index = self.next_early_index();
debug!("visit_ty: index = {}", index);
let mut type_count = 0;
let lifetimes = generics.params
.iter()
.filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => {
Some(Region::early(&self.tcx.hir, &mut index, param))
}
GenericParamKind::Type { .. } => {
type_count += 1;
None
}
})
.collect();
let lifetimes = generics.params.iter().filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => {
Some(Region::early(&self.tcx.hir, &mut index, param))
}
GenericParamKind::Type { .. } => {
type_count += 1;
None
}
}).collect();
let scope = Scope::Binder {
lifetimes,
next_early_index: index + type_count,
@ -825,19 +818,15 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
let mut index = self.next_early_index();
let mut next_early_index = index;
debug!("visit_ty: index = {}", index);
let lifetimes = generics.params
.iter()
.filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => {
Some(Region::early(&self.tcx.hir, &mut index, param))
}
GenericParamKind::Type { .. } => {
next_early_index += 1;
None
}
})
.collect();
let lifetimes = generics.params.iter().filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => {
Some(Region::early(&self.tcx.hir, &mut index, param))
}
GenericParamKind::Type { .. } => {
next_early_index += 1;
None
}
}).collect();
let scope = Scope::Binder {
lifetimes,
next_early_index,
@ -888,13 +877,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
check_mixed_explicit_and_in_band_defs(
self.tcx,
&generics.params.iter().filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => Some(param.clone()),
_ => None,
}).collect::<Vec<_>>()
);
check_mixed_explicit_and_in_band_defs(self.tcx, &generics.params);
for param in &generics.params {
match param.kind {
GenericParamKind::Lifetime { .. } => {}
@ -920,8 +903,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
Some(Region::late(&self.tcx.hir, param))
}
_ => None,
})
.collect();
}).collect();
if !lifetimes.is_empty() {
self.trait_ref_hack = true;
let next_early_index = self.next_early_index();
@ -992,16 +974,13 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
let next_early_index = self.next_early_index();
let scope = Scope::Binder {
lifetimes: trait_ref
.bound_generic_params
.iter()
lifetimes: trait_ref.bound_generic_params.iter()
.filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => {
Some(Region::late(&self.tcx.hir, param))
}
_ => None,
})
.collect(),
}).collect(),
s: self.scope,
next_early_index,
track_lifetime_uses: true,
@ -1068,11 +1047,11 @@ impl ShadowKind {
fn check_mixed_explicit_and_in_band_defs(
tcx: TyCtxt<'_, '_, '_>,
params: &[hir::GenericParam],
params: &P<[hir::GenericParam]>,
) {
let in_bands: Vec<_> = params.iter().map(|param| match param.kind {
GenericParamKind::Lifetime { in_band, .. } => (in_band, param.span),
_ => bug!("expected lifetime param"),
let in_bands: Vec<_> = params.iter().filter_map(|param| match param.kind {
GenericParamKind::Lifetime { in_band, .. } => Some((in_band, param.span)),
_ => None,
}).collect();
let out_of_band = in_bands.iter().find(|(in_band, _)| !in_band);
let in_band = in_bands.iter().find(|(in_band, _)| *in_band);
@ -1707,9 +1686,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
if elide_lifetimes {
self.resolve_elided_lifetimes(lifetimes, true);
} else {
for lt in lifetimes {
self.visit_lifetime(lt);
}
lifetimes.iter().for_each(|lt| self.visit_lifetime(lt));
}
// Figure out if this is a type/trait segment,

View file

@ -337,10 +337,10 @@ impl PrintContext {
if !verbose {
let mut type_params =
generics.params.iter().rev().filter_map(|param| match param.kind {
GenericParamDefKind::Lifetime => None,
GenericParamDefKind::Type { has_default, .. } => {
Some((param.def_id, has_default))
}
GenericParamDefKind::Lifetime => None,
}).peekable();
let has_default = {
let has_default = type_params.peek().map(|(_, has_default)| has_default);

View file

@ -836,8 +836,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
.zip(variants)
.map(|(variant, variant_layout)| {
// Subtract the size of the enum discriminant.
let bytes = variant_layout.size.bytes()
.saturating_sub(discr_size);
let bytes = variant_layout.size.bytes().saturating_sub(discr_size);
debug!("- variant `{}` is {} bytes large", variant.node.name, bytes);
bytes

View file

@ -1648,18 +1648,15 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
}
fn encode_info_for_generics(&mut self, generics: &hir::Generics) {
for param in &generics.params {
match param.kind {
hir::GenericParamKind::Lifetime { .. } => {}
hir::GenericParamKind::Type { ref default, .. } => {
let def_id = self.tcx.hir.local_def_id(param.id);
let has_default = Untracked(default.is_some());
self.record(def_id,
IsolatedEncoder::encode_info_for_ty_param,
(def_id, has_default));
}
generics.params.iter().for_each(|param| match param.kind {
hir::GenericParamKind::Lifetime { .. } => {}
hir::GenericParamKind::Type { ref default, .. } => {
let def_id = self.tcx.hir.local_def_id(param.id);
let has_default = Untracked(default.is_some());
let encode_info = IsolatedEncoder::encode_info_for_ty_param;
self.record(def_id, encode_info, (def_id, has_default));
}
}
});
}
fn encode_info_for_ty(&mut self, ty: &hir::Ty) {

View file

@ -1099,12 +1099,7 @@ fn create_mono_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
item: &'tcx hir::Item,
output: &mut Vec<MonoItem<'tcx>>) {
match item.node {
hir::ItemImpl(_,
_,
_,
ref generics,
..,
ref impl_item_refs) => {
hir::ItemImpl(_, _, _, ref generics, .., ref impl_item_refs) => {
for param in &generics.params {
match param.kind {
hir::GenericParamKind::Lifetime { .. } => {}

View file

@ -141,20 +141,19 @@ impl<'a> AstValidator<'a> {
fn check_late_bound_lifetime_defs(&self, params: &Vec<GenericParamAST>) {
// Check only lifetime parameters are present and that the lifetime
// parameters that are present have no bounds.
let non_lifetime_param_spans: Vec<_> = params.iter()
.filter_map(|param| match param.kind {
let non_lt_param_spans: Vec<_> = params.iter().filter_map(|param| match param.kind {
GenericParamKindAST::Lifetime { ref bounds, .. } => {
if !bounds.is_empty() {
let spans: Vec<_> = bounds.iter().map(|b| b.ident.span).collect();
self.err_handler().span_err(spans,
"lifetime bounds cannot be used in this context");
self.err_handler()
.span_err(spans, "lifetime bounds cannot be used in this context");
}
None
}
_ => Some(param.ident.span),
}).collect();
if !non_lifetime_param_spans.is_empty() {
self.err_handler().span_err(non_lifetime_param_spans,
if !non_lt_param_spans.is_empty() {
self.err_handler().span_err(non_lt_param_spans,
"only lifetime parameters can be used in this context");
}
}
@ -333,16 +332,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
GenericParamKindAST::Lifetime { .. } => {}
GenericParamKindAST::Type { ref bounds, ref default, .. } => {
if !bounds.is_empty() {
self.err_handler().span_err(param.ident.span,
"type parameters on the left side \
of a trait alias cannot be \
bounded");
self.err_handler()
.span_err(param.ident.span, "type parameters on the left \
side of a trait alias cannot be bounded");
}
if !default.is_none() {
self.err_handler().span_err(param.ident.span,
"type parameters on the left side \
of a trait alias cannot have \
defaults");
self.err_handler()
.span_err(param.ident.span, "type parameters on the left \
side of a trait alias cannot have defaults");
}
}
}
@ -402,10 +399,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
visit::walk_vis(self, vis)
}
fn visit_generics(&mut self, g: &'a Generics) {
fn visit_generics(&mut self, generics: &'a Generics) {
let mut seen_non_lifetime_param = false;
let mut seen_default = None;
for param in &g.params {
for param in &generics.params {
match (&param.kind, seen_non_lifetime_param) {
(GenericParamKindAST::Lifetime { .. }, true) => {
self.err_handler()
@ -424,13 +421,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
}
}
for predicate in &g.where_clause.predicates {
for predicate in &generics.where_clause.predicates {
if let WherePredicate::EqPredicate(ref predicate) = *predicate {
self.err_handler().span_err(predicate.span, "equality constraints are not yet \
supported in where clauses (#20041)");
}
}
visit::walk_generics(self, g)
visit::walk_generics(self, generics)
}
fn visit_generic_param(&mut self, param: &'a GenericParam) {
@ -516,12 +513,10 @@ impl<'a> Visitor<'a> for NestedImplTraitVisitor<'a> {
fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) {
match *generic_args {
GenericArgs::AngleBracketed(ref data) => {
for arg in &data.args {
match arg {
GenericArgAST::Type(ty) => self.visit_ty(ty),
_ => {}
}
}
data.args.iter().for_each(|arg| match arg {
GenericArgAST::Type(ty) => self.visit_ty(ty),
_ => {}
});
for type_binding in &data.bindings {
// Type bindings such as `Item=impl Debug` in `Iterator<Item=Debug>`
// are allowed to contain nested `impl Trait`.

View file

@ -1268,16 +1268,14 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
}
fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
for param in &generics.params {
match param.kind {
GenericParamKind::Lifetime { .. } => {}
GenericParamKind::Type { ref bounds, .. } => {
for bound in bounds {
self.check_ty_param_bound(bound);
}
generics.params.iter().for_each(|param| match param.kind {
GenericParamKind::Lifetime { .. } => {}
GenericParamKind::Type { ref bounds, .. } => {
for bound in bounds {
self.check_ty_param_bound(bound);
}
}
}
});
for predicate in &generics.where_clause.predicates {
match predicate {
&hir::WherePredicate::BoundPredicate(ref bound_pred) => {

View file

@ -802,10 +802,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
.filter_map(|param| match param.kind {
GenericParamKindAST::Lifetime { .. } => None,
GenericParamKindAST::Type { ref default, .. } => {
if default.is_some() {
if found_default || default.is_some() {
found_default = true;
}
if found_default {
return Some((Ident::with_empty_ctxt(param.ident.name), Def::Err));
}
None
@ -2209,8 +2207,7 @@ impl<'a> Resolver<'a> {
HasTypeParameters(generics, rib_kind) => {
let mut function_type_rib = Rib::new(rib_kind);
let mut seen_bindings = FxHashMap();
for param in &generics.params {
match param.kind {
generics.params.iter().for_each(|param| match param.kind {
GenericParamKindAST::Type { .. } => {
let ident = param.ident.modern();
debug!("with_type_parameter_rib: {}", param.id);
@ -2225,15 +2222,13 @@ impl<'a> Resolver<'a> {
}
seen_bindings.entry(ident).or_insert(param.ident.span);
// plain insert (no renaming)
let def_id = self.definitions.local_def_id(param.id);
let def = Def::TyParam(def_id);
// Plain insert (no renaming).
let def = Def::TyParam(self.definitions.local_def_id(param.id));
function_type_rib.bindings.insert(ident, def);
self.record_def(param.id, PathResolution::new(def));
}
_ => {}
}
}
});
self.ribs[TypeNS].push(function_type_rib);
}

View file

@ -826,12 +826,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
if let Some(ref generic_args) = seg.args {
match **generic_args {
ast::GenericArgs::AngleBracketed(ref data) => {
for arg in &data.args {
match arg {
ast::GenericArgAST::Type(ty) => self.visit_ty(ty),
_ => {}
}
}
data.args.iter().for_each(|arg| match arg {
ast::GenericArgAST::Type(ty) => self.visit_ty(ty),
_ => {}
});
}
ast::GenericArgs::Parenthesized(ref data) => {
for t in &data.inputs {
@ -915,12 +913,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
// Explicit types in the turbo-fish.
if let Some(ref generic_args) = seg.args {
if let ast::GenericArgs::AngleBracketed(ref data) = **generic_args {
for arg in &data.args {
match arg {
ast::GenericArgAST::Type(ty) => self.visit_ty(ty),
_ => {}
}
}
data.args.iter().for_each(|arg| match arg {
ast::GenericArgAST::Type(ty) => self.visit_ty(ty),
_ => {}
});
}
}
@ -1489,21 +1485,19 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
}
fn visit_generics(&mut self, generics: &'l ast::Generics) {
for param in &generics.params {
match param.kind {
ast::GenericParamKindAST::Lifetime { .. } => {}
ast::GenericParamKindAST::Type { ref bounds, ref default, .. } => {
for bound in bounds {
if let ast::TraitTyParamBound(ref trait_ref, _) = *bound {
self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path)
}
}
if let Some(ref ty) = default {
self.visit_ty(&ty);
generics.params.iter().for_each(|param| match param.kind {
ast::GenericParamKindAST::Lifetime { .. } => {}
ast::GenericParamKindAST::Type { ref bounds, ref default, .. } => {
for bound in bounds {
if let ast::TraitTyParamBound(ref trait_ref, _) = *bound {
self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path)
}
}
if let Some(ref ty) = default {
self.visit_ty(&ty);
}
}
}
});
}
fn visit_ty(&mut self, t: &'l ast::Ty) {

View file

@ -4979,12 +4979,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|data| {
let mut lifetimes = vec![];
let mut types = vec![];
for arg in &data.args {
match arg {
GenericArg::Lifetime(lt) => lifetimes.push(lt),
GenericArg::Type(ty) => types.push(ty),
}
}
data.args.iter().for_each(|arg| match arg {
GenericArg::Lifetime(lt) => lifetimes.push(lt),
GenericArg::Type(ty) => types.push(ty),
});
(lifetimes, types, s.infer_types, &data.bindings[..])
}
)

View file

@ -521,7 +521,10 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
// We only care about late bound regions, as we need to add them
// to the 'for<>' section
&ty::ReLateBound(_, ty::BoundRegion::BrNamed(_, name)) => {
Some(GenericParamDef::Lifetime(Lifetime(name.to_string())))
Some(GenericParamDef {
name: name.to_string(),
kind: GenericParamDefKind::Lifetime,
})
}
&ty::ReVar(_) | &ty::ReEarlyBound(_) => None,
_ => panic!("Unexpected region type {:?}", r),
@ -867,19 +870,17 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
existing_predicates.extend(final_bounds);
for p in generic_params.iter_mut() {
match p {
&mut GenericParamDef::Type(ref mut ty) => {
// We never want something like 'impl<T=Foo>'
ty.default.take();
let generic_ty = Type::Generic(ty.name.clone());
for param in generic_params.iter_mut() {
match param.kind {
GenericParamDefKind::Type { ref mut default, ref mut bounds, .. } => {
// We never want something like `impl<T=Foo>`.
default.take();
let generic_ty = Type::Generic(param.name.clone());
if !has_sized.contains(&generic_ty) {
ty.bounds.insert(0, TyParamBound::maybe_sized(self.cx));
bounds.insert(0, TyParamBound::maybe_sized(self.cx));
}
}
GenericParamDef::Lifetime(_) => {}
GenericParamDefKind::Lifetime => {}
}
}

View file

@ -1457,53 +1457,6 @@ impl Clean<Attributes> for [ast::Attribute] {
}
}
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
pub struct TyParam {
pub name: String,
pub did: DefId,
pub bounds: Vec<TyParamBound>,
pub default: Option<Type>,
pub synthetic: Option<hir::SyntheticTyParamKind>,
}
impl Clean<TyParam> for hir::GenericParam {
fn clean(&self, cx: &DocContext) -> TyParam {
match self.kind {
hir::GenericParamKind::Type { ref bounds, ref default, synthetic, .. } => {
TyParam {
name: self.name().clean(cx),
did: cx.tcx.hir.local_def_id(self.id),
bounds: bounds.clean(cx),
default: default.clean(cx),
synthetic: synthetic,
}
}
_ => panic!(),
}
}
}
impl<'tcx> Clean<TyParam> for ty::GenericParamDef {
fn clean(&self, cx: &DocContext) -> TyParam {
cx.renderinfo.borrow_mut().external_typarams.insert(self.def_id, self.name.clean(cx));
let has_default = match self.kind {
ty::GenericParamDefKind::Type { has_default, .. } => has_default,
_ => panic!("tried to convert a non-type GenericParamDef as a type")
};
TyParam {
name: self.name.clean(cx),
did: self.def_id,
bounds: vec![], // these are filled in from the where-clauses
default: if has_default {
Some(cx.tcx.type_of(self.def_id).clean(cx))
} else {
None
},
synthetic: None,
}
}
}
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
pub enum TyParamBound {
RegionBound(Lifetime),
@ -1634,8 +1587,11 @@ impl<'a, 'tcx> Clean<TyParamBound> for (&'a ty::TraitRef<'tcx>, Vec<TypeBinding>
if let ty::TyRef(ref reg, _, _) = ty_s.sty {
if let &ty::RegionKind::ReLateBound(..) = *reg {
debug!(" hit an ReLateBound {:?}", reg);
if let Some(lt) = reg.clean(cx) {
late_bounds.push(GenericParamDef::Lifetime(lt));
if let Some(Lifetime(name)) = reg.clean(cx) {
late_bounds.push(GenericParamDef {
name,
kind: GenericParamDefKind::Lifetime,
});
}
}
}
@ -1872,27 +1828,90 @@ impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
}
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
pub enum GenericParamDef {
Lifetime(Lifetime),
Type(TyParam),
pub enum GenericParamDefKind {
Lifetime,
Type {
did: DefId,
bounds: Vec<TyParamBound>,
default: Option<Type>,
synthetic: Option<hir::SyntheticTyParamKind>,
},
}
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
pub struct GenericParamDef {
pub name: String,
pub kind: GenericParamDefKind,
}
impl GenericParamDef {
pub fn is_synthetic_type_param(&self) -> bool {
match self {
GenericParamDef::Type(ty) => ty.synthetic.is_some(),
GenericParamDef::Lifetime(_) => false,
match self.kind {
GenericParamDefKind::Lifetime => false,
GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
}
}
}
impl<'tcx> Clean<GenericParamDef> for ty::GenericParamDef {
fn clean(&self, cx: &DocContext) -> GenericParamDef {
let (name, kind) = match self.kind {
ty::GenericParamDefKind::Lifetime => {
(self.name.to_string(), GenericParamDefKind::Lifetime)
}
ty::GenericParamDefKind::Type { has_default, .. } => {
cx.renderinfo.borrow_mut().external_typarams
.insert(self.def_id, self.name.clean(cx));
let default = if has_default {
Some(cx.tcx.type_of(self.def_id).clean(cx))
} else {
None
};
(self.name.clean(cx), GenericParamDefKind::Type {
did: self.def_id,
bounds: vec![], // These are filled in from the where-clauses.
default,
synthetic: None,
})
}
};
GenericParamDef {
name,
kind,
}
}
}
impl Clean<GenericParamDef> for hir::GenericParam {
fn clean(&self, cx: &DocContext) -> GenericParamDef {
match self.kind {
hir::GenericParamKind::Lifetime { .. } => {
GenericParamDef::Lifetime(self.clean(cx))
let (name, kind) = match self.kind {
hir::GenericParamKind::Lifetime { ref bounds, .. } => {
let name = if bounds.len() > 0 {
let mut s = format!("{}: {}", self.name(), bounds[0].name.name());
for bound in bounds.iter().skip(1) {
s.push_str(&format!(" + {}", bound.name.name()));
}
s
} else {
self.name().to_string()
};
(name, GenericParamDefKind::Lifetime)
}
hir::GenericParamKind::Type { .. } => GenericParamDef::Type(self.clean(cx)),
hir::GenericParamKind::Type { ref bounds, ref default, synthetic, .. } => {
(self.name().clean(cx), GenericParamDefKind::Type {
did: cx.tcx.hir.local_def_id(self.id),
bounds: bounds.clean(cx),
default: default.clean(cx),
synthetic: synthetic,
})
}
};
GenericParamDef {
name,
kind,
}
}
}
@ -1919,17 +1938,16 @@ impl Clean<Generics> for hir::Generics {
}
let impl_trait_params = self.params
.iter()
.filter(|p| is_impl_trait(p))
.map(|p| {
let p = p.clean(cx);
if let GenericParamDef::Type(ref tp) = p {
cx.impl_trait_bounds
.borrow_mut()
.insert(tp.did, tp.bounds.clone());
} else {
unreachable!()
.filter(|param| is_impl_trait(param))
.map(|param| {
let param: GenericParamDef = param.clean(cx);
match param.kind {
GenericParamDefKind::Lifetime => unreachable!(),
GenericParamDefKind::Type { did, ref bounds, .. } => {
cx.impl_trait_bounds.borrow_mut().insert(did, bounds.clone());
}
}
p
param
})
.collect::<Vec<_>>();
@ -1940,23 +1958,26 @@ impl Clean<Generics> for hir::Generics {
}
params.extend(impl_trait_params);
let mut g = Generics {
let mut generics = Generics {
params,
where_predicates: self.where_clause.predicates.clean(cx)
where_predicates: self.where_clause.predicates.clean(cx),
};
// Some duplicates are generated for ?Sized bounds between type params and where
// predicates. The point in here is to move the bounds definitions from type params
// to where predicates when such cases occur.
for where_pred in &mut g.where_predicates {
for where_pred in &mut generics.where_predicates {
match *where_pred {
WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds } => {
if bounds.is_empty() {
for param in &mut g.params {
if let GenericParamDef::Type(ref mut type_param) = *param {
if &type_param.name == name {
mem::swap(bounds, &mut type_param.bounds);
break
for param in &mut generics.params {
match param.kind {
GenericParamDefKind::Lifetime => {}
GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => {
if &param.name == name {
mem::swap(bounds, ty_bounds);
break
}
}
}
}
@ -1965,7 +1986,7 @@ impl Clean<Generics> for hir::Generics {
_ => continue,
}
}
g
generics
}
}
@ -1988,7 +2009,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
}
Some(param.clean(cx))
}
}).collect::<Vec<TyParam>>();
}).collect::<Vec<GenericParamDef>>();
let mut where_predicates = preds.predicates.to_vec().clean(cx);
@ -2033,15 +2054,9 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
params: gens.params
.iter()
.flat_map(|param| match param.kind {
ty::GenericParamDefKind::Lifetime => {
Some(GenericParamDef::Lifetime(param.clean(cx)))
}
ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)),
ty::GenericParamDefKind::Type { .. } => None,
}).chain(
simplify::ty_params(stripped_typarams)
.into_iter()
.map(|tp| GenericParamDef::Type(tp))
)
}).chain(simplify::ty_params(stripped_typarams).into_iter())
.collect(),
where_predicates: simplify::where_clauses(cx, where_predicates),
}

View file

@ -135,9 +135,14 @@ pub fn where_clauses(cx: &DocContext, clauses: Vec<WP>) -> Vec<WP> {
clauses
}
pub fn ty_params(mut params: Vec<clean::TyParam>) -> Vec<clean::TyParam> {
pub fn ty_params(mut params: Vec<clean::GenericParamDef>) -> Vec<clean::GenericParamDef> {
for param in &mut params {
param.bounds = ty_bounds(mem::replace(&mut param.bounds, Vec::new()));
match param.kind {
clean::GenericParamDefKind::Type { ref mut bounds, .. } => {
*bounds = ty_bounds(mem::replace(bounds, Vec::new()));
}
_ => panic!("expected only type parameters"),
}
}
params
}

View file

@ -119,20 +119,20 @@ impl<'a> fmt::Display for TyParamBounds<'a> {
impl fmt::Display for clean::GenericParamDef {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
clean::GenericParamDef::Lifetime(ref lp) => write!(f, "{}", lp),
clean::GenericParamDef::Type(ref tp) => {
f.write_str(&tp.name)?;
match self.kind {
clean::GenericParamDefKind::Lifetime => write!(f, "{}", self.name),
clean::GenericParamDefKind::Type { ref bounds, ref default, .. } => {
f.write_str(&self.name)?;
if !tp.bounds.is_empty() {
if !bounds.is_empty() {
if f.alternate() {
write!(f, ": {:#}", TyParamBounds(&tp.bounds))?;
write!(f, ": {:#}", TyParamBounds(bounds))?;
} else {
write!(f, ":&nbsp;{}", TyParamBounds(&tp.bounds))?;
write!(f, ":&nbsp;{}", TyParamBounds(bounds))?;
}
}
if let Some(ref ty) = tp.default {
if let Some(ref ty) = default {
if f.alternate() {
write!(f, " = {:#}", ty)?;
} else {

View file

@ -1453,11 +1453,11 @@ impl DocFolder for Cache {
impl<'a> Cache {
fn generics(&mut self, generics: &clean::Generics) {
for param in &generics.params {
match *param {
clean::GenericParamDef::Type(ref typ) => {
self.typarams.insert(typ.did, typ.name.clone());
match param.kind {
clean::GenericParamDefKind::Lifetime => {}
clean::GenericParamDefKind::Type { did, .. } => {
self.typarams.insert(did, param.name.clone());
}
clean::GenericParamDef::Lifetime(_) => {}
}
}
}