1
Fork 0

Add GenericParam, refactor Generics in ast, hir, rustdoc

The Generics now contain one Vec of an enum for the generic parameters,
rather than two separate Vec's for lifetime and type parameters.

Additionally, places that previously used Vec<LifetimeDef> now use
Vec<GenericParam> instead.
This commit is contained in:
Jonas Platte 2017-10-16 21:07:26 +02:00
parent ab7abfcf34
commit 78493ed21a
51 changed files with 1020 additions and 832 deletions

View file

@ -279,6 +279,9 @@ pub trait Visitor<'v> : Sized {
fn visit_ty(&mut self, t: &'v Ty) {
walk_ty(self, t)
}
fn visit_generic_param(&mut self, p: &'v GenericParam) {
walk_generic_param(self, p)
}
fn visit_generics(&mut self, g: &'v Generics) {
walk_generics(self, g)
}
@ -336,9 +339,6 @@ pub trait Visitor<'v> : Sized {
fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
walk_lifetime(self, lifetime)
}
fn visit_lifetime_def(&mut self, lifetime: &'v LifetimeDef) {
walk_lifetime_def(self, lifetime)
}
fn visit_qpath(&mut self, qpath: &'v QPath, id: NodeId, span: Span) {
walk_qpath(self, qpath, id, span)
}
@ -430,17 +430,12 @@ pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime
}
}
pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V, lifetime_def: &'v LifetimeDef) {
visitor.visit_lifetime(&lifetime_def.lifetime);
walk_list!(visitor, visit_lifetime, &lifetime_def.bounds);
}
pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V,
trait_ref: &'v PolyTraitRef,
_modifier: TraitBoundModifier)
where V: Visitor<'v>
{
walk_list!(visitor, visit_lifetime_def, &trait_ref.bound_lifetimes);
walk_list!(visitor, visit_generic_param, &trait_ref.bound_generic_params);
visitor.visit_trait_ref(&trait_ref.trait_ref);
}
@ -581,7 +576,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
}
TyBareFn(ref function_declaration) => {
visitor.visit_fn_decl(&function_declaration.decl);
walk_list!(visitor, visit_lifetime_def, &function_declaration.lifetimes);
walk_list!(visitor, visit_generic_param, &function_declaration.generic_params);
}
TyPath(ref qpath) => {
visitor.visit_qpath(qpath, typ.id, typ.span);
@ -729,14 +724,23 @@ pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v TyPar
}
}
pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) {
for param in &generics.ty_params {
visitor.visit_id(param.id);
visitor.visit_name(param.span, param.name);
walk_list!(visitor, visit_ty_param_bound, &param.bounds);
walk_list!(visitor, visit_ty, &param.default);
pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v GenericParam) {
match *param {
GenericParam::Lifetime(ref ld) => {
visitor.visit_lifetime(&ld.lifetime);
walk_list!(visitor, visit_lifetime, &ld.bounds);
}
walk_list!(visitor, visit_lifetime_def, &generics.lifetimes);
GenericParam::Type(ref ty_param) => {
visitor.visit_id(ty_param.id);
visitor.visit_name(ty_param.span, ty_param.name);
walk_list!(visitor, visit_ty_param_bound, &ty_param.bounds);
walk_list!(visitor, visit_ty, &ty_param.default);
}
}
}
pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) {
walk_list!(visitor, visit_generic_param, &generics.params);
visitor.visit_id(generics.where_clause.id);
walk_list!(visitor, visit_where_predicate, &generics.where_clause.predicates);
}
@ -748,11 +752,11 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>(
match predicate {
&WherePredicate::BoundPredicate(WhereBoundPredicate{ref bounded_ty,
ref bounds,
ref bound_lifetimes,
ref bound_generic_params,
..}) => {
visitor.visit_ty(bounded_ty);
walk_list!(visitor, visit_ty_param_bound, bounds);
walk_list!(visitor, visit_lifetime_def, bound_lifetimes);
walk_list!(visitor, visit_generic_param, bound_generic_params);
}
&WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime,
ref bounds,

View file

@ -253,7 +253,9 @@ impl<'a> LoweringContext<'a> {
ItemKind::Ty(_, ref generics) |
ItemKind::Trait(_, _, ref generics, ..) => {
let def_id = self.lctx.resolver.definitions().local_def_id(item.id);
let count = generics.lifetimes.len();
let count = generics.params.iter()
.filter(|param| param.is_lifetime_param())
.count();
self.lctx.type_def_lifetime_params.insert(def_id, count);
}
_ => {}
@ -306,8 +308,8 @@ 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.lifetimes.clone(),
_ => Vec::new().into(),
generics.lifetimes().cloned().collect::<Vec<_>>(),
_ => Vec::new(),
};
self.lctx.with_parent_impl_lifetime_defs(&item_lifetimes, |this| {
@ -532,14 +534,14 @@ impl<'a> LoweringContext<'a> {
span.with_ctxt(SyntaxContext::empty().apply_mark(mark))
}
// Creates a new hir::LifetimeDef for every new lifetime encountered
// while evaluating `f`. Definitions are created with the parent provided.
// If no `parent_id` is provided, no definitions will be returned.
// Creates a new hir::GenericParam for every new lifetime and type parameter
// encountered while evaluating `f`. Definitions are created with the parent
// provided. If no `parent_id` is provided, no definitions will be returned.
fn collect_in_band_defs<T, F>(
&mut self,
parent_id: Option<DefId>,
f: F
) -> (Vec<hir::TyParam>, Vec<hir::LifetimeDef>, T) where F: FnOnce(&mut LoweringContext) -> T
) -> (Vec<hir::GenericParam>, T) where F: FnOnce(&mut LoweringContext) -> T
{
assert!(!self.is_collecting_in_band_lifetimes);
assert!(self.lifetimes_to_define.is_empty());
@ -554,7 +556,7 @@ impl<'a> LoweringContext<'a> {
let in_band_ty_params = self.in_band_ty_params.split_off(0);
let lifetimes_to_define = self.lifetimes_to_define.split_off(0);
let lifetime_defs = match parent_id {
let mut params = match parent_id {
Some(parent_id) => lifetimes_to_define.into_iter().map(|(span, name)| {
let def_node_id = self.next_id().node_id;
@ -567,7 +569,7 @@ impl<'a> LoweringContext<'a> {
Mark::root()
);
hir::LifetimeDef {
hir::GenericParam::Lifetime(hir::LifetimeDef {
lifetime: hir::Lifetime {
id: def_node_id,
span,
@ -576,12 +578,14 @@ impl<'a> LoweringContext<'a> {
bounds: Vec::new().into(),
pure_wrt_drop: false,
in_band: true,
}
})
}).collect(),
None => Vec::new(),
};
(in_band_ty_params, lifetime_defs, res)
params.extend(in_band_ty_params.into_iter().map(|tp| hir::GenericParam::Type(tp)));
(params, res)
}
// Evaluates `f` with the lifetimes in `lt_defs` in-scope.
@ -635,24 +639,24 @@ impl<'a> LoweringContext<'a> {
) -> (hir::Generics, T)
where F: FnOnce(&mut LoweringContext) -> T
{
let (in_band_ty_defs, in_band_lifetime_defs, (mut lowered_generics, res)) =
self.with_in_scope_lifetime_defs(&generics.lifetimes, |this| {
let (in_band_defs, (mut lowered_generics, res)) =
self.with_in_scope_lifetime_defs(
&generics.params
.iter()
.filter_map(|p| match *p {
GenericParam::Lifetime(ref ld) => Some(ld.clone()),
_ => None,
})
.collect::<Vec<_>>(),
|this| {
this.collect_in_band_defs(parent_id, |this| {
(this.lower_generics(generics), f(this))
})
});
}
);
lowered_generics.ty_params =
lowered_generics.ty_params
.iter().cloned()
.chain(in_band_ty_defs.into_iter())
.collect();
lowered_generics.lifetimes =
lowered_generics.lifetimes
.iter().cloned()
.chain(in_band_lifetime_defs.into_iter())
.collect();
lowered_generics.params =
lowered_generics.params.iter().cloned().chain(in_band_defs).collect();
(lowered_generics, res)
}
@ -877,9 +881,16 @@ impl<'a> LoweringContext<'a> {
hir::TyRptr(lifetime, self.lower_mt(mt, itctx))
}
TyKind::BareFn(ref f) => {
self.with_in_scope_lifetime_defs(&f.lifetimes, |this|
hir::TyBareFn(P(hir::BareFnTy {
lifetimes: this.lower_lifetime_defs(&f.lifetimes),
self.with_in_scope_lifetime_defs(
&f.generic_params
.iter()
.filter_map(|p| match *p {
GenericParam::Lifetime(ref ld) => Some(ld.clone()),
_ => None,
})
.collect::<Vec<_>>(),
|this| hir::TyBareFn(P(hir::BareFnTy {
generic_params: this.lower_generic_params(&f.generic_params, &NodeMap()),
unsafety: this.lower_unsafety(f.unsafety),
abi: f.abi,
decl: this.lower_fn_decl(&f.decl, None, false),
@ -954,9 +965,7 @@ impl<'a> LoweringContext<'a> {
hir::TyImplTraitExistential(hir::ExistTy {
generics: hir::Generics {
lifetimes: lifetime_defs,
// Type parameters are taken from environment:
ty_params: Vec::new().into(),
params: lifetime_defs,
where_clause: hir::WhereClause {
id: self.next_id().node_id,
predicates: Vec::new().into(),
@ -1027,7 +1036,7 @@ impl<'a> LoweringContext<'a> {
&mut self,
parent_index: DefIndex,
bounds: &hir::TyParamBounds
) -> (HirVec<hir::Lifetime>, HirVec<hir::LifetimeDef>) {
) -> (HirVec<hir::Lifetime>, HirVec<hir::GenericParam>) {
// This visitor walks over impl trait bounds and creates defs for all lifetimes which
// appear in the bounds, excluding lifetimes that are created within the bounds.
@ -1039,7 +1048,7 @@ impl<'a> LoweringContext<'a> {
currently_bound_lifetimes: Vec<hir::LifetimeName>,
already_defined_lifetimes: HashSet<hir::LifetimeName>,
output_lifetimes: Vec<hir::Lifetime>,
output_lifetime_defs: Vec<hir::LifetimeDef>,
output_lifetime_params: Vec<hir::GenericParam>,
}
impl<'r, 'a: 'r, 'v> hir::intravisit::Visitor<'v> for ImplTraitLifetimeCollector<'r, 'a> {
@ -1078,7 +1087,8 @@ impl<'a> LoweringContext<'a> {
let old_len = self.currently_bound_lifetimes.len();
// Record the introduction of 'a in `for<'a> ...`
for lt_def in &polytr.bound_lifetimes {
for param in &polytr.bound_generic_params {
if let hir::GenericParam::Lifetime(ref lt_def) = *param {
// Introduce lifetimes one at a time so that we can handle
// cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>`
self.currently_bound_lifetimes.push(lt_def.lifetime.name);
@ -1088,6 +1098,7 @@ impl<'a> LoweringContext<'a> {
self.visit_lifetime(&lt_bound);
}
}
}
hir::intravisit::walk_trait_ref(self, &polytr.trait_ref);
@ -1133,12 +1144,12 @@ impl<'a> LoweringContext<'a> {
span: lifetime.span,
name: name,
};
self.output_lifetime_defs.push(hir::LifetimeDef {
self.output_lifetime_params.push(hir::GenericParam::Lifetime(hir::LifetimeDef {
lifetime: def_lifetime,
bounds: Vec::new().into(),
pure_wrt_drop: false,
in_band: false,
});
}));
}
}
}
@ -1150,7 +1161,7 @@ impl<'a> LoweringContext<'a> {
currently_bound_lifetimes: Vec::new(),
already_defined_lifetimes: HashSet::new(),
output_lifetimes: Vec::new(),
output_lifetime_defs: Vec::new(),
output_lifetime_params: Vec::new(),
};
for bound in bounds {
@ -1159,7 +1170,7 @@ impl<'a> LoweringContext<'a> {
(
lifetime_collector.output_lifetimes.into(),
lifetime_collector.output_lifetime_defs.into()
lifetime_collector.output_lifetime_params.into()
)
}
@ -1568,13 +1579,6 @@ impl<'a> LoweringContext<'a> {
}
}
fn lower_ty_params(&mut self, tps: &Vec<TyParam>, add_bounds: &NodeMap<Vec<TyParamBound>>)
-> hir::HirVec<hir::TyParam> {
tps.iter().map(|tp| {
self.lower_ty_param(tp, add_bounds.get(&tp.id).map_or(&[][..], |x| &x))
}).collect()
}
fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime {
let name = match self.lower_ident(l.ident) {
x if x == "'_" => hir::LifetimeName::Underscore,
@ -1620,12 +1624,31 @@ impl<'a> LoweringContext<'a> {
lts.iter().map(|l| self.lower_lifetime(l)).collect()
}
fn lower_lifetime_defs(&mut self, lts: &Vec<LifetimeDef>) -> hir::HirVec<hir::LifetimeDef> {
lts.iter().map(|l| self.lower_lifetime_def(l)).collect()
fn lower_generic_params(
&mut self,
params: &Vec<GenericParam>,
add_bounds: &NodeMap<Vec<TyParamBound>>,
) -> hir::HirVec<hir::GenericParam> {
params.iter()
.map(|param| match *param {
GenericParam::Lifetime(ref lifetime_def) => {
hir::GenericParam::Lifetime(self.lower_lifetime_def(lifetime_def))
}
GenericParam::Type(ref ty_param) => {
hir::GenericParam::Type(self.lower_ty_param(
ty_param,
add_bounds.get(&ty_param.id).map_or(&[][..], |x| &x)
))
}
})
.collect()
}
fn lower_generics(&mut self, g: &Generics) -> hir::Generics {
// Collect `?Trait` bounds in where clause and move them to parameter definitions.
// FIXME: This could probably be done with less rightward drift. Also looks like two control
// paths where report_error is called are also the only paths that advance to after
// the match statement, so the error reporting could probably just be moved there.
let mut add_bounds = NodeMap();
for pred in &g.where_clause.predicates {
if let WherePredicate::BoundPredicate(ref bound_pred) = *pred {
@ -1640,21 +1663,24 @@ impl<'a> LoweringContext<'a> {
match bound_pred.bounded_ty.node {
TyKind::Path(None, ref path)
if path.segments.len() == 1 &&
bound_pred.bound_lifetimes.is_empty() => {
bound_pred.bound_generic_params.is_empty() => {
if let Some(Def::TyParam(def_id)) =
self.resolver.get_resolution(bound_pred.bounded_ty.id)
.map(|d| d.base_def()) {
if let Some(node_id) =
self.resolver.definitions().as_local_node_id(def_id) {
for ty_param in &g.ty_params {
for param in &g.params {
if let GenericParam::Type(ref ty_param) = *param {
if node_id == ty_param.id {
add_bounds.entry(ty_param.id).or_insert(Vec::new())
add_bounds.entry(ty_param.id)
.or_insert(Vec::new())
.push(bound.clone());
continue 'next_bound;
}
}
}
}
}
report_error(self)
}
_ => report_error(self)
@ -1665,8 +1691,7 @@ impl<'a> LoweringContext<'a> {
}
hir::Generics {
ty_params: self.lower_ty_params(&g.ty_params, &add_bounds),
lifetimes: self.lower_lifetime_defs(&g.lifetimes),
params: self.lower_generic_params(&g.params, &add_bounds),
where_clause: self.lower_where_clause(&g.where_clause),
span: g.span,
}
@ -1684,13 +1709,21 @@ impl<'a> LoweringContext<'a> {
fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate {
match *pred {
WherePredicate::BoundPredicate(WhereBoundPredicate{ ref bound_lifetimes,
WherePredicate::BoundPredicate(WhereBoundPredicate{ ref bound_generic_params,
ref bounded_ty,
ref bounds,
span}) => {
self.with_in_scope_lifetime_defs(bound_lifetimes, |this| {
self.with_in_scope_lifetime_defs(
&bound_generic_params.iter()
.filter_map(|p| match *p {
GenericParam::Lifetime(ref ld) => Some(ld.clone()),
_ => None,
})
.collect::<Vec<_>>(),
|this| {
hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
bound_lifetimes: this.lower_lifetime_defs(bound_lifetimes),
bound_generic_params:
this.lower_generic_params(bound_generic_params, &NodeMap()),
bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::Disallowed),
bounds: bounds.iter().filter_map(|bound| match *bound {
// Ignore `?Trait` bounds.
@ -1701,7 +1734,8 @@ impl<'a> LoweringContext<'a> {
}).collect(),
span,
})
})
}
)
}
WherePredicate::RegionPredicate(WhereRegionPredicate{ ref lifetime,
ref bounds,
@ -1761,12 +1795,19 @@ impl<'a> LoweringContext<'a> {
p: &PolyTraitRef,
itctx: ImplTraitContext)
-> hir::PolyTraitRef {
let bound_lifetimes = self.lower_lifetime_defs(&p.bound_lifetimes);
let trait_ref = self.with_parent_impl_lifetime_defs(&bound_lifetimes,
|this| this.lower_trait_ref(&p.trait_ref, itctx));
let bound_generic_params = self.lower_generic_params(&p.bound_generic_params, &NodeMap());
let trait_ref = self.with_parent_impl_lifetime_defs(
&bound_generic_params.iter()
.filter_map(|p| match *p {
hir::GenericParam::Lifetime(ref ld) => Some(ld.clone()),
_ => None,
})
.collect::<Vec<_>>(),
|this| this.lower_trait_ref(&p.trait_ref, itctx),
);
hir::PolyTraitRef {
bound_lifetimes,
bound_generic_params,
trait_ref,
span: p.span,
}
@ -1945,11 +1986,19 @@ impl<'a> LoweringContext<'a> {
});
let new_impl_items = self.with_in_scope_lifetime_defs(
&ast_generics.lifetimes, |this| {
&ast_generics.params
.iter()
.filter_map(|p| match *p {
GenericParam::Lifetime(ref ld) => Some(ld.clone()),
_ => None,
})
.collect::<Vec<_>>(),
|this| {
impl_items.iter()
.map(|item| this.lower_impl_item_ref(item))
.collect()
});
}
);
hir::ItemImpl(self.lower_unsafety(unsafety),
@ -3621,7 +3670,7 @@ impl<'a> LoweringContext<'a> {
// Turn trait object paths into `TyTraitObject` instead.
if let Def::Trait(_) = path.def {
let principal = hir::PolyTraitRef {
bound_lifetimes: hir_vec![],
bound_generic_params: hir::HirVec::new(),
trait_ref: hir::TraitRef {
path: path.and_then(|path| path),
ref_id: id.node_id,

View file

@ -326,7 +326,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
}
fn visit_generics(&mut self, generics: &'hir Generics) {
for ty_param in generics.ty_params.iter() {
for ty_param in generics.ty_params() {
self.insert(ty_param.id, NodeTyParam(ty_param));
}

View file

@ -183,14 +183,25 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
});
}
fn visit_generics(&mut self, generics: &'a Generics) {
for ty_param in generics.ty_params.iter() {
self.create_def(ty_param.id,
fn visit_generic_param(&mut self, param: &'a GenericParam) {
match *param {
GenericParam::Lifetime(ref lifetime_def) => {
self.create_def(
lifetime_def.lifetime.id,
DefPathData::LifetimeDef(lifetime_def.lifetime.ident.name.as_str()),
REGULAR_SPACE
);
}
GenericParam::Type(ref ty_param) => {
self.create_def(
ty_param.id,
DefPathData::TypeParam(ty_param.ident.name.as_str()),
REGULAR_SPACE);
REGULAR_SPACE
);
}
}
visit::walk_generics(self, generics);
visit::walk_generic_param(self, param);
}
fn visit_trait_item(&mut self, ti: &'a TraitItem) {
@ -268,12 +279,6 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
visit::walk_ty(self, ty);
}
fn visit_lifetime_def(&mut self, def: &'a LifetimeDef) {
self.create_def(def.lifetime.id,
DefPathData::LifetimeDef(def.lifetime.ident.name.as_str()),
REGULAR_SPACE);
}
fn visit_stmt(&mut self, stmt: &'a Stmt) {
match stmt.node {
StmtKind::Mac(..) => self.visit_macro_invoc(stmt.id, false),

View file

@ -48,6 +48,8 @@ use rustc_data_structures::indexed_vec;
use serialize::{self, Encoder, Encodable, Decoder, Decodable};
use std::collections::BTreeMap;
use std::fmt;
use std::iter;
use std::slice;
/// HIR doesn't commit to a concrete storage type and has its own alias for a vector.
/// It can be `Vec`, `P<[T]>` or potentially `Box<[T]>`, or some other container with similar
@ -398,12 +400,67 @@ pub struct TyParam {
pub synthetic: Option<SyntheticTyParamKind>,
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum GenericParam {
Lifetime(LifetimeDef),
Type(TyParam),
}
impl GenericParam {
pub fn is_lifetime_param(&self) -> bool {
match *self {
GenericParam::Lifetime(_) => true,
_ => false,
}
}
pub fn is_type_param(&self) -> bool {
match *self {
GenericParam::Type(_) => true,
_ => false,
}
}
}
pub trait GenericParamsExt {
fn lifetimes<'a>(&'a self) -> iter::FilterMap<
slice::Iter<GenericParam>,
fn(&GenericParam) -> Option<&LifetimeDef>,
>;
fn ty_params<'a>(&'a self) -> iter::FilterMap<
slice::Iter<GenericParam>,
fn(&GenericParam) -> Option<&TyParam>,
>;
}
impl GenericParamsExt for [GenericParam] {
fn lifetimes<'a>(&'a self) -> iter::FilterMap<
slice::Iter<GenericParam>,
fn(&GenericParam) -> Option<&LifetimeDef>,
> {
self.iter().filter_map(|param| match *param {
GenericParam::Lifetime(ref l) => Some(l),
_ => None,
})
}
fn ty_params<'a>(&'a self) -> iter::FilterMap<
slice::Iter<GenericParam>,
fn(&GenericParam) -> Option<&TyParam>,
> {
self.iter().filter_map(|param| match *param {
GenericParam::Type(ref t) => Some(t),
_ => None,
})
}
}
/// Represents lifetimes and type parameters attached to a declaration
/// of a function, enum, trait, etc.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct Generics {
pub lifetimes: HirVec<LifetimeDef>,
pub ty_params: HirVec<TyParam>,
pub params: HirVec<GenericParam>,
pub where_clause: WhereClause,
pub span: Span,
}
@ -411,8 +468,7 @@ pub struct Generics {
impl Generics {
pub fn empty() -> Generics {
Generics {
lifetimes: HirVec::new(),
ty_params: HirVec::new(),
params: HirVec::new(),
where_clause: WhereClause {
id: DUMMY_NODE_ID,
predicates: HirVec::new(),
@ -422,15 +478,19 @@ impl Generics {
}
pub fn is_lt_parameterized(&self) -> bool {
!self.lifetimes.is_empty()
self.params.iter().any(|param| param.is_lifetime_param())
}
pub fn is_type_parameterized(&self) -> bool {
!self.ty_params.is_empty()
self.params.iter().any(|param| param.is_type_param())
}
pub fn is_parameterized(&self) -> bool {
self.is_lt_parameterized() || self.is_type_parameterized()
pub fn lifetimes<'a>(&'a self) -> impl Iterator<Item = &'a LifetimeDef> {
self.params.lifetimes()
}
pub fn ty_params<'a>(&'a self) -> impl Iterator<Item = &'a TyParam> {
self.params.ty_params()
}
}
@ -450,17 +510,22 @@ impl UnsafeGeneric {
impl Generics {
pub fn carries_unsafe_attr(&self) -> Option<UnsafeGeneric> {
for r in &self.lifetimes {
if r.pure_wrt_drop {
return Some(UnsafeGeneric::Region(r.clone(), "may_dangle"));
for param in &self.params {
match *param {
GenericParam::Lifetime(ref l) => {
if l.pure_wrt_drop {
return Some(UnsafeGeneric::Region(l.clone(), "may_dangle"));
}
}
for t in &self.ty_params {
GenericParam::Type(ref t) => {
if t.pure_wrt_drop {
return Some(UnsafeGeneric::Type(t.clone(), "may_dangle"));
}
}
return None;
}
}
None
}
}
@ -493,8 +558,8 @@ pub enum WherePredicate {
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct WhereBoundPredicate {
pub span: Span,
/// Any lifetimes from a `for` binding
pub bound_lifetimes: HirVec<LifetimeDef>,
/// Any generics from a `for` binding
pub bound_generic_params: HirVec<GenericParam>,
/// The type being bounded
pub bounded_ty: P<Ty>,
/// Trait and lifetime bounds (`Clone+Send+'static`)
@ -1475,7 +1540,7 @@ pub enum PrimTy {
pub struct BareFnTy {
pub unsafety: Unsafety,
pub abi: Abi,
pub lifetimes: HirVec<LifetimeDef>,
pub generic_params: HirVec<GenericParam>,
pub decl: P<FnDecl>,
pub arg_names: HirVec<Spanned<Name>>,
}
@ -1733,7 +1798,7 @@ pub struct TraitRef {
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct PolyTraitRef {
/// The `'a` in `<'a> Foo<&'a T>`
pub bound_lifetimes: HirVec<LifetimeDef>,
pub bound_generic_params: HirVec<GenericParam>,
/// The `Foo<&'a T>` in `<'a> Foo<&'a T>`
pub trait_ref: TraitRef,

View file

@ -390,16 +390,7 @@ impl<'a> State<'a> {
self.pclose()?;
}
hir::TyBareFn(ref f) => {
let generics = hir::Generics {
lifetimes: f.lifetimes.clone(),
ty_params: hir::HirVec::new(),
where_clause: hir::WhereClause {
id: ast::DUMMY_NODE_ID,
predicates: hir::HirVec::new(),
},
span: syntax_pos::DUMMY_SP,
};
self.print_ty_fn(f.abi, f.unsafety, &f.decl, None, &generics,
self.print_ty_fn(f.abi, f.unsafety, &f.decl, None, &f.generic_params,
&f.arg_names[..])?;
}
hir::TyPath(ref qpath) => {
@ -635,15 +626,15 @@ impl<'a> State<'a> {
self.s.word(&ga.asm.as_str())?;
self.end()?
}
hir::ItemTy(ref ty, ref params) => {
hir::ItemTy(ref ty, ref generics) => {
self.ibox(indent_unit)?;
self.ibox(0)?;
self.word_nbsp(&visibility_qualified(&item.vis, "type"))?;
self.print_name(item.name)?;
self.print_generics(params)?;
self.print_generic_params(&generics.params)?;
self.end()?; // end the inner ibox
self.print_where_clause(&params.where_clause)?;
self.print_where_clause(&generics.where_clause)?;
self.s.space()?;
self.word_space("=")?;
self.print_type(&ty)?;
@ -686,8 +677,8 @@ impl<'a> State<'a> {
self.print_unsafety(unsafety)?;
self.word_nbsp("impl")?;
if generics.is_parameterized() {
self.print_generics(generics)?;
if !generics.params.is_empty() {
self.print_generic_params(&generics.params)?;
self.s.space()?;
}
@ -725,7 +716,7 @@ impl<'a> State<'a> {
self.print_unsafety(unsafety)?;
self.word_nbsp("trait")?;
self.print_name(item.name)?;
self.print_generics(generics)?;
self.print_generic_params(&generics.params)?;
let mut real_bounds = Vec::with_capacity(bounds.len());
for b in bounds.iter() {
if let TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
@ -750,7 +741,7 @@ impl<'a> State<'a> {
self.print_visibility(&item.vis)?;
self.word_nbsp("trait")?;
self.print_name(item.name)?;
self.print_generics(generics)?;
self.print_generic_params(&generics.params)?;
let mut real_bounds = Vec::with_capacity(bounds.len());
// FIXME(durka) this seems to be some quite outdated syntax
for b in bounds.iter() {
@ -775,25 +766,20 @@ impl<'a> State<'a> {
self.print_path(&t.path, false)
}
fn print_formal_lifetime_list(&mut self, lifetimes: &[hir::LifetimeDef]) -> io::Result<()> {
if !lifetimes.is_empty() {
self.s.word("for<")?;
let mut comma = false;
for lifetime_def in lifetimes {
if comma {
self.word_space(",")?
}
self.print_lifetime_def(lifetime_def)?;
comma = true;
}
self.s.word(">")?;
fn print_formal_generic_params(
&mut self,
generic_params: &[hir::GenericParam]
) -> io::Result<()> {
if !generic_params.is_empty() {
self.s.word("for")?;
self.print_generic_params(generic_params)?;
self.nbsp()?;
}
Ok(())
}
fn print_poly_trait_ref(&mut self, t: &hir::PolyTraitRef) -> io::Result<()> {
self.print_formal_lifetime_list(&t.bound_lifetimes)?;
self.print_formal_generic_params(&t.bound_generic_params)?;
self.print_trait_ref(&t.trait_ref)
}
@ -806,7 +792,7 @@ impl<'a> State<'a> {
-> io::Result<()> {
self.head(&visibility_qualified(visibility, "enum"))?;
self.print_name(name)?;
self.print_generics(generics)?;
self.print_generic_params(&generics.params)?;
self.print_where_clause(&generics.where_clause)?;
self.s.space()?;
self.print_variants(&enum_definition.variants, span)
@ -859,7 +845,7 @@ impl<'a> State<'a> {
print_finalizer: bool)
-> io::Result<()> {
self.print_name(name)?;
self.print_generics(generics)?;
self.print_generic_params(&generics.params)?;
if !struct_def.is_struct() {
if struct_def.is_tuple() {
self.popen()?;
@ -1941,7 +1927,7 @@ impl<'a> State<'a> {
self.nbsp()?;
self.print_name(name)?;
}
self.print_generics(generics)?;
self.print_generic_params(&generics.params)?;
self.popen()?;
let mut i = 0;
@ -2056,31 +2042,19 @@ impl<'a> State<'a> {
Ok(())
}
pub fn print_generics(&mut self, generics: &hir::Generics) -> io::Result<()> {
let total = generics.lifetimes.len() + generics.ty_params.len();
if total == 0 {
return Ok(());
}
pub fn print_generic_params(&mut self, generic_params: &[hir::GenericParam]) -> io::Result<()> {
if !generic_params.is_empty() {
self.s.word("<")?;
let mut ints = Vec::new();
for i in 0..total {
ints.push(i);
}
self.commasep(Inconsistent, &ints[..], |s, &idx| {
if idx < generics.lifetimes.len() {
let lifetime = &generics.lifetimes[idx];
s.print_lifetime_def(lifetime)
} else {
let idx = idx - generics.lifetimes.len();
let param = &generics.ty_params[idx];
s.print_ty_param(param)
self.commasep(Inconsistent, generic_params, |s, param| {
match *param {
hir::GenericParam::Lifetime(ref ld) => s.print_lifetime_def(ld),
hir::GenericParam::Type(ref tp) => s.print_ty_param(tp),
}
})?;
self.s.word(">")?;
}
Ok(())
}
@ -2111,11 +2085,13 @@ impl<'a> State<'a> {
}
match predicate {
&hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate{ref bound_lifetimes,
&hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
ref bound_generic_params,
ref bounded_ty,
ref bounds,
..}) => {
self.print_formal_lifetime_list(bound_lifetimes)?;
..
}) => {
self.print_formal_generic_params(bound_generic_params)?;
self.print_type(&bounded_ty)?;
self.print_bounds(":", bounds)?;
}
@ -2184,17 +2160,16 @@ impl<'a> State<'a> {
unsafety: hir::Unsafety,
decl: &hir::FnDecl,
name: Option<ast::Name>,
generics: &hir::Generics,
generic_params: &[hir::GenericParam],
arg_names: &[Spanned<ast::Name>])
-> io::Result<()> {
self.ibox(indent_unit)?;
if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() {
if !generic_params.is_empty() {
self.s.word("for")?;
self.print_generics(generics)?;
self.print_generic_params(generic_params)?;
}
let generics = hir::Generics {
lifetimes: hir::HirVec::new(),
ty_params: hir::HirVec::new(),
params: hir::HirVec::new(),
where_clause: hir::WhereClause {
id: ast::DUMMY_NODE_ID,
predicates: hir::HirVec::new(),

View file

@ -200,9 +200,13 @@ impl_stable_hash_for!(struct hir::TyParam {
synthetic
});
impl_stable_hash_for!(enum hir::GenericParam {
Lifetime(lifetime_def),
Type(ty_param)
});
impl_stable_hash_for!(struct hir::Generics {
lifetimes,
ty_params,
params,
where_clause,
span
});
@ -224,7 +228,7 @@ impl_stable_hash_for!(enum hir::WherePredicate {
impl_stable_hash_for!(struct hir::WhereBoundPredicate {
span,
bound_lifetimes,
bound_generic_params,
bounded_ty,
bounds
});
@ -291,7 +295,7 @@ impl_stable_hash_for!(enum hir::PrimTy {
impl_stable_hash_for!(struct hir::BareFnTy {
unsafety,
abi,
lifetimes,
generic_params,
decl,
arg_names
});
@ -345,7 +349,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::TraitRef {
impl_stable_hash_for!(struct hir::PolyTraitRef {
bound_lifetimes,
bound_generic_params,
trait_ref,
span
});

View file

@ -783,6 +783,11 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
hir_visit::walk_decl(self, d);
}
fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam) {
run_lints!(self, check_generic_param, late_passes, p);
hir_visit::walk_generic_param(self, p);
}
fn visit_generics(&mut self, g: &'tcx hir::Generics) {
run_lints!(self, check_generics, late_passes, g);
hir_visit::walk_generics(self, g);
@ -819,11 +824,6 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
hir_visit::walk_lifetime(self, lt);
}
fn visit_lifetime_def(&mut self, lt: &'tcx hir::LifetimeDef) {
run_lints!(self, check_lifetime_def, late_passes, lt);
hir_visit::walk_lifetime_def(self, lt);
}
fn visit_path(&mut self, p: &'tcx hir::Path, id: ast::NodeId) {
run_lints!(self, check_path, late_passes, p, id);
hir_visit::walk_path(self, p);
@ -945,6 +945,11 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> {
run_lints!(self, check_expr_post, early_passes, e);
}
fn visit_generic_param(&mut self, param: &'a ast::GenericParam) {
run_lints!(self, check_generic_param, early_passes, param);
ast_visit::walk_generic_param(self, param);
}
fn visit_generics(&mut self, g: &'a ast::Generics) {
run_lints!(self, check_generics, early_passes, g);
ast_visit::walk_generics(self, g);
@ -971,10 +976,6 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> {
self.check_id(lt.id);
}
fn visit_lifetime_def(&mut self, lt: &'a ast::LifetimeDef) {
run_lints!(self, check_lifetime_def, early_passes, lt);
}
fn visit_path(&mut self, p: &'a ast::Path, id: ast::NodeId) {
run_lints!(self, check_path, early_passes, p, id);
self.check_id(id);

View file

@ -155,6 +155,7 @@ pub trait LateLintPass<'a, 'tcx>: LintPass {
fn check_expr(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Expr) { }
fn check_expr_post(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Expr) { }
fn check_ty(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Ty) { }
fn check_generic_param(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::GenericParam) { }
fn check_generics(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Generics) { }
fn check_fn(&mut self,
_: &LateContext<'a, 'tcx>,
@ -196,7 +197,6 @@ pub trait LateLintPass<'a, 'tcx>: LintPass {
_: &'tcx hir::Variant,
_: &'tcx hir::Generics) { }
fn check_lifetime(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Lifetime) { }
fn check_lifetime_def(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::LifetimeDef) { }
fn check_path(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Path, _: ast::NodeId) { }
fn check_attribute(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx ast::Attribute) { }
@ -227,6 +227,7 @@ pub trait EarlyLintPass: LintPass {
fn check_expr(&mut self, _: &EarlyContext, _: &ast::Expr) { }
fn check_expr_post(&mut self, _: &EarlyContext, _: &ast::Expr) { }
fn check_ty(&mut self, _: &EarlyContext, _: &ast::Ty) { }
fn check_generic_param(&mut self, _: &EarlyContext, _: &ast::GenericParam) { }
fn check_generics(&mut self, _: &EarlyContext, _: &ast::Generics) { }
fn check_fn(&mut self, _: &EarlyContext,
_: ast_visit::FnKind, _: &ast::FnDecl, _: Span, _: ast::NodeId) { }
@ -244,7 +245,6 @@ pub trait EarlyLintPass: LintPass {
fn check_variant(&mut self, _: &EarlyContext, _: &ast::Variant, _: &ast::Generics) { }
fn check_variant_post(&mut self, _: &EarlyContext, _: &ast::Variant, _: &ast::Generics) { }
fn check_lifetime(&mut self, _: &EarlyContext, _: &ast::Lifetime) { }
fn check_lifetime_def(&mut self, _: &EarlyContext, _: &ast::LifetimeDef) { }
fn check_path(&mut self, _: &EarlyContext, _: &ast::Path, _: ast::NodeId) { }
fn check_attribute(&mut self, _: &EarlyContext, _: &ast::Attribute) { }

View file

@ -37,7 +37,7 @@ use hir::intravisit;
// Returns true if the given set of generics implies that the item it's
// associated with must be inlined.
fn generics_require_inlining(generics: &hir::Generics) -> bool {
!generics.ty_params.is_empty()
generics.params.iter().any(|param| param.is_type_param())
}
// Returns true if the given item must be inlined because it may be

View file

@ -33,7 +33,7 @@ use util::nodemap::{DefIdMap, FxHashMap, FxHashSet, NodeMap, NodeSet};
use std::slice;
use rustc::lint;
use hir;
use hir::{self, GenericParamsExt};
use hir::intravisit::{self, NestedVisitorMap, Visitor};
/// The origin of a named lifetime definition.
@ -491,19 +491,17 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
} else {
0
};
let lifetimes = generics
.lifetimes
.iter()
let lifetimes = generics.lifetimes()
.map(|def| Region::early(&self.tcx.hir, &mut index, def))
.collect();
let next_early_index = index + generics.ty_params.len() as u32;
let next_early_index = index + generics.ty_params().count() as u32;
let scope = Scope::Binder {
lifetimes,
next_early_index,
s: ROOT_SCOPE,
};
self.with(scope, |old_scope, this| {
this.check_lifetime_defs(old_scope, &generics.lifetimes);
this.check_lifetime_params(old_scope, &generics.params);
intravisit::walk_item(this, item);
});
}
@ -537,8 +535,8 @@ 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.lifetimes
.iter()
lifetimes: c.generic_params
.lifetimes()
.map(|def| Region::late(&self.tcx.hir, def))
.collect(),
s: self.scope,
@ -547,7 +545,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
self.with(scope, |old_scope, this| {
// a bare fn has no bounds, so everything
// contained within is scoped within its binder.
this.check_lifetime_defs(old_scope, &c.lifetimes);
this.check_lifetime_params(old_scope, &c.generic_params);
intravisit::walk_ty(this, ty);
});
self.is_in_fn_syntax = was_in_fn_syntax;
@ -621,7 +619,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
let mut elision = None;
let mut lifetimes = FxHashMap();
for lt_def in &generics.lifetimes {
for lt_def in generics.lifetimes() {
let (lt_name, region) = Region::early(&self.tcx.hir, &mut index, &lt_def);
if let hir::LifetimeName::Underscore = lt_name {
// Pick the elided lifetime "definition" if one exists and use it to make an
@ -632,7 +630,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
}
let next_early_index = index + generics.ty_params.len() as u32;
let next_early_index = index + generics.ty_params().count() as u32;
if let Some(elision_region) = elision {
let scope = Scope::Elision {
@ -678,11 +676,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
let generics = &trait_item.generics;
let mut index = self.next_early_index();
debug!("visit_ty: index = {}", index);
let lifetimes = generics.lifetimes.iter()
let lifetimes = generics.lifetimes()
.map(|lt_def| Region::early(&self.tcx.hir, &mut index, lt_def))
.collect();
let next_early_index = index + generics.ty_params.len() as u32;
let next_early_index = index + generics.ty_params().count() as u32;
let scope = Scope::Binder { lifetimes, next_early_index, s: self.scope };
self.with(scope, |_old_scope, this| {
this.visit_generics(generics);
@ -696,7 +694,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
},
Const(_, _) => {
// Only methods and types support generics.
assert!(!trait_item.generics.is_parameterized());
assert!(trait_item.generics.params.is_empty());
intravisit::walk_trait_item(self, trait_item);
},
}
@ -718,11 +716,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
let generics = &impl_item.generics;
let mut index = self.next_early_index();
debug!("visit_ty: index = {}", index);
let lifetimes = generics.lifetimes.iter()
let lifetimes = generics.lifetimes()
.map(|lt_def| Region::early(&self.tcx.hir, &mut index, lt_def))
.collect();
let next_early_index = index + generics.ty_params.len() as u32;
let next_early_index = index + generics.ty_params().count() as u32;
let scope = Scope::Binder { lifetimes, next_early_index, s: self.scope };
self.with(scope, |_old_scope, this| {
this.visit_generics(generics);
@ -731,7 +729,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
},
Const(_, _) => {
// Only methods and types support generics.
assert!(!impl_item.generics.is_parameterized());
assert!(impl_item.generics.params.is_empty());
intravisit::walk_impl_item(self, impl_item);
},
}
@ -767,8 +765,11 @@ 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.lifetimes);
for ty_param in generics.ty_params.iter() {
check_mixed_explicit_and_in_band_defs(
self.tcx,
&generics.lifetimes().cloned().collect::<Vec<_>>()
);
for ty_param in generics.ty_params() {
walk_list!(self, visit_ty_param_bound, &ty_param.bounds);
if let Some(ref ty) = ty_param.default {
self.visit_ty(&ty);
@ -779,22 +780,21 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
&hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
ref bounded_ty,
ref bounds,
ref bound_lifetimes,
ref bound_generic_params,
..
}) => {
if !bound_lifetimes.is_empty() {
if bound_generic_params.iter().any(|p| p.is_lifetime_param()) {
self.trait_ref_hack = true;
let next_early_index = self.next_early_index();
let scope = Scope::Binder {
lifetimes: bound_lifetimes
.iter()
lifetimes: bound_generic_params.lifetimes()
.map(|def| Region::late(&self.tcx.hir, def))
.collect(),
s: self.scope,
next_early_index,
};
let result = self.with(scope, |old_scope, this| {
this.check_lifetime_defs(old_scope, bound_lifetimes);
this.check_lifetime_params(old_scope, &bound_generic_params);
this.visit_ty(&bounded_ty);
walk_list!(this, visit_ty_param_bound, bounds);
});
@ -834,7 +834,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
) {
debug!("visit_poly_trait_ref trait_ref={:?}", trait_ref);
if !self.trait_ref_hack || !trait_ref.bound_lifetimes.is_empty() {
if !self.trait_ref_hack ||
trait_ref.bound_generic_params.iter().any(|p| p.is_lifetime_param())
{
if self.trait_ref_hack {
span_err!(
self.tcx.sess,
@ -845,19 +847,16 @@ 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_lifetimes
.iter()
lifetimes: trait_ref.bound_generic_params
.lifetimes()
.map(|def| Region::late(&self.tcx.hir, def))
.collect(),
s: self.scope,
next_early_index,
};
self.with(scope, |old_scope, this| {
this.check_lifetime_defs(old_scope, &trait_ref.bound_lifetimes);
for lifetime in &trait_ref.bound_lifetimes {
this.visit_lifetime_def(lifetime);
}
this.check_lifetime_params(old_scope, &trait_ref.bound_generic_params);
walk_list!(this, visit_generic_param, &trait_ref.bound_generic_params);
this.visit_trait_ref(&trait_ref.trait_ref)
})
} else {
@ -1087,8 +1086,9 @@ fn compute_object_lifetime_defaults(
.map(|set| match *set {
Set1::Empty => "BaseDefault".to_string(),
Set1::One(Region::Static) => "'static".to_string(),
Set1::One(Region::EarlyBound(i, _, _)) => generics.lifetimes
[i as usize]
Set1::One(Region::EarlyBound(i, _, _)) => generics.lifetimes()
.nth(i as usize)
.unwrap()
.lifetime
.name
.name()
@ -1124,9 +1124,7 @@ fn object_lifetime_defaults_for_item(
}
}
generics
.ty_params
.iter()
generics.ty_params()
.map(|param| {
let mut set = Set1::Empty;
@ -1142,7 +1140,7 @@ fn object_lifetime_defaults_for_item(
// Ignore `for<'a> type: ...` as they can change what
// lifetimes mean (although we could "just" handle it).
if !data.bound_lifetimes.is_empty() {
if !data.bound_generic_params.is_empty() {
continue;
}
@ -1163,8 +1161,7 @@ fn object_lifetime_defaults_for_item(
Set1::One(Region::Static)
} else {
generics
.lifetimes
.iter()
.lifetimes()
.enumerate()
.find(|&(_, def)| def.lifetime.name == name)
.map_or(Set1::Many, |(i, def)| {
@ -1283,15 +1280,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
match parent.node {
hir::ItemTrait(_, _, ref generics, ..)
| hir::ItemImpl(_, _, _, ref generics, ..) => {
index += (generics.lifetimes.len() + generics.ty_params.len()) as u32;
index += generics.params.len() as u32;
}
_ => {}
}
}
let lifetimes = generics
.lifetimes
.iter()
.lifetimes()
.map(|def| {
if self.map.late_bound.contains(&def.lifetime.id) {
Region::late(&self.tcx.hir, def)
@ -1301,7 +1297,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
})
.collect();
let next_early_index = index + generics.ty_params.len() as u32;
let next_early_index = index + generics.ty_params().count() as u32;
let scope = Scope::Binder {
lifetimes,
@ -1309,7 +1305,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
s: self.scope,
};
self.with(scope, move |old_scope, this| {
this.check_lifetime_defs(old_scope, &generics.lifetimes);
this.check_lifetime_params(old_scope, &generics.params);
this.hack(walk); // FIXME(#37666) workaround in place of `walk(this)`
});
}
@ -1769,6 +1765,16 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
}
}
fn visit_generic_param(&mut self, param: &hir::GenericParam) {
if let hir::GenericParam::Lifetime(ref lifetime_def) = *param {
for l in &lifetime_def.bounds {
self.visit_lifetime(l);
}
}
intravisit::walk_generic_param(self, param);
}
fn visit_poly_trait_ref(
&mut self,
trait_ref: &hir::PolyTraitRef,
@ -1779,12 +1785,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
self.binder_depth -= 1;
}
fn visit_lifetime_def(&mut self, lifetime_def: &hir::LifetimeDef) {
for l in &lifetime_def.bounds {
self.visit_lifetime(l);
}
}
fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) {
if let Some(&lifetime) = self.map.defs.get(&lifetime_ref.id) {
match lifetime {
@ -1980,11 +1980,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
self.insert_lifetime(lifetime_ref, lifetime.shifted(late_depth));
}
fn check_lifetime_defs(&mut self, old_scope: ScopeRef, lifetimes: &'tcx [hir::LifetimeDef]) {
for i in 0..lifetimes.len() {
let lifetime_i = &lifetimes[i];
for lifetime in lifetimes {
fn check_lifetime_params(&mut self, old_scope: ScopeRef, params: &'tcx [hir::GenericParam]) {
for (i, lifetime_i) in params.lifetimes().enumerate() {
for lifetime in params.lifetimes() {
match lifetime.lifetime.name {
hir::LifetimeName::Static | hir::LifetimeName::Underscore => {
let lifetime = lifetime.lifetime;
@ -2007,9 +2005,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
}
// It is a hard error to shadow a lifetime within the same scope.
for j in i + 1..lifetimes.len() {
let lifetime_j = &lifetimes[j];
for lifetime_j in params.lifetimes().skip(i + 1) {
if lifetime_i.lifetime.name == lifetime_j.lifetime.name {
struct_span_err!(
self.tcx.sess,
@ -2200,24 +2196,30 @@ fn insert_late_bound_lifetimes(
let mut appears_in_where_clause = AllCollector {
regions: FxHashSet(),
};
for ty_param in generics.ty_params.iter() {
for param in &generics.params {
match *param {
hir::GenericParam::Lifetime(ref lifetime_def) => {
if !lifetime_def.bounds.is_empty() {
// `'a: 'b` means both `'a` and `'b` are referenced
appears_in_where_clause.visit_generic_param(param);
}
}
hir::GenericParam::Type(ref ty_param) => {
walk_list!(
&mut appears_in_where_clause,
visit_ty_param_bound,
&ty_param.bounds
);
}
}
}
walk_list!(
&mut appears_in_where_clause,
visit_where_predicate,
&generics.where_clause.predicates
);
for lifetime_def in &generics.lifetimes {
if !lifetime_def.bounds.is_empty() {
// `'a: 'b` means both `'a` and `'b` are referenced
appears_in_where_clause.visit_lifetime_def(lifetime_def);
}
}
debug!(
"insert_late_bound_lifetimes: appears_in_where_clause={:?}",
@ -2228,7 +2230,7 @@ fn insert_late_bound_lifetimes(
// - appear in the inputs
// - do not appear in the where-clauses
// - are not implicitly captured by `impl Trait`
for lifetime in &generics.lifetimes {
for lifetime in generics.lifetimes() {
let name = lifetime.lifetime.name;
// appears in the where clauses? early-bound.

View file

@ -126,8 +126,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCamelCaseTypes {
self.check_case(cx, "variant", v.node.name, v.span);
}
fn check_generics(&mut self, cx: &LateContext, it: &hir::Generics) {
for gen in it.ty_params.iter() {
fn check_generic_param(&mut self, cx: &LateContext, param: &hir::GenericParam) {
if let hir::GenericParam::Type(ref gen) = *param {
self.check_case(cx, "type parameter", gen.name, gen.span);
}
}
@ -232,6 +232,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase {
}
}
fn check_generic_param(&mut self, cx: &LateContext, param: &hir::GenericParam) {
if let hir::GenericParam::Lifetime(ref ld) = *param {
self.check_snake_case(
cx,
"lifetime",
&ld.lifetime.name.name().as_str(),
Some(ld.lifetime.span)
);
}
}
fn check_fn(&mut self,
cx: &LateContext,
fk: FnKind,
@ -280,13 +291,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase {
}
}
fn check_lifetime_def(&mut self, cx: &LateContext, t: &hir::LifetimeDef) {
self.check_snake_case(cx,
"lifetime",
&t.lifetime.name.name().as_str(),
Some(t.lifetime.span));
}
fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
if let &PatKind::Binding(_, _, ref path1, _) = &p.node {
self.check_snake_case(cx, "variable", &path1.node.as_str(), Some(p.span));

View file

@ -507,21 +507,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingCopyImplementations {
}
let (def, ty) = match item.node {
hir::ItemStruct(_, ref ast_generics) => {
if ast_generics.is_parameterized() {
if !ast_generics.params.is_empty() {
return;
}
let def = cx.tcx.adt_def(cx.tcx.hir.local_def_id(item.id));
(def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
}
hir::ItemUnion(_, ref ast_generics) => {
if ast_generics.is_parameterized() {
if !ast_generics.params.is_empty() {
return;
}
let def = cx.tcx.adt_def(cx.tcx.hir.local_def_id(item.id));
(def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
}
hir::ItemEnum(_, ref ast_generics) => {
if ast_generics.is_parameterized() {
if !ast_generics.params.is_empty() {
return;
}
let def = cx.tcx.adt_def(cx.tcx.hir.local_def_id(item.id));

View file

@ -744,7 +744,7 @@ impl LintPass for VariantSizeDifferences {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
if let hir::ItemEnum(ref enum_definition, ref gens) = it.node {
if gens.ty_params.is_empty() {
if gens.params.iter().all(|param| param.is_lifetime_param()) {
// sizes only make sense for non-generic types
let item_def_id = cx.tcx.hir.local_def_id(it.id);
let t = cx.tcx.type_of(item_def_id);

View file

@ -1078,8 +1078,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
}
hir::ItemConst(..) => self.encode_optimized_mir(def_id),
hir::ItemFn(_, _, constness, _, ref generics, _) => {
let tps_len = generics.ty_params.len();
let needs_inline = tps_len > 0 || attr::requests_inline(&item.attrs);
let has_tps = generics.ty_params().next().is_some();
let needs_inline = has_tps || attr::requests_inline(&item.attrs);
let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
if needs_inline || constness == hir::Constness::Const || always_encode_mir {
self.encode_optimized_mir(def_id)
@ -1480,7 +1480,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
}
fn encode_info_for_generics(&mut self, generics: &hir::Generics) {
for ty_param in &generics.ty_params {
for ty_param in generics.ty_params() {
let def_id = self.tcx.hir.local_def_id(ty_param.id);
let has_default = Untracked(ty_param.default.is_some());
self.record(def_id, IsolatedEncoder::encode_info_for_ty_param, (def_id, has_default));

View file

@ -922,7 +922,7 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
hir::ItemEnum(_, ref generics) |
hir::ItemStruct(_, ref generics) |
hir::ItemUnion(_, ref generics) => {
if !generics.is_parameterized() {
if generics.params.is_empty() {
if self.mode == MonoItemCollectionMode::Eager {
let def_id = self.tcx.hir.local_def_id(item.id);
debug!("RootCollector: ADT drop-glue for {}",

View file

@ -250,7 +250,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
ItemKind::Trait(is_auto, _, ref generics, ref bounds, ref trait_items) => {
if is_auto == IsAuto::Yes {
// Auto traits cannot have generics, super traits nor contain items.
if !generics.ty_params.is_empty() {
if generics.is_parameterized() {
self.err_handler().span_err(item.span,
"auto traits cannot have generics");
}
@ -283,8 +283,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
}
}
ItemKind::TraitAlias(Generics { ref ty_params, .. }, ..) => {
for &TyParam { ref bounds, ref default, span, .. } in ty_params {
ItemKind::TraitAlias(Generics { ref params, .. }, ..) => {
for param in params {
if let GenericParam::Type(TyParam {
ref bounds,
ref default,
span,
..
}) = *param
{
if !bounds.is_empty() {
self.err_handler().span_err(span,
"type parameters on the left side of a \
@ -297,6 +304,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
}
}
}
ItemKind::Mod(_) => {
// Ensure that `path` attributes on modules are recorded as used (c.f. #35584).
attr::first_attr_value_str_by_name(&item.attrs, "path");
@ -352,9 +360,21 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
fn visit_generics(&mut self, g: &'a Generics) {
let mut seen_non_lifetime_param = false;
let mut seen_default = None;
for ty_param in &g.ty_params {
if ty_param.default.is_some() {
for param in &g.params {
match (param, seen_non_lifetime_param) {
(&GenericParam::Lifetime(ref ld), true) => {
self.err_handler()
.span_err(ld.lifetime.span, "lifetime parameters must be leading");
},
(&GenericParam::Lifetime(_), false) => {}
_ => {
seen_non_lifetime_param = true;
}
}
if let GenericParam::Type(ref ty_param @ TyParam { default: Some(_), .. }) = *param {
seen_default = Some(ty_param.span);
} else if let Some(span) = seen_default {
self.err_handler()

View file

@ -224,10 +224,6 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
self.record("Lifetime", Id::Node(lifetime.id), lifetime);
hir_visit::walk_lifetime(self, lifetime)
}
fn visit_lifetime_def(&mut self, lifetime: &'v hir::LifetimeDef) {
self.record("LifetimeDef", Id::None, lifetime);
hir_visit::walk_lifetime_def(self, lifetime)
}
fn visit_qpath(&mut self, qpath: &'v hir::QPath, id: NodeId, span: Span) {
self.record("QPath", Id::None, qpath);
hir_visit::walk_qpath(self, qpath, id, span)
@ -349,11 +345,6 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
ast_visit::walk_lifetime(self, lifetime)
}
fn visit_lifetime_def(&mut self, lifetime: &'v ast::LifetimeDef) {
self.record("LifetimeDef", Id::None, lifetime);
ast_visit::walk_lifetime_def(self, lifetime)
}
fn visit_mac(&mut self, mac: &'v ast::Mac) {
self.record("Mac", Id::None, mac);
}

View file

@ -1236,7 +1236,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
}
fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
for ty_param in generics.ty_params.iter() {
for ty_param in generics.ty_params() {
for bound in ty_param.bounds.iter() {
self.check_ty_param_bound(bound)
}

View file

@ -53,7 +53,7 @@ use syntax::util::lev_distance::find_best_match_for_name;
use syntax::visit::{self, FnKind, Visitor};
use syntax::attr;
use syntax::ast::{Arm, BindingMode, Block, Crate, Expr, ExprKind};
use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, Generics};
use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, GenericParam, Generics};
use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
use syntax::ast::{Local, Mutability, Pat, PatKind, Path};
use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
@ -790,25 +790,30 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
// to following type parameters, as the Substs can only
// provide previous type parameters as they're built.
let mut default_ban_rib = Rib::new(ForwardTyParamBanRibKind);
default_ban_rib.bindings.extend(generics.ty_params.iter()
default_ban_rib.bindings.extend(generics.params.iter()
.filter_map(|p| if let GenericParam::Type(ref tp) = *p { Some(tp) } else { None })
.skip_while(|p| p.default.is_none())
.map(|p| (Ident::with_empty_ctxt(p.ident.name), Def::Err)));
for param in &generics.ty_params {
for bound in &param.bounds {
for param in &generics.params {
match *param {
GenericParam::Lifetime(_) => self.visit_generic_param(param),
GenericParam::Type(ref ty_param) => {
for bound in &ty_param.bounds {
self.visit_ty_param_bound(bound);
}
if let Some(ref ty) = param.default {
if let Some(ref ty) = ty_param.default {
self.ribs[TypeNS].push(default_ban_rib);
self.visit_ty(ty);
default_ban_rib = self.ribs[TypeNS].pop().unwrap();
}
// Allow all following defaults to refer to this type parameter.
default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(param.ident.name));
default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(ty_param.ident.name));
}
}
}
for lt in &generics.lifetimes { self.visit_lifetime_def(lt); }
for p in &generics.where_clause.predicates { self.visit_where_predicate(p); }
}
}
@ -2022,14 +2027,17 @@ impl<'a> Resolver<'a> {
HasTypeParameters(generics, rib_kind) => {
let mut function_type_rib = Rib::new(rib_kind);
let mut seen_bindings = FxHashMap();
for type_parameter in &generics.ty_params {
for param in &generics.params {
if let GenericParam::Type(ref type_parameter) = *param {
let ident = type_parameter.ident.modern();
debug!("with_type_parameter_rib: {}", type_parameter.id);
if seen_bindings.contains_key(&ident) {
let span = seen_bindings.get(&ident).unwrap();
let err =
ResolutionError::NameAlreadyUsedInTypeParameterList(ident.name, span);
let err = ResolutionError::NameAlreadyUsedInTypeParameterList(
ident.name,
span,
);
resolve_error(self, type_parameter.span, err);
}
seen_bindings.entry(ident).or_insert(type_parameter.span);
@ -2040,6 +2048,7 @@ impl<'a> Resolver<'a> {
function_type_rib.bindings.insert(ident, def);
self.record_def(type_parameter.id, PathResolution::new(def));
}
}
self.ribs[TypeNS].push(function_type_rib);
}

View file

@ -36,7 +36,12 @@ use syntax::ast::{self, Attribute, NodeId, PatKind, CRATE_NODE_ID};
use syntax::parse::token;
use syntax::symbol::keywords;
use syntax::visit::{self, Visitor};
use syntax::print::pprust::{bounds_to_string, generics_to_string, path_to_string, ty_to_string};
use syntax::print::pprust::{
bounds_to_string,
generic_params_to_string,
path_to_string,
ty_to_string
};
use syntax::ptr::P;
use syntax::codemap::{Spanned, DUMMY_SP};
use syntax_pos::*;
@ -438,13 +443,14 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
prefix: &str,
id: NodeId,
) {
for param in &generics.ty_params {
let param_ss = param.span;
for param in &generics.params {
if let ast::GenericParam::Type(ref ty_param) = *param {
let param_ss = ty_param.span;
let name = escape(self.span.snippet(param_ss));
// Append $id to name to make sure each one is unique
let qualname = format!("{}::{}${}", prefix, name, id);
if !self.span.filter_generated(Some(param_ss), full_span) {
let id = ::id_from_node_id(param.id, &self.save_ctxt);
let id = ::id_from_node_id(ty_param.id, &self.save_ctxt);
let span = self.span_from_span(param_ss);
self.dumper.dump_def(
@ -469,6 +475,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
);
}
}
}
self.visit_generics(generics);
}
@ -787,8 +794,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
let name = item.ident.to_string();
let qualname = format!("::{}", self.tcx.node_path_str(item.id));
let mut val = name.clone();
if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() {
val.push_str(&generics_to_string(generics));
if !generics.params.is_empty() {
val.push_str(&generic_params_to_string(&generics.params));
}
if !trait_refs.is_empty() {
val.push_str(": ");
@ -1478,17 +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.ty_params.iter() {
for bound in param.bounds.iter() {
for param in &generics.params {
if let ast::GenericParam::Type(ref ty_param) = *param {
for bound in ty_param.bounds.iter() {
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) = param.default {
if let Some(ref ty) = ty_param.default {
self.visit_ty(&ty);
}
}
}
}
fn visit_ty(&mut self, t: &'l ast::Ty) {
self.process_macro_use(t.span);

View file

@ -886,21 +886,15 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String {
let mut sig = "fn ".to_owned();
if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() {
if !generics.params.is_empty() {
sig.push('<');
sig.push_str(&generics
.lifetimes
.params
.iter()
.map(|l| l.lifetime.ident.name.to_string())
.collect::<Vec<_>>()
.join(", "));
if !generics.lifetimes.is_empty() {
sig.push_str(", ");
}
sig.push_str(&generics
.ty_params
.iter()
.map(|l| l.ident.to_string())
.map(|param| match *param {
ast::GenericParam::Lifetime(ref l) => l.lifetime.ident.name.to_string(),
ast::GenericParam::Type(ref t) => t.ident.to_string(),
})
.collect::<Vec<_>>()
.join(", "));
sig.push_str("> ");

View file

@ -218,12 +218,17 @@ impl Sig for ast::Ty {
}
ast::TyKind::BareFn(ref f) => {
let mut text = String::new();
if !f.lifetimes.is_empty() {
if !f.generic_params.is_empty() {
// FIXME defs, bounds on lifetimes
text.push_str("for<");
text.push_str(&f.lifetimes
text.push_str(&f.generic_params
.iter()
.map(|l| l.lifetime.ident.to_string())
.filter_map(|p| match *p {
ast::GenericParam::Lifetime(ref l) => {
Some(l.lifetime.ident.to_string())
}
_ => None,
})
.collect::<Vec<_>>()
.join(", "));
text.push('>');
@ -615,15 +620,16 @@ impl Sig for ast::Path {
// This does not cover the where clause, which must be processed separately.
impl Sig for ast::Generics {
fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) -> Result {
let total = self.lifetimes.len() + self.ty_params.len();
if total == 0 {
if self.params.is_empty() {
return Ok(text_sig(String::new()));
}
let mut text = "<".to_owned();
let mut defs = vec![];
for l in &self.lifetimes {
for param in &self.params {
match *param {
ast::GenericParam::Lifetime(ref l) => {
let mut l_text = l.lifetime.ident.to_string();
defs.push(SigElement {
id: id_from_node_id(l.lifetime.id, scx),
@ -644,7 +650,7 @@ impl Sig for ast::Generics {
text.push_str(&l_text);
text.push(',');
}
for t in &self.ty_params {
ast::GenericParam::Type(ref t) => {
let mut t_text = t.ident.to_string();
defs.push(SigElement {
id: id_from_node_id(t.id, scx),
@ -660,6 +666,8 @@ impl Sig for ast::Generics {
text.push_str(&t_text);
text.push(',');
}
}
}
text.push('>');
Ok(Signature {

View file

@ -562,10 +562,10 @@ fn compare_number_of_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
if num_impl_m_type_params != num_trait_m_type_params {
let impl_m_node_id = tcx.hir.as_local_node_id(impl_m.def_id).unwrap();
let impl_m_item = tcx.hir.expect_impl_item(impl_m_node_id);
let span = if impl_m_item.generics.is_parameterized() {
impl_m_item.generics.span
} else {
let span = if impl_m_item.generics.params.is_empty() {
impl_m_span
} else {
impl_m_item.generics.span
};
let mut err = struct_span_err!(tcx.sess,

View file

@ -4949,16 +4949,18 @@ pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
generics: &hir::Generics,
ty: Ty<'tcx>) {
debug!("check_bounds_are_used(n_tps={}, ty={:?})",
generics.ty_params.len(), ty);
generics.ty_params().count(), ty);
// make a vector of booleans initially false, set to true when used
if generics.ty_params.is_empty() { return; }
let mut tps_used = vec![false; generics.ty_params.len()];
if generics.ty_params().next().is_none() { return; }
let mut tps_used = vec![false; generics.ty_params().count()];
let lifetime_count = generics.lifetimes().count();
for leaf_ty in ty.walk() {
if let ty::TyParam(ParamTy {idx, ..}) = leaf_ty.sty {
debug!("Found use of ty param num {}", idx);
tps_used[idx as usize - generics.lifetimes.len()] = true;
tps_used[idx as usize - lifetime_count] = true;
} else if let ty::TyError = leaf_ty.sty {
// If there already another error, do not emit an error for not using a type Parameter
assert!(tcx.sess.err_count() > 0);
@ -4966,7 +4968,7 @@ pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
}
for (&used, param) in tps_used.iter().zip(&generics.ty_params) {
for (&used, param) in tps_used.iter().zip(generics.ty_params()) {
if !used {
struct_span_err!(tcx.sess, param.span, E0091,
"type parameter `{}` is unused",

View file

@ -592,13 +592,9 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
continue;
}
let (span, name) = if index < ast_generics.lifetimes.len() {
(ast_generics.lifetimes[index].lifetime.span,
ast_generics.lifetimes[index].lifetime.name.name())
} else {
let index = index - ast_generics.lifetimes.len();
(ast_generics.ty_params[index].span,
ast_generics.ty_params[index].name)
let (span, name) = match ast_generics.params[index] {
hir::GenericParam::Lifetime(ref ld) => (ld.lifetime.span, ld.lifetime.name.name()),
hir::GenericParam::Type(ref tp) => (tp.span, tp.name),
};
self.report_bivariance(span, name);
}

View file

@ -111,7 +111,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> {
}
fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
for param in &generics.ty_params {
for param in generics.ty_params() {
if param.default.is_some() {
let def_id = self.tcx.hir.local_def_id(param.id);
self.tcx.type_of(def_id);
@ -315,8 +315,7 @@ impl<'a, 'tcx> ItemCtxt<'a, 'tcx> {
-> Vec<ty::Predicate<'tcx>>
{
let from_ty_params =
ast_generics.ty_params
.iter()
ast_generics.ty_params()
.filter(|p| p.id == param_id)
.flat_map(|p| p.bounds.iter())
.flat_map(|b| predicates_from_bound(self, ty, b));
@ -365,7 +364,7 @@ fn ensure_no_ty_param_bounds(tcx: TyCtxt,
thing: &'static str) {
let mut warn = false;
for ty_param in generics.ty_params.iter() {
for ty_param in generics.ty_params() {
for bound in ty_param.bounds.iter() {
match *bound {
hir::TraitTyParamBound(..) => {
@ -804,7 +803,7 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let mut visitor = LateBoundRegionsDetector {
tcx, binder_depth: 1, has_late_bound_regions: None
};
for lifetime in &generics.lifetimes {
for lifetime in generics.lifetimes() {
let hir_id = tcx.hir.node_to_hir_id(lifetime.lifetime.id);
if tcx.is_late_bound(hir_id) {
return Some(lifetime.lifetime.span);
@ -964,7 +963,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// Now create the real type parameters.
let type_start = own_start + regions.len() as u32;
let types = ast_generics.ty_params.iter().enumerate().map(|(i, p)| {
let types = ast_generics.ty_params().enumerate().map(|(i, p)| {
if p.name == keywords::SelfType.name() {
span_bug!(p.span, "`Self` should not be the name of a regular parameter");
}
@ -1359,8 +1358,7 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx>(
-> impl Iterator<Item=&'a hir::LifetimeDef>
{
ast_generics
.lifetimes
.iter()
.lifetimes()
.filter(move |l| {
let hir_id = tcx.hir.node_to_hir_id(l.lifetime.id);
!tcx.is_late_bound(hir_id)
@ -1492,7 +1490,7 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// Collect the predicates that were written inline by the user on each
// type parameter (e.g., `<T:Foo>`).
for param in &ast_generics.ty_params {
for param in ast_generics.ty_params() {
let param_ty = ty::ParamTy::new(index, param.name).to_ty(tcx);
index += 1;

View file

@ -105,7 +105,7 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
tcx, &impl_predicates.predicates.as_slice(), impl_trait_ref, &mut input_parameters);
// Disallow ANY unconstrained type parameters.
for (ty_param, param) in impl_generics.types.iter().zip(&impl_hir_generics.ty_params) {
for (ty_param, param) in impl_generics.types.iter().zip(impl_hir_generics.ty_params()) {
let param_ty = ty::ParamTy::for_def(ty_param);
if !input_parameters.contains(&ctp::Parameter::from(param_ty)) {
report_unused_parameter(tcx, param.span, "type", &param_ty.to_string());
@ -123,7 +123,7 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
ctp::parameters_for(&tcx.type_of(def_id), true)
}).collect();
for (ty_lifetime, lifetime) in impl_generics.regions.iter()
.zip(&impl_hir_generics.lifetimes)
.zip(impl_hir_generics.lifetimes())
{
let param = ctp::Parameter::from(ty_lifetime.to_early_bound_region_data());

View file

@ -186,7 +186,7 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
Some(hir_map::NodeItem(it)) => {
match it.node {
hir::ItemFn(.., ref generics, _) => {
if generics.is_parameterized() {
if !generics.params.is_empty() {
struct_span_err!(tcx.sess, generics.span, E0131,
"main function is not allowed to have type parameters")
.span_label(generics.span,
@ -235,7 +235,7 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
Some(hir_map::NodeItem(it)) => {
match it.node {
hir::ItemFn(..,ref ps,_)
if ps.is_parameterized() => {
if !ps.params.is_empty() => {
struct_span_err!(tcx.sess, ps.span, E0132,
"start function is not allowed to have type parameters")
.span_label(ps.span,

View file

@ -43,6 +43,7 @@ use rustc_typeck::hir_ty_to_ty;
use rustc::hir;
use rustc_const_math::ConstInt;
use std::default::Default;
use std::{mem, slice, vec};
use std::iter::FromIterator;
use std::rc::Rc;
@ -856,7 +857,7 @@ impl TyParamBound {
did,
is_generic: false,
},
lifetimes: vec![]
generic_params: Vec::new(),
}, hir::TraitBoundModifier::Maybe)
}
@ -951,7 +952,7 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
if let &ty::RegionKind::ReLateBound(..) = *reg {
debug!(" hit an ReLateBound {:?}", reg);
if let Some(lt) = reg.clean(cx) {
late_bounds.push(lt);
late_bounds.push(GenericParam::Lifetime(lt));
}
}
}
@ -967,7 +968,7 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
did: self.def_id,
is_generic: false,
},
lifetimes: late_bounds,
generic_params: late_bounds,
},
hir::TraitBoundModifier::None
)
@ -981,7 +982,7 @@ impl<'tcx> Clean<Option<Vec<TyParamBound>>> for Substs<'tcx> {
.map(RegionBound));
v.extend(self.types().map(|t| TraitBound(PolyTrait {
trait_: t.clean(cx),
lifetimes: vec![]
generic_params: Vec::new(),
}, hir::TraitBoundModifier::None)));
if !v.is_empty() {Some(v)} else {None}
}
@ -1186,19 +1187,31 @@ impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
}
}
// maybe use a Generic enum and use Vec<Generic>?
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
pub enum GenericParam {
Lifetime(Lifetime),
Type(TyParam),
}
impl Clean<GenericParam> for hir::GenericParam {
fn clean(&self, cx: &DocContext) -> GenericParam {
match *self {
hir::GenericParam::Lifetime(ref l) => GenericParam::Lifetime(l.clean(cx)),
hir::GenericParam::Type(ref t) => GenericParam::Type(t.clean(cx)),
}
}
}
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug, Default)]
pub struct Generics {
pub lifetimes: Vec<Lifetime>,
pub type_params: Vec<TyParam>,
pub params: Vec<GenericParam>,
pub where_predicates: Vec<WherePredicate>,
}
impl Clean<Generics> for hir::Generics {
fn clean(&self, cx: &DocContext) -> Generics {
let mut g = Generics {
lifetimes: self.lifetimes.clean(cx),
type_params: self.ty_params.clean(cx),
params: self.params.clean(cx),
where_predicates: self.where_clause.predicates.clean(cx)
};
@ -1209,14 +1222,16 @@ impl Clean<Generics> for hir::Generics {
match *where_pred {
WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds } => {
if bounds.is_empty() {
for type_params in &mut g.type_params {
if &type_params.name == name {
mem::swap(bounds, &mut type_params.bounds);
for param in &mut g.params {
if let GenericParam::Type(ref mut type_param) = *param {
if &type_param.name == name {
mem::swap(bounds, &mut type_param.bounds);
break
}
}
}
}
}
_ => continue,
}
}
@ -1283,8 +1298,16 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
// and instead see `where T: Foo + Bar + Sized + 'a`
Generics {
type_params: simplify::ty_params(stripped_typarams),
lifetimes: gens.regions.clean(cx),
params: gens.regions
.clean(cx)
.into_iter()
.map(|lp| GenericParam::Lifetime(lp))
.chain(
simplify::ty_params(stripped_typarams)
.into_iter()
.map(|tp| GenericParam::Type(tp))
)
.collect(),
where_predicates: simplify::where_clauses(cx, where_predicates),
}
}
@ -1538,7 +1561,7 @@ impl Clean<PolyTrait> for hir::PolyTraitRef {
fn clean(&self, cx: &DocContext) -> PolyTrait {
PolyTrait {
trait_: self.trait_ref.clean(cx),
lifetimes: self.bound_lifetimes.clean(cx)
generic_params: self.bound_generic_params.clean(cx)
}
}
}
@ -1590,11 +1613,7 @@ impl Clean<Item> for hir::ImplItem {
}
hir::ImplItemKind::Type(ref ty) => TypedefItem(Typedef {
type_: ty.clean(cx),
generics: Generics {
lifetimes: Vec::new(),
type_params: Vec::new(),
where_predicates: Vec::new()
},
generics: Generics::default(),
}, true),
};
Item {
@ -1726,8 +1745,7 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem {
TypedefItem(Typedef {
type_: cx.tcx.type_of(self.def_id).clean(cx),
generics: Generics {
lifetimes: Vec::new(),
type_params: Vec::new(),
params: Vec::new(),
where_predicates: Vec::new(),
},
}, true)
@ -1757,7 +1775,7 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem {
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
pub struct PolyTrait {
pub trait_: Type,
pub lifetimes: Vec<Lifetime>
pub generic_params: Vec<GenericParam>,
}
/// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
@ -2081,7 +2099,7 @@ impl Clean<Type> for hir::Ty {
let mut ty_substs = FxHashMap();
let mut lt_substs = FxHashMap();
provided_params.with_parameters(|provided_params| {
for (i, ty_param) in generics.ty_params.iter().enumerate() {
for (i, ty_param) in generics.ty_params().enumerate() {
let ty_param_def = Def::TyParam(cx.tcx.hir.local_def_id(ty_param.id));
if let Some(ty) = provided_params.types.get(i).cloned() {
ty_substs.insert(ty_param_def, ty.into_inner().clean(cx));
@ -2089,7 +2107,8 @@ impl Clean<Type> for hir::Ty {
ty_substs.insert(ty_param_def, default.into_inner().clean(cx));
}
}
for (i, lt_param) in generics.lifetimes.iter().enumerate() {
for (i, lt_param) in generics.lifetimes().enumerate() {
if let Some(lt) = provided_params.lifetimes.get(i).cloned() {
if !lt.is_elided() {
let lt_def_id = cx.tcx.hir.local_def_id(lt_param.lifetime.id);
@ -2197,11 +2216,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
let sig = ty.fn_sig(cx.tcx);
BareFunction(box BareFunctionDecl {
unsafety: sig.unsafety(),
generics: Generics {
lifetimes: Vec::new(),
type_params: Vec::new(),
where_predicates: Vec::new()
},
generic_params: Vec::new(),
decl: (cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), sig).clean(cx),
abi: sig.abi(),
})
@ -2253,7 +2268,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
did,
is_generic: false,
},
lifetimes: vec![]
generic_params: Vec::new(),
}, hir::TraitBoundModifier::None);
typarams.push(bound);
}
@ -2713,7 +2728,7 @@ impl Clean<Item> for doctree::Typedef {
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
pub struct BareFunctionDecl {
pub unsafety: hir::Unsafety,
pub generics: Generics,
pub generic_params: Vec<GenericParam>,
pub decl: FnDecl,
pub abi: Abi,
}
@ -2722,11 +2737,7 @@ impl Clean<BareFunctionDecl> for hir::BareFnTy {
fn clean(&self, cx: &DocContext) -> BareFunctionDecl {
BareFunctionDecl {
unsafety: self.unsafety,
generics: Generics {
lifetimes: self.lifetimes.clean(cx),
type_params: Vec::new(),
where_predicates: Vec::new()
},
generic_params: self.generic_params.clean(cx),
decl: (&*self.decl, &self.arg_names[..]).clean(cx),
abi: self.abi,
}

View file

@ -118,30 +118,11 @@ impl<'a> fmt::Display for TyParamBounds<'a> {
}
}
impl fmt::Display for clean::Generics {
impl fmt::Display for clean::GenericParam {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.lifetimes.is_empty() && self.type_params.is_empty() { return Ok(()) }
if f.alternate() {
f.write_str("<")?;
} else {
f.write_str("&lt;")?;
}
for (i, life) in self.lifetimes.iter().enumerate() {
if i > 0 {
f.write_str(", ")?;
}
write!(f, "{}", *life)?;
}
if !self.type_params.is_empty() {
if !self.lifetimes.is_empty() {
f.write_str(", ")?;
}
for (i, tp) in self.type_params.iter().enumerate() {
if i > 0 {
f.write_str(", ")?
}
match *self {
clean::GenericParam::Lifetime(ref lp) => write!(f, "{}", lp),
clean::GenericParam::Type(ref tp) => {
f.write_str(&tp.name)?;
if !tp.bounds.is_empty() {
@ -158,16 +139,23 @@ impl fmt::Display for clean::Generics {
} else {
write!(f, "&nbsp;=&nbsp;{}", ty)?;
}
};
}
}
if f.alternate() {
f.write_str(">")?;
} else {
f.write_str("&gt;")?;
}
Ok(())
}
}
}
}
impl fmt::Display for clean::Generics {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.params.is_empty() { return Ok(()) }
if f.alternate() {
write!(f, "<{:#}>", CommaSep(&self.params))
} else {
write!(f, "&lt;{}&gt;", CommaSep(&self.params))
}
}
}
impl<'a> fmt::Display for WhereClause<'a> {
@ -259,22 +247,11 @@ impl fmt::Display for clean::Lifetime {
impl fmt::Display for clean::PolyTrait {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if !self.lifetimes.is_empty() {
if !self.generic_params.is_empty() {
if f.alternate() {
f.write_str("for<")?;
write!(f, "for<{:#}> ", CommaSep(&self.generic_params))?;
} else {
f.write_str("for&lt;")?;
}
for (i, lt) in self.lifetimes.iter().enumerate() {
if i > 0 {
f.write_str(", ")?;
}
write!(f, "{}", lt)?;
}
if f.alternate() {
f.write_str("> ")?;
} else {
f.write_str("&gt; ")?;
write!(f, "for&lt;{}&gt; ", CommaSep(&self.generic_params))?;
}
}
if f.alternate() {
@ -602,12 +579,12 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt:
write!(f, "{}{:#}fn{:#}{:#}",
UnsafetySpace(decl.unsafety),
AbiSpace(decl.abi),
decl.generics,
CommaSep(&decl.generic_params),
decl.decl)
} else {
write!(f, "{}{}", UnsafetySpace(decl.unsafety), AbiSpace(decl.abi))?;
primitive_link(f, PrimitiveType::Fn, "fn")?;
write!(f, "{}{}", decl.generics, decl.decl)
write!(f, "{}{}", CommaSep(&decl.generic_params), decl.decl)
}
}
clean::Tuple(ref typs) => {

View file

@ -1424,10 +1424,12 @@ impl DocFolder for Cache {
impl<'a> Cache {
fn generics(&mut self, generics: &clean::Generics) {
for typ in &generics.type_params {
for param in &generics.params {
if let clean::GenericParam::Type(ref typ) = *param {
self.typarams.insert(typ.did, typ.name.clone());
}
}
}
}
impl Context {

View file

@ -302,32 +302,58 @@ pub struct TyParam {
pub span: Span,
}
/// Represents lifetimes and type parameters attached to a declaration
/// of a function, enum, trait, etc.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum GenericParam {
Lifetime(LifetimeDef),
Type(TyParam),
}
impl GenericParam {
pub fn is_lifetime_param(&self) -> bool {
match *self {
GenericParam::Lifetime(_) => true,
_ => false,
}
}
pub fn is_type_param(&self) -> bool {
match *self {
GenericParam::Type(_) => true,
_ => false,
}
}
}
/// Represents lifetime, type and const parameters attached to a declaration of
/// a function, enum, trait, etc.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct Generics {
pub lifetimes: Vec<LifetimeDef>,
pub ty_params: Vec<TyParam>,
pub params: Vec<GenericParam>,
pub where_clause: WhereClause,
pub span: Span,
}
impl Generics {
pub fn is_lt_parameterized(&self) -> bool {
!self.lifetimes.is_empty()
self.params.iter().any(|param| param.is_lifetime_param())
}
pub fn is_type_parameterized(&self) -> bool {
!self.ty_params.is_empty()
self.params.iter().any(|param| param.is_type_param())
}
pub fn is_parameterized(&self) -> bool {
self.is_lt_parameterized() || self.is_type_parameterized()
!self.params.is_empty()
}
pub fn span_for_name(&self, name: &str) -> Option<Span> {
for t in &self.ty_params {
for param in &self.params {
if let GenericParam::Type(ref t) = *param {
if t.ident.name == name {
return Some(t.span);
}
}
}
None
}
}
@ -336,8 +362,7 @@ impl Default for Generics {
/// Creates an instance of `Generics`.
fn default() -> Generics {
Generics {
lifetimes: Vec::new(),
ty_params: Vec::new(),
params: Vec::new(),
where_clause: WhereClause {
id: DUMMY_NODE_ID,
predicates: Vec::new(),
@ -373,8 +398,8 @@ pub enum WherePredicate {
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct WhereBoundPredicate {
pub span: Span,
/// Any lifetimes from a `for` binding
pub bound_lifetimes: Vec<LifetimeDef>,
/// Any generics from a `for` binding
pub bound_generic_params: Vec<GenericParam>,
/// The type being bounded
pub bounded_ty: P<Ty>,
/// Trait and lifetime bounds (`Clone+Send+'static`)
@ -1492,7 +1517,7 @@ impl fmt::Debug for Ty {
pub struct BareFnTy {
pub unsafety: Unsafety,
pub abi: Abi,
pub lifetimes: Vec<LifetimeDef>,
pub generic_params: Vec<GenericParam>,
pub decl: P<FnDecl>
}
@ -1851,7 +1876,7 @@ pub struct TraitRef {
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct PolyTraitRef {
/// The `'a` in `<'a> Foo<&'a T>`
pub bound_lifetimes: Vec<LifetimeDef>,
pub bound_generic_params: Vec<GenericParam>,
/// The `Foo<&'a T>` in `<'a> Foo<&'a T>`
pub trait_ref: TraitRef,
@ -1860,9 +1885,9 @@ pub struct PolyTraitRef {
}
impl PolyTraitRef {
pub fn new(lifetimes: Vec<LifetimeDef>, path: Path, span: Span) -> Self {
pub fn new(generic_params: Vec<GenericParam>, path: Path, span: Span) -> Self {
PolyTraitRef {
bound_lifetimes: lifetimes,
bound_generic_params: generic_params,
trait_ref: TraitRef { path: path, ref_id: DUMMY_NODE_ID },
span,
}

View file

@ -462,7 +462,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
fn poly_trait_ref(&self, span: Span, path: ast::Path) -> ast::PolyTraitRef {
ast::PolyTraitRef {
bound_lifetimes: Vec::new(),
bound_generic_params: Vec::new(),
trait_ref: self.trait_ref(path),
span,
}

View file

@ -1748,22 +1748,19 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
visit::walk_vis(self, vis);
}
fn visit_generics(&mut self, g: &'a ast::Generics) {
for t in &g.ty_params {
if !t.attrs.is_empty() {
gate_feature_post!(&self, generic_param_attrs, t.attrs[0].span,
"attributes on type parameter bindings are experimental");
}
}
visit::walk_generics(self, g)
fn visit_generic_param(&mut self, param: &'a ast::GenericParam) {
let (attrs, explain) = match *param {
ast::GenericParam::Lifetime(ref ld) =>
(&ld.attrs, "attributes on lifetime bindings are experimental"),
ast::GenericParam::Type(ref t) =>
(&t.attrs, "attributes on type parameter bindings are experimental"),
};
if !attrs.is_empty() {
gate_feature_post!(&self, generic_param_attrs, attrs[0].span, explain);
}
fn visit_lifetime_def(&mut self, lifetime_def: &'a ast::LifetimeDef) {
if !lifetime_def.attrs.is_empty() {
gate_feature_post!(&self, generic_param_attrs, lifetime_def.attrs[0].span,
"attributes on lifetime bindings are experimental");
}
visit::walk_lifetime_def(self, lifetime_def)
visit::walk_generic_param(self, param)
}
fn visit_lifetime(&mut self, lt: &'a ast::Lifetime) {

View file

@ -237,8 +237,12 @@ pub trait Folder : Sized {
noop_fold_ty_param(tp, self)
}
fn fold_ty_params(&mut self, tps: Vec<TyParam>) -> Vec<TyParam> {
noop_fold_ty_params(tps, self)
fn fold_generic_param(&mut self, param: GenericParam) -> GenericParam {
noop_fold_generic_param(param, self)
}
fn fold_generic_params(&mut self, params: Vec<GenericParam>) -> Vec<GenericParam> {
noop_fold_generic_params(params, self)
}
fn fold_tt(&mut self, tt: TokenTree) -> TokenTree {
@ -363,8 +367,8 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
TyKind::Rptr(fld.fold_opt_lifetime(region), fld.fold_mt(mt))
}
TyKind::BareFn(f) => {
TyKind::BareFn(f.map(|BareFnTy {lifetimes, unsafety, abi, decl}| BareFnTy {
lifetimes: fld.fold_lifetime_defs(lifetimes),
TyKind::BareFn(f.map(|BareFnTy {generic_params, unsafety, abi, decl}| BareFnTy {
generic_params: fld.fold_generic_params(generic_params),
unsafety,
abi,
decl: fld.fold_fn_decl(decl)
@ -677,8 +681,18 @@ pub fn noop_fold_ty_param<T: Folder>(tp: TyParam, fld: &mut T) -> TyParam {
}
}
pub fn noop_fold_ty_params<T: Folder>(tps: Vec<TyParam>, fld: &mut T) -> Vec<TyParam> {
tps.move_map(|tp| fld.fold_ty_param(tp))
pub fn noop_fold_generic_param<T: Folder>(param: GenericParam, fld: &mut T) -> GenericParam {
match param {
GenericParam::Lifetime(l) => GenericParam::Lifetime(fld.fold_lifetime_def(l)),
GenericParam::Type(t) => GenericParam::Type(fld.fold_ty_param(t)),
}
}
pub fn noop_fold_generic_params<T: Folder>(
params: Vec<GenericParam>,
fld: &mut T
) -> Vec<GenericParam> {
params.move_map(|p| fld.fold_generic_param(p))
}
pub fn noop_fold_lifetime<T: Folder>(l: Lifetime, fld: &mut T) -> Lifetime {
@ -716,11 +730,10 @@ pub fn noop_fold_opt_lifetime<T: Folder>(o_lt: Option<Lifetime>, fld: &mut T)
o_lt.map(|lt| fld.fold_lifetime(lt))
}
pub fn noop_fold_generics<T: Folder>(Generics {ty_params, lifetimes, where_clause, span}: Generics,
pub fn noop_fold_generics<T: Folder>(Generics { params, where_clause, span }: Generics,
fld: &mut T) -> Generics {
Generics {
ty_params: fld.fold_ty_params(ty_params),
lifetimes: fld.fold_lifetime_defs(lifetimes),
params: fld.fold_generic_params(params),
where_clause: fld.fold_where_clause(where_clause),
span: fld.new_span(span),
}
@ -744,12 +757,12 @@ pub fn noop_fold_where_predicate<T: Folder>(
fld: &mut T)
-> WherePredicate {
match pred {
ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{bound_lifetimes,
ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{bound_generic_params,
bounded_ty,
bounds,
span}) => {
ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
bound_lifetimes: fld.fold_lifetime_defs(bound_lifetimes),
bound_generic_params: fld.fold_generic_params(bound_generic_params),
bounded_ty: fld.fold_ty(bounded_ty),
bounds: bounds.move_map(|x| fld.fold_ty_param_bound(x)),
span: fld.new_span(span)
@ -806,7 +819,7 @@ pub fn noop_fold_trait_ref<T: Folder>(p: TraitRef, fld: &mut T) -> TraitRef {
pub fn noop_fold_poly_trait_ref<T: Folder>(p: PolyTraitRef, fld: &mut T) -> PolyTraitRef {
ast::PolyTraitRef {
bound_lifetimes: fld.fold_lifetime_defs(p.bound_lifetimes),
bound_generic_params: fld.fold_generic_params(p.bound_generic_params),
trait_ref: fld.fold_trait_ref(p.trait_ref),
span: fld.new_span(p.span),
}

View file

@ -905,9 +905,8 @@ mod tests {
node: ast::Constness::NotConst,
},
Abi::Rust,
ast::Generics{ // no idea on either of these:
lifetimes: Vec::new(),
ty_params: Vec::new(),
ast::Generics{
params: Vec::new(),
where_clause: ast::WhereClause {
id: ast::DUMMY_NODE_ID,
predicates: Vec::new(),

View file

@ -21,6 +21,7 @@ use ast::EnumDef;
use ast::{Expr, ExprKind, RangeLimits};
use ast::{Field, FnDecl};
use ast::{ForeignItem, ForeignItemKind, FunctionRetTy};
use ast::GenericParam;
use ast::{Ident, ImplItem, IsAuto, Item, ItemKind};
use ast::{Lifetime, LifetimeDef, Lit, LitKind, UintTy};
use ast::Local;
@ -1261,7 +1262,7 @@ impl<'a> Parser<'a> {
}
/// parse a TyKind::BareFn type:
pub fn parse_ty_bare_fn(&mut self, lifetime_defs: Vec<LifetimeDef>)
pub fn parse_ty_bare_fn(&mut self, generic_params: Vec<GenericParam>)
-> PResult<'a, TyKind> {
/*
@ -1293,7 +1294,7 @@ impl<'a> Parser<'a> {
Ok(TyKind::BareFn(P(BareFnTy {
abi,
unsafety,
lifetimes: lifetime_defs,
generic_params,
decl,
})))
}
@ -1582,9 +1583,9 @@ impl<'a> Parser<'a> {
Ok(P(ty))
}
fn parse_remaining_bounds(&mut self, lifetime_defs: Vec<LifetimeDef>, path: ast::Path,
fn parse_remaining_bounds(&mut self, generic_params: Vec<GenericParam>, path: ast::Path,
lo: Span, parse_plus: bool) -> PResult<'a, TyKind> {
let poly_trait_ref = PolyTraitRef::new(lifetime_defs, path, lo.to(self.prev_span));
let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_span));
let mut bounds = vec![TraitTyParamBound(poly_trait_ref, TraitBoundModifier::None)];
if parse_plus {
self.bump(); // `+`
@ -4550,9 +4551,8 @@ impl<'a> Parser<'a> {
/// Parses (possibly empty) list of lifetime and type parameters, possibly including
/// trailing comma and erroneous trailing attributes.
pub fn parse_generic_params(&mut self) -> PResult<'a, (Vec<LifetimeDef>, Vec<TyParam>)> {
let mut lifetime_defs = Vec::new();
let mut ty_params = Vec::new();
pub fn parse_generic_params(&mut self) -> PResult<'a, Vec<ast::GenericParam>> {
let mut params = Vec::new();
let mut seen_ty_param = false;
loop {
let attrs = self.parse_outer_attributes()?;
@ -4564,18 +4564,18 @@ impl<'a> Parser<'a> {
} else {
Vec::new()
};
lifetime_defs.push(LifetimeDef {
params.push(ast::GenericParam::Lifetime(LifetimeDef {
attrs: attrs.into(),
lifetime,
bounds,
});
}));
if seen_ty_param {
self.span_err(self.prev_span,
"lifetime parameters must be declared prior to type parameters");
}
} else if self.check_ident() {
// Parse type parameter.
ty_params.push(self.parse_ty_param(attrs)?);
params.push(ast::GenericParam::Type(self.parse_ty_param(attrs)?));
seen_ty_param = true;
} else {
// Check for trailing attributes and stop parsing.
@ -4591,7 +4591,7 @@ impl<'a> Parser<'a> {
break
}
}
Ok((lifetime_defs, ty_params))
Ok(params)
}
/// Parse a set of optional generic type parameter declarations. Where
@ -4606,11 +4606,10 @@ impl<'a> Parser<'a> {
let span_lo = self.span;
if self.eat_lt() {
let (lifetime_defs, ty_params) = self.parse_generic_params()?;
let params = self.parse_generic_params()?;
self.expect_gt()?;
Ok(ast::Generics {
lifetimes: lifetime_defs,
ty_params,
params,
where_clause: WhereClause {
id: ast::DUMMY_NODE_ID,
predicates: Vec::new(),
@ -4738,7 +4737,7 @@ impl<'a> Parser<'a> {
where_clause.predicates.push(ast::WherePredicate::BoundPredicate(
ast::WhereBoundPredicate {
span: lo.to(self.prev_span),
bound_lifetimes: lifetime_defs,
bound_generic_params: lifetime_defs,
bounded_ty: ty,
bounds,
}
@ -5363,16 +5362,24 @@ impl<'a> Parser<'a> {
}
}
fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<LifetimeDef>> {
fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<GenericParam>> {
if self.eat_keyword(keywords::For) {
self.expect_lt()?;
let (lifetime_defs, ty_params) = self.parse_generic_params()?;
let params = self.parse_generic_params()?;
self.expect_gt()?;
if !ty_params.is_empty() {
self.span_err(ty_params[0].span,
"only lifetime parameters can be used in this context");
let first_non_lifetime_param_span = params.iter()
.filter_map(|param| match *param {
ast::GenericParam::Lifetime(_) => None,
ast::GenericParam::Type(ref t) => Some(t.span),
})
.next();
if let Some(span) = first_non_lifetime_param_span {
self.span_err(span, "only lifetime parameters can be used in this context");
}
Ok(lifetime_defs)
Ok(params)
} else {
Ok(Vec::new())
}

View file

@ -275,7 +275,7 @@ pub fn token_to_string(tok: &Token) -> String {
token::NtArm(ref e) => arm_to_string(e),
token::NtImplItem(ref e) => impl_item_to_string(e),
token::NtTraitItem(ref e) => trait_item_to_string(e),
token::NtGenerics(ref e) => generics_to_string(e),
token::NtGenerics(ref e) => generic_params_to_string(&e.params),
token::NtWhereClause(ref e) => where_clause_to_string(e),
token::NtArg(ref e) => arg_to_string(e),
token::NtVis(ref e) => vis_to_string(e),
@ -339,8 +339,8 @@ pub fn trait_item_to_string(i: &ast::TraitItem) -> String {
to_string(|s| s.print_trait_item(i))
}
pub fn generics_to_string(generics: &ast::Generics) -> String {
to_string(|s| s.print_generics(generics))
pub fn generic_params_to_string(generic_params: &[ast::GenericParam]) -> String {
to_string(|s| s.print_generic_params(generic_params))
}
pub fn where_clause_to_string(i: &ast::WhereClause) -> String {
@ -1043,21 +1043,11 @@ impl<'a> State<'a> {
self.pclose()?;
}
ast::TyKind::BareFn(ref f) => {
let generics = ast::Generics {
lifetimes: f.lifetimes.clone(),
ty_params: Vec::new(),
where_clause: ast::WhereClause {
id: ast::DUMMY_NODE_ID,
predicates: Vec::new(),
span: syntax_pos::DUMMY_SP,
},
span: syntax_pos::DUMMY_SP,
};
self.print_ty_fn(f.abi,
f.unsafety,
&f.decl,
None,
&generics)?;
&f.generic_params)?;
}
ast::TyKind::Path(None, ref path) => {
self.print_path(path, false, 0, false)?;
@ -1271,15 +1261,15 @@ impl<'a> State<'a> {
self.s.word(&ga.asm.as_str())?;
self.end()?;
}
ast::ItemKind::Ty(ref ty, ref params) => {
ast::ItemKind::Ty(ref ty, ref generics) => {
self.ibox(INDENT_UNIT)?;
self.ibox(0)?;
self.word_nbsp(&visibility_qualified(&item.vis, "type"))?;
self.print_ident(item.ident)?;
self.print_generics(params)?;
self.print_generic_params(&generics.params)?;
self.end()?; // end the inner ibox
self.print_where_clause(&params.where_clause)?;
self.print_where_clause(&generics.where_clause)?;
self.s.space()?;
self.word_space("=")?;
self.print_type(ty)?;
@ -1329,7 +1319,7 @@ impl<'a> State<'a> {
self.word_nbsp("impl")?;
if generics.is_parameterized() {
self.print_generics(generics)?;
self.print_generic_params(&generics.params)?;
self.s.space()?;
}
@ -1361,7 +1351,7 @@ impl<'a> State<'a> {
self.print_is_auto(is_auto)?;
self.word_nbsp("trait")?;
self.print_ident(item.ident)?;
self.print_generics(generics)?;
self.print_generic_params(&generics.params)?;
let mut real_bounds = Vec::with_capacity(bounds.len());
for b in bounds.iter() {
if let TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = *b {
@ -1386,7 +1376,7 @@ impl<'a> State<'a> {
self.print_visibility(&item.vis)?;
self.word_nbsp("trait")?;
self.print_ident(item.ident)?;
self.print_generics(generics)?;
self.print_generic_params(&generics.params)?;
let mut real_bounds = Vec::with_capacity(bounds.len());
// FIXME(durka) this seems to be some quite outdated syntax
for b in bounds.iter() {
@ -1432,26 +1422,20 @@ impl<'a> State<'a> {
self.print_path(&t.path, false, 0, false)
}
fn print_formal_lifetime_list(&mut self, lifetimes: &[ast::LifetimeDef]) -> io::Result<()> {
if !lifetimes.is_empty() {
self.s.word("for<")?;
let mut comma = false;
for lifetime_def in lifetimes {
if comma {
self.word_space(",")?
}
self.print_outer_attributes_inline(&lifetime_def.attrs)?;
self.print_lifetime_bounds(&lifetime_def.lifetime, &lifetime_def.bounds)?;
comma = true;
}
self.s.word(">")?;
fn print_formal_generic_params(
&mut self,
generic_params: &[ast::GenericParam]
) -> io::Result<()> {
if !generic_params.is_empty() {
self.s.word("for")?;
self.print_generic_params(generic_params)?;
self.nbsp()?;
}
Ok(())
}
fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) -> io::Result<()> {
self.print_formal_lifetime_list(&t.bound_lifetimes)?;
self.print_formal_generic_params(&t.bound_generic_params)?;
self.print_trait_ref(&t.trait_ref)
}
@ -1461,7 +1445,7 @@ impl<'a> State<'a> {
visibility: &ast::Visibility) -> io::Result<()> {
self.head(&visibility_qualified(visibility, "enum"))?;
self.print_ident(ident)?;
self.print_generics(generics)?;
self.print_generic_params(&generics.params)?;
self.print_where_clause(&generics.where_clause)?;
self.s.space()?;
self.print_variants(&enum_definition.variants, span)
@ -1517,7 +1501,7 @@ impl<'a> State<'a> {
span: syntax_pos::Span,
print_finalizer: bool) -> io::Result<()> {
self.print_ident(ident)?;
self.print_generics(generics)?;
self.print_generic_params(&generics.params)?;
if !struct_def.is_struct() {
if struct_def.is_tuple() {
self.popen()?;
@ -2764,7 +2748,7 @@ impl<'a> State<'a> {
self.nbsp()?;
self.print_ident(name)?;
}
self.print_generics(generics)?;
self.print_generic_params(&generics.params)?;
self.print_fn_args_and_ret(decl)?;
self.print_where_clause(&generics.where_clause)
}
@ -2870,31 +2854,23 @@ impl<'a> State<'a> {
Ok(())
}
pub fn print_generics(&mut self,
generics: &ast::Generics)
-> io::Result<()>
{
let total = generics.lifetimes.len() + generics.ty_params.len();
if total == 0 {
pub fn print_generic_params(
&mut self,
generic_params: &[ast::GenericParam]
) -> io::Result<()> {
if generic_params.is_empty() {
return Ok(());
}
self.s.word("<")?;
let mut ints = Vec::new();
for i in 0..total {
ints.push(i);
}
self.commasep(Inconsistent, &ints[..], |s, &idx| {
if idx < generics.lifetimes.len() {
let lifetime_def = &generics.lifetimes[idx];
self.commasep(Inconsistent, &generic_params, |s, param| {
match *param {
ast::GenericParam::Lifetime(ref lifetime_def) => {
s.print_outer_attributes_inline(&lifetime_def.attrs)?;
s.print_lifetime_bounds(&lifetime_def.lifetime, &lifetime_def.bounds)
} else {
let idx = idx - generics.lifetimes.len();
let param = &generics.ty_params[idx];
s.print_ty_param(param)
},
ast::GenericParam::Type(ref ty_param) => s.print_ty_param(ty_param),
}
})?;
@ -2931,11 +2907,13 @@ impl<'a> State<'a> {
}
match *predicate {
ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bound_lifetimes,
ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
ref bound_generic_params,
ref bounded_ty,
ref bounds,
..}) => {
self.print_formal_lifetime_list(bound_lifetimes)?;
..
}) => {
self.print_formal_generic_params(bound_generic_params)?;
self.print_type(bounded_ty)?;
self.print_bounds(":", bounds)?;
}
@ -3057,16 +3035,15 @@ impl<'a> State<'a> {
unsafety: ast::Unsafety,
decl: &ast::FnDecl,
name: Option<ast::Ident>,
generics: &ast::Generics)
generic_params: &Vec<ast::GenericParam>)
-> io::Result<()> {
self.ibox(INDENT_UNIT)?;
if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() {
if !generic_params.is_empty() {
self.s.word("for")?;
self.print_generics(generics)?;
self.print_generic_params(generic_params)?;
}
let generics = ast::Generics {
lifetimes: Vec::new(),
ty_params: Vec::new(),
params: Vec::new(),
where_clause: ast::WhereClause {
id: ast::DUMMY_NODE_ID,
predicates: Vec::new(),

View file

@ -363,7 +363,10 @@ fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
ast::FunctionRetTy::Ty(ref t) if t.node == ast::TyKind::Tup(vec![]) => true,
_ => false
};
let tparm_cnt = generics.ty_params.len();
let tparm_cnt = generics.params.iter()
.filter(|param| param.is_type_param())
.count();
// NB: inadequate check, but we're running
// well before resolve, can't get too deep.
input_cnt == 1

View file

@ -71,6 +71,10 @@ impl<'ast> Visitor<'ast> for NodeCounter {
self.count += 1;
walk_ty(self, t)
}
fn visit_generic_param(&mut self, param: &GenericParam) {
self.count += 1;
walk_generic_param(self, param)
}
fn visit_generics(&mut self, g: &Generics) {
self.count += 1;
walk_generics(self, g)
@ -121,10 +125,6 @@ impl<'ast> Visitor<'ast> for NodeCounter {
self.count += 1;
walk_lifetime(self, lifetime)
}
fn visit_lifetime_def(&mut self, lifetime: &LifetimeDef) {
self.count += 1;
walk_lifetime_def(self, lifetime)
}
fn visit_mac(&mut self, _mac: &Mac) {
self.count += 1;
walk_mac(self, _mac)

View file

@ -72,6 +72,7 @@ pub trait Visitor<'ast>: Sized {
fn visit_expr(&mut self, ex: &'ast Expr) { walk_expr(self, ex) }
fn visit_expr_post(&mut self, _ex: &'ast Expr) { }
fn visit_ty(&mut self, t: &'ast Ty) { walk_ty(self, t) }
fn visit_generic_param(&mut self, param: &'ast GenericParam) { walk_generic_param(self, param) }
fn visit_generics(&mut self, g: &'ast Generics) { walk_generics(self, g) }
fn visit_where_predicate(&mut self, p: &'ast WherePredicate) {
walk_where_predicate(self, p)
@ -103,9 +104,6 @@ pub trait Visitor<'ast>: Sized {
fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) {
walk_lifetime(self, lifetime)
}
fn visit_lifetime_def(&mut self, lifetime: &'ast LifetimeDef) {
walk_lifetime_def(self, lifetime)
}
fn visit_mac(&mut self, _mac: &'ast Mac) {
panic!("visit_mac disabled by default");
// NB: see note about macros above.
@ -210,18 +208,12 @@ pub fn walk_lifetime<'a, V: Visitor<'a>>(visitor: &mut V, lifetime: &'a Lifetime
visitor.visit_ident(lifetime.span, lifetime.ident);
}
pub fn walk_lifetime_def<'a, V: Visitor<'a>>(visitor: &mut V, lifetime_def: &'a LifetimeDef) {
visitor.visit_lifetime(&lifetime_def.lifetime);
walk_list!(visitor, visit_lifetime, &lifetime_def.bounds);
walk_list!(visitor, visit_attribute, &*lifetime_def.attrs);
}
pub fn walk_poly_trait_ref<'a, V>(visitor: &mut V,
trait_ref: &'a PolyTraitRef,
_: &TraitBoundModifier)
where V: Visitor<'a>,
{
walk_list!(visitor, visit_lifetime_def, &trait_ref.bound_lifetimes);
walk_list!(visitor, visit_generic_param, &trait_ref.bound_generic_params);
visitor.visit_trait_ref(&trait_ref.trait_ref);
}
@ -339,7 +331,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
}
TyKind::BareFn(ref function_declaration) => {
walk_fn_decl(visitor, &function_declaration.decl);
walk_list!(visitor, visit_lifetime_def, &function_declaration.lifetimes);
walk_list!(visitor, visit_generic_param, &function_declaration.generic_params);
}
TyKind::Path(ref maybe_qself, ref path) => {
if let Some(ref qself) = *maybe_qself {
@ -499,14 +491,24 @@ pub fn walk_ty_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a TyPar
}
}
pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics) {
for param in &generics.ty_params {
visitor.visit_ident(param.span, param.ident);
walk_list!(visitor, visit_ty_param_bound, &param.bounds);
walk_list!(visitor, visit_ty, &param.default);
walk_list!(visitor, visit_attribute, &*param.attrs);
pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a GenericParam) {
match *param {
GenericParam::Lifetime(ref l) => {
visitor.visit_lifetime(&l.lifetime);
walk_list!(visitor, visit_lifetime, &l.bounds);
walk_list!(visitor, visit_attribute, &*l.attrs);
}
walk_list!(visitor, visit_lifetime_def, &generics.lifetimes);
GenericParam::Type(ref t) => {
visitor.visit_ident(t.span, t.ident);
walk_list!(visitor, visit_ty_param_bound, &t.bounds);
walk_list!(visitor, visit_ty, &t.default);
walk_list!(visitor, visit_attribute, &*t.attrs);
}
}
}
pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics) {
walk_list!(visitor, visit_generic_param, &generics.params);
walk_list!(visitor, visit_where_predicate, &generics.where_clause.predicates);
}
@ -514,11 +516,11 @@ pub fn walk_where_predicate<'a, V: Visitor<'a>>(visitor: &mut V, predicate: &'a
match *predicate {
WherePredicate::BoundPredicate(WhereBoundPredicate{ref bounded_ty,
ref bounds,
ref bound_lifetimes,
ref bound_generic_params,
..}) => {
visitor.visit_ty(bounded_ty);
walk_list!(visitor, visit_ty_param_bound, bounds);
walk_list!(visitor, visit_lifetime_def, bound_lifetimes);
walk_list!(visitor, visit_generic_param, bound_generic_params);
}
WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime,
ref bounds,

View file

@ -45,15 +45,23 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt,
match *item {
Annotatable::Item(ref annitem) => {
match annitem.node {
ItemKind::Struct(_, Generics { ref ty_params, .. }) |
ItemKind::Enum(_, Generics { ref ty_params, .. })
ItemKind::Struct(_, Generics { ref params, .. }) |
ItemKind::Enum(_, Generics { ref params, .. }) => {
if attr::contains_name(&annitem.attrs, "rustc_copy_clone_marker") &&
ty_params.is_empty() => {
!params.iter().any(|param| param.is_type_param())
{
bounds = vec![];
is_shallow = true;
substructure = combine_substructure(Box::new(|c, s, sub| {
cs_clone_shallow("Clone", c, s, sub, false)
}));
} else {
bounds = vec![];
is_shallow = false;
substructure = combine_substructure(Box::new(|c, s, sub| {
cs_clone("Clone", c, s, sub)
}));
}
}
ItemKind::Union(..) => {
bounds = vec![Literal(path_std!(cx, marker::Copy))];

View file

@ -192,7 +192,9 @@ use std::collections::HashSet;
use std::vec;
use syntax::abi::Abi;
use syntax::ast::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind, VariantData};
use syntax::ast::{
self, BinOpKind, EnumDef, Expr, GenericParam, Generics, Ident, PatKind, VariantData
};
use syntax::attr;
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ext::build::AstBuilder;
@ -417,7 +419,7 @@ impl<'a> TraitDef<'a> {
ast::ItemKind::Struct(_, ref generics) |
ast::ItemKind::Enum(_, ref generics) |
ast::ItemKind::Union(_, ref generics) => {
generics.ty_params.is_empty()
!generics.params.iter().any(|p| p.is_type_param())
}
_ => {
// Non-ADT derive is an error, but it should have been
@ -537,18 +539,19 @@ impl<'a> TraitDef<'a> {
}
});
let Generics { mut lifetimes, mut ty_params, mut where_clause, span } = self.generics
let Generics { mut params, mut where_clause, span } = self.generics
.to_generics(cx, self.span, type_ident, generics);
// Copy the lifetimes
lifetimes.extend(generics.lifetimes.iter().cloned());
// Create the type parameters.
ty_params.extend(generics.ty_params.iter().map(|ty_param| {
// Create the generic parameters
params.extend(generics.params.iter().map(|param| {
match *param {
ref l @ GenericParam::Lifetime(_) => l.clone(),
GenericParam::Type(ref ty_param) => {
// I don't think this can be moved out of the loop, since
// a TyParamBound requires an ast id
let mut bounds: Vec<_> =
// extra restrictions on the generics parameters to the type being derived upon
// extra restrictions on the generics parameters to the
// type being derived upon
self.additional_bounds.iter().map(|p| {
cx.typarambound(p.to_path(cx, self.span,
type_ident, generics))
@ -562,7 +565,9 @@ impl<'a> TraitDef<'a> {
bounds.push((*declared_bound).clone());
}
cx.typaram(self.span, ty_param.ident, vec![], bounds, None)
GenericParam::Type(cx.typaram(self.span, ty_param.ident, vec![], bounds, None))
}
}
}));
// and similarly for where clauses
@ -571,7 +576,7 @@ impl<'a> TraitDef<'a> {
ast::WherePredicate::BoundPredicate(ref wb) => {
ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
span: self.span,
bound_lifetimes: wb.bound_lifetimes.clone(),
bound_generic_params: wb.bound_generic_params.clone(),
bounded_ty: wb.bounded_ty.clone(),
bounds: wb.bounds.iter().cloned().collect(),
})
@ -594,8 +599,18 @@ impl<'a> TraitDef<'a> {
}
}));
if !ty_params.is_empty() {
let ty_param_names: Vec<ast::Name> = ty_params.iter()
{
// Extra scope required here so ty_params goes out of scope before params is moved
let mut ty_params = params.iter()
.filter_map(|param| match *param {
ast::GenericParam::Type(ref t) => Some(t),
_ => None,
})
.peekable();
if ty_params.peek().is_some() {
let ty_param_names: Vec<ast::Name> = ty_params
.map(|ty_param| ty_param.ident.name)
.collect();
@ -615,7 +630,9 @@ impl<'a> TraitDef<'a> {
}
let mut bounds: Vec<_> = self.additional_bounds
.iter()
.map(|p| cx.typarambound(p.to_path(cx, self.span, type_ident, generics)))
.map(|p| {
cx.typarambound(p.to_path(cx, self.span, type_ident, generics))
})
.collect();
// require the current trait
@ -623,7 +640,7 @@ impl<'a> TraitDef<'a> {
let predicate = ast::WhereBoundPredicate {
span: self.span,
bound_lifetimes: vec![],
bound_generic_params: Vec::new(),
bounded_ty: ty,
bounds,
};
@ -633,10 +650,10 @@ impl<'a> TraitDef<'a> {
}
}
}
}
let trait_generics = Generics {
lifetimes,
ty_params,
params,
where_clause,
span,
};
@ -645,14 +662,21 @@ impl<'a> TraitDef<'a> {
let trait_ref = cx.trait_ref(trait_path);
// Create the type parameters on the `self` path.
let self_ty_params = generics.ty_params
let self_ty_params = generics.params
.iter()
.map(|ty_param| cx.ty_ident(self.span, ty_param.ident))
.filter_map(|param| match *param {
GenericParam::Type(ref ty_param)
=> Some(cx.ty_ident(self.span, ty_param.ident)),
_ => None,
})
.collect();
let self_lifetimes: Vec<ast::Lifetime> = generics.lifetimes
let self_lifetimes: Vec<ast::Lifetime> = generics.params
.iter()
.map(|ld| ld.lifetime)
.filter_map(|param| match *param {
GenericParam::Lifetime(ref ld) => Some(ld.lifetime),
_ => None,
})
.collect();
// Create the type of `self`.

View file

@ -15,7 +15,7 @@ pub use self::PtrTy::*;
pub use self::Ty::*;
use syntax::ast;
use syntax::ast::{Expr, Generics, Ident, SelfKind};
use syntax::ast::{Expr, GenericParam, Generics, Ident, SelfKind};
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::codemap::respan;
@ -185,13 +185,20 @@ impl<'a> Ty<'a> {
-> ast::Path {
match *self {
Self_ => {
let self_params = self_generics.ty_params
let self_params = self_generics.params
.iter()
.map(|ty_param| cx.ty_ident(span, ty_param.ident))
.filter_map(|param| match *param {
GenericParam::Type(ref ty_param) => Some(cx.ty_ident(span, ty_param.ident)),
_ => None,
})
.collect();
let lifetimes = self_generics.lifetimes
let lifetimes: Vec<ast::Lifetime> = self_generics.params
.iter()
.map(|d| d.lifetime)
.filter_map(|param| match *param {
GenericParam::Lifetime(ref ld) => Some(ld.lifetime),
_ => None,
})
.collect();
cx.path_all(span,
@ -226,11 +233,9 @@ fn mk_ty_param(cx: &ExtCtxt,
cx.typaram(span, cx.ident_of(name), attrs.to_owned(), bounds, None)
}
fn mk_generics(lifetimes: Vec<ast::LifetimeDef>, ty_params: Vec<ast::TyParam>, span: Span)
-> Generics {
fn mk_generics(params: Vec<GenericParam>, span: Span) -> Generics {
Generics {
lifetimes,
ty_params,
params,
where_clause: ast::WhereClause {
id: ast::DUMMY_NODE_ID,
predicates: Vec::new(),
@ -260,26 +265,26 @@ impl<'a> LifetimeBounds<'a> {
self_ty: Ident,
self_generics: &Generics)
-> Generics {
let lifetimes = self.lifetimes
let generic_params = self.lifetimes
.iter()
.map(|&(lt, ref bounds)| {
let bounds = bounds.iter()
.map(|b| cx.lifetime(span, Ident::from_str(b)))
.collect();
cx.lifetime_def(span, Ident::from_str(lt), vec![], bounds)
GenericParam::Lifetime(cx.lifetime_def(span, Ident::from_str(lt), vec![], bounds))
})
.collect();
let ty_params = self.bounds
.chain(self.bounds
.iter()
.map(|t| {
match *t {
(ref name, ref bounds) => {
mk_ty_param(cx, span, *name, &[], bounds, self_ty, self_generics)
}
}
let (name, ref bounds) = *t;
GenericParam::Type(mk_ty_param(
cx, span, name, &[], &bounds, self_ty, self_generics
))
})
)
.collect();
mk_generics(lifetimes, ty_params, span)
mk_generics(generic_params, span)
}
}

View file

@ -121,12 +121,14 @@ fn hygienic_type_parameter(item: &Annotatable, base: &str) -> String {
let mut typaram = String::from(base);
if let Annotatable::Item(ref item) = *item {
match item.node {
ast::ItemKind::Struct(_, ast::Generics { ref ty_params, .. }) |
ast::ItemKind::Enum(_, ast::Generics { ref ty_params, .. }) => {
for ty in ty_params.iter() {
ast::ItemKind::Struct(_, ast::Generics { ref params, .. }) |
ast::ItemKind::Enum(_, ast::Generics { ref params, .. }) => {
for param in params.iter() {
if let ast::GenericParam::Type(ref ty) = *param{
typaram.push_str(&ty.ident.name.as_str());
}
}
}
_ => {}
}

View file

@ -89,9 +89,9 @@ error[E0309]: the parameter type `T` may not live long enough
56 | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:17), 'a))`...
= help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))`...
error: free region `ReEarlyBound(0, 'b)` does not outlive free region `ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:17), 'a))`
error: free region `ReEarlyBound(0, 'b)` does not outlive free region `ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))`
--> $DIR/projection-one-region-closure.rs:56:20
|
56 | with_signature(cell, t, |cell, t| require(cell, t));

View file

@ -94,7 +94,7 @@ note: External requirements
= note: number of external vids: 3
= note: where '_#1r: '_#2r
error: free region `ReEarlyBound(0, 'b)` does not outlive free region `ReFree(DefId(0/0:8 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:17), 'a))`
error: free region `ReEarlyBound(0, 'b)` does not outlive free region `ReFree(DefId(0/0:8 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))`
--> $DIR/projection-one-region-trait-bound-closure.rs:48:20
|
48 | with_signature(cell, t, |cell, t| require(cell, t));

View file

@ -158,7 +158,7 @@ error[E0309]: the associated type `<T as Anything<'_#5r, '_#6r>>::AssocType` may
49 | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `<T as Anything<'_#5r, '_#6r>>::AssocType: ReFree(DefId(0/0:8 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:19), 'a))`...
= help: consider adding an explicit lifetime bound `<T as Anything<'_#5r, '_#6r>>::AssocType: ReFree(DefId(0/0:8 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:18), 'a))`...
note: No external requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:45:1
@ -270,7 +270,7 @@ note: No external requirements
T
]
error: free region `ReEarlyBound(0, 'b)` does not outlive free region `ReFree(DefId(0/0:13 ~ projection_two_region_trait_bound_closure[317d]::two_regions[0]), BrNamed(crate0:DefIndex(1:44), 'a))`
error: free region `ReEarlyBound(0, 'b)` does not outlive free region `ReFree(DefId(0/0:13 ~ projection_two_region_trait_bound_closure[317d]::two_regions[0]), BrNamed(crate0:DefIndex(1:43), 'a))`
--> $DIR/projection-two-region-trait-bound-closure.rs:109:20
|
109 | with_signature(cell, t, |cell, t| require(cell, t));

View file

@ -66,7 +66,7 @@ error[E0309]: the parameter type `T` may not live long enough
43 | twice(cell, value, |a, b| invoke(a, b));
| ^^^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]), BrNamed(crate0:DefIndex(1:16), 'a))`...
= help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]), BrNamed(crate0:DefIndex(1:15), 'a))`...
note: No external requirements
--> $DIR/ty-param-closure-approximate-lower-bound.rs:42:1

View file

@ -107,7 +107,7 @@ error[E0309]: the parameter type `T` may not live long enough
47 | | })
| |_____^
|
= help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]), BrNamed(crate0:DefIndex(1:15), 'a))`...
= help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]), BrNamed(crate0:DefIndex(1:14), 'a))`...
note: No external requirements
--> $DIR/ty-param-closure-outlives-from-where-clause.rs:37:1
@ -154,7 +154,7 @@ error[E0309]: the parameter type `T` may not live long enough
81 | | })
| |_____^
|
= help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]), BrNamed(crate0:DefIndex(1:21), 'a))`...
= help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]), BrNamed(crate0:DefIndex(1:20), 'a))`...
note: No external requirements
--> $DIR/ty-param-closure-outlives-from-where-clause.rs:72:1