1
Fork 0

Refactor hir::GenericParam as a struct

This commit is contained in:
varkor 2018-05-26 00:27:54 +01:00
parent d643946550
commit 82dba3d419
23 changed files with 710 additions and 572 deletions

View file

@ -743,26 +743,25 @@ pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v TyPar
} }
pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v GenericParam) { pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v GenericParam) {
match *param { visitor.visit_id(param.id);
GenericParam::Lifetime(ref ld) => { match param.kind {
visitor.visit_id(ld.lifetime.id); GenericParamKind::Lifetime { ref bounds, ref lifetime_deprecated, .. } => {
match ld.lifetime.name { match lifetime_deprecated.name {
LifetimeName::Name(name) => { LifetimeName::Name(name) => {
visitor.visit_name(ld.lifetime.span, name); visitor.visit_name(param.span, name);
} }
LifetimeName::Fresh(_) | LifetimeName::Fresh(_) |
LifetimeName::Static | LifetimeName::Static |
LifetimeName::Implicit | LifetimeName::Implicit |
LifetimeName::Underscore => {} LifetimeName::Underscore => {}
} }
walk_list!(visitor, visit_lifetime, &ld.bounds); walk_list!(visitor, visit_lifetime, bounds);
} }
GenericParam::Type(ref ty_param) => { GenericParamKind::Type { name, ref bounds, ref default, ref attrs, .. } => {
visitor.visit_id(ty_param.id); visitor.visit_name(param.span, name);
visitor.visit_name(ty_param.span, ty_param.name); walk_list!(visitor, visit_ty_param_bound, bounds);
walk_list!(visitor, visit_ty_param_bound, &ty_param.bounds); walk_list!(visitor, visit_ty, default);
walk_list!(visitor, visit_ty, &ty_param.default); walk_list!(visitor, visit_attribute, attrs.iter());
walk_list!(visitor, visit_attribute, ty_param.attrs.iter());
} }
} }
} }

View file

@ -116,7 +116,7 @@ pub struct LoweringContext<'a> {
// When traversing a signature such as `fn foo(x: impl Trait)`, // When traversing a signature such as `fn foo(x: impl Trait)`,
// we record `impl Trait` as a new type parameter, then later // we record `impl Trait` as a new type parameter, then later
// add it on to `foo`s generics. // add it on to `foo`s generics.
in_band_ty_params: Vec<hir::TyParam>, in_band_ty_params: Vec<hir::GenericParam>,
// Used to create lifetime definitions from in-band lifetime usages. // Used to create lifetime definitions from in-band lifetime usages.
// e.g. `fn foo(x: &'x u8) -> &'x u8` to `fn foo<'x>(x: &'x u8) -> &'x u8` // e.g. `fn foo(x: &'x u8) -> &'x u8` to `fn foo<'x>(x: &'x u8) -> &'x u8`
@ -695,22 +695,23 @@ impl<'a> LoweringContext<'a> {
span, span,
); );
hir::GenericParam::Lifetime(hir::LifetimeDef { hir::GenericParam {
lifetime: hir::Lifetime { id: def_node_id,
span,
pure_wrt_drop: false,
kind: hir::GenericParamKind::Lifetime {
name: hir_name,
bounds: vec![].into(),
in_band: true,
lifetime_deprecated: hir::Lifetime {
id: def_node_id, id: def_node_id,
span, span,
name: hir_name, name: hir_name,
}, }
bounds: Vec::new().into(), }
pure_wrt_drop: false, }
in_band: true,
}) })
}) .chain(in_band_ty_params.into_iter())
.chain(
in_band_ty_params
.into_iter()
.map(|tp| hir::GenericParam::Type(tp)),
)
.collect(); .collect();
(params, res) (params, res)
@ -778,12 +779,12 @@ impl<'a> LoweringContext<'a> {
// This should only be used with generics that have already had their // This should only be used with generics that have already had their
// in-band lifetimes added. In practice, this means that this function is // in-band lifetimes added. In practice, this means that this function is
// only used when lowering a child item of a trait or impl. // only used when lowering a child item of a trait or impl.
fn with_parent_impl_lifetime_defs<T, F>(&mut self, lt_defs: &[hir::LifetimeDef], f: F) -> T fn with_parent_impl_lifetime_defs<T, F>(&mut self, params: &[hir::GenericParam], f: F) -> T
where where
F: FnOnce(&mut LoweringContext) -> T, F: FnOnce(&mut LoweringContext) -> T,
{ {
let old_len = self.in_scope_lifetimes.len(); let old_len = self.in_scope_lifetimes.len();
let lt_def_names = lt_defs.iter().map(|lt_def| lt_def.lifetime.name.name()); let lt_def_names = params.iter().map(|param| param.name());
self.in_scope_lifetimes.extend(lt_def_names); self.in_scope_lifetimes.extend(lt_def_names);
let res = f(self); let res = f(self);
@ -1252,15 +1253,17 @@ impl<'a> LoweringContext<'a> {
let hir_bounds = self.lower_bounds(bounds, itctx); let hir_bounds = self.lower_bounds(bounds, itctx);
// Set the name to `impl Bound1 + Bound2` // Set the name to `impl Bound1 + Bound2`
let name = Symbol::intern(&pprust::ty_to_string(t)); let name = Symbol::intern(&pprust::ty_to_string(t));
self.in_band_ty_params.push(hir::TyParam { self.in_band_ty_params.push(hir::GenericParam {
name,
id: def_node_id, id: def_node_id,
bounds: hir_bounds,
default: None,
span, span,
pure_wrt_drop: false, pure_wrt_drop: false,
kind: hir::GenericParamKind::Type {
name,
bounds: hir_bounds,
default: None,
synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
attrs: P::new(), attrs: P::new(),
}
}); });
hir::TyPath(hir::QPath::Resolved( hir::TyPath(hir::QPath::Resolved(
@ -1367,10 +1370,10 @@ impl<'a> LoweringContext<'a> {
fn visit_generic_param(&mut self, param: &'v hir::GenericParam) { fn visit_generic_param(&mut self, param: &'v hir::GenericParam) {
// Record the introduction of 'a in `for<'a> ...` // Record the introduction of 'a in `for<'a> ...`
if let hir::GenericParam::Lifetime(ref lt_def) = *param { if let hir::GenericParamKind::Lifetime { name, .. } = param.kind {
// Introduce lifetimes one at a time so that we can handle // Introduce lifetimes one at a time so that we can handle
// cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>` // cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>`
self.currently_bound_lifetimes.push(lt_def.lifetime.name); self.currently_bound_lifetimes.push(name);
} }
hir::intravisit::walk_generic_param(self, param); hir::intravisit::walk_generic_param(self, param);
@ -1416,18 +1419,22 @@ impl<'a> LoweringContext<'a> {
Mark::root(), Mark::root(),
lifetime.span, lifetime.span,
); );
let def_lifetime = hir::Lifetime {
self.output_lifetime_params.push(hir::GenericParam {
id: def_node_id,
span: lifetime.span,
pure_wrt_drop: false,
kind: hir::GenericParamKind::Lifetime {
name,
bounds: vec![].into(),
in_band: false,
lifetime_deprecated: hir::Lifetime {
id: def_node_id, id: def_node_id,
span: lifetime.span, span: lifetime.span,
name, name,
}; }
self.output_lifetime_params }
.push(hir::GenericParam::Lifetime(hir::LifetimeDef { });
lifetime: def_lifetime,
bounds: Vec::new().into(),
pure_wrt_drop: false,
in_band: false,
}));
} }
} }
} }
@ -1887,47 +1894,6 @@ impl<'a> LoweringContext<'a> {
} }
} }
fn lower_ty_param(
&mut self,
tp: &TyParam,
add_bounds: &[TyParamBound],
itctx: ImplTraitContext,
) -> hir::TyParam {
let mut name = self.lower_ident(tp.ident);
// Don't expose `Self` (recovered "keyword used as ident" parse error).
// `rustc::ty` expects `Self` to be only used for a trait's `Self`.
// Instead, use gensym("Self") to create a distinct name that looks the same.
if name == keywords::SelfType.name() {
name = Symbol::gensym("Self");
}
let mut bounds = self.lower_bounds(&tp.bounds, itctx);
if !add_bounds.is_empty() {
bounds = bounds
.into_iter()
.chain(self.lower_bounds(add_bounds, itctx).into_iter())
.collect();
}
hir::TyParam {
id: self.lower_node_id(tp.id).node_id,
name,
bounds,
default: tp.default
.as_ref()
.map(|x| self.lower_ty(x, ImplTraitContext::Disallowed)),
span: tp.ident.span,
pure_wrt_drop: attr::contains_name(&tp.attrs, "may_dangle"),
synthetic: tp.attrs
.iter()
.filter(|attr| attr.check_name("rustc_synthetic"))
.map(|_| hir::SyntheticTyParamKind::ImplTrait)
.nth(0),
attrs: self.lower_attrs(&tp.attrs),
}
}
fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime { fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime {
let span = l.ident.span; let span = l.ident.span;
match self.lower_ident(l.ident) { match self.lower_ident(l.ident) {
@ -1962,20 +1928,75 @@ impl<'a> LoweringContext<'a> {
} }
} }
fn lower_lifetime_def(&mut self, l: &LifetimeDef) -> hir::LifetimeDef { fn lower_generic_param(&mut self,
param: &GenericParamAST,
add_bounds: &NodeMap<Vec<TyParamBound>>,
itctx: ImplTraitContext)
-> hir::GenericParam {
match param {
GenericParamAST::Lifetime(ref lifetime_def) => {
let was_collecting_in_band = self.is_collecting_in_band_lifetimes; let was_collecting_in_band = self.is_collecting_in_band_lifetimes;
self.is_collecting_in_band_lifetimes = false; self.is_collecting_in_band_lifetimes = false;
let def = hir::LifetimeDef { let lifetime = self.lower_lifetime(&lifetime_def.lifetime);
lifetime: self.lower_lifetime(&l.lifetime), let param = hir::GenericParam {
bounds: l.bounds.iter().map(|l| self.lower_lifetime(l)).collect(), id: lifetime.id,
pure_wrt_drop: attr::contains_name(&l.attrs, "may_dangle"), span: lifetime.span,
pure_wrt_drop: attr::contains_name(&lifetime_def.attrs, "may_dangle"),
kind: hir::GenericParamKind::Lifetime {
name: lifetime.name,
bounds: lifetime_def.bounds
.iter()
.map(|lt| self.lower_lifetime(lt)).collect(),
in_band: false, in_band: false,
lifetime_deprecated: lifetime,
}
}; };
self.is_collecting_in_band_lifetimes = was_collecting_in_band; self.is_collecting_in_band_lifetimes = was_collecting_in_band;
def param
}
GenericParamAST::Type(ref ty_param) => {
let mut name = self.lower_ident(ty_param.ident);
// Don't expose `Self` (recovered "keyword used as ident" parse error).
// `rustc::ty` expects `Self` to be only used for a trait's `Self`.
// Instead, use gensym("Self") to create a distinct name that looks the same.
if name == keywords::SelfType.name() {
name = Symbol::gensym("Self");
}
let mut bounds = self.lower_bounds(&ty_param.bounds, itctx);
let add_bounds = add_bounds.get(&ty_param.id).map_or(&[][..], |x| &x);
if !add_bounds.is_empty() {
bounds = bounds
.into_iter()
.chain(self.lower_bounds(add_bounds, itctx).into_iter())
.collect();
}
hir::GenericParam {
id: self.lower_node_id(ty_param.id).node_id,
span: ty_param.ident.span,
pure_wrt_drop: attr::contains_name(&ty_param.attrs, "may_dangle"),
kind: hir::GenericParamKind::Type {
name,
bounds,
default: ty_param.default.as_ref()
.map(|x| {
self.lower_ty(x, ImplTraitContext::Disallowed)
}),
synthetic: ty_param.attrs
.iter()
.filter(|attr| attr.check_name("rustc_synthetic"))
.map(|_| hir::SyntheticTyParamKind::ImplTrait)
.nth(0),
attrs: self.lower_attrs(&ty_param.attrs),
}
}
}
}
} }
fn lower_generic_params( fn lower_generic_params(
@ -1984,19 +2005,7 @@ impl<'a> LoweringContext<'a> {
add_bounds: &NodeMap<Vec<TyParamBound>>, add_bounds: &NodeMap<Vec<TyParamBound>>,
itctx: ImplTraitContext, itctx: ImplTraitContext,
) -> hir::HirVec<hir::GenericParam> { ) -> hir::HirVec<hir::GenericParam> {
params params.iter().map(|param| self.lower_generic_param(param, add_bounds, itctx)).collect()
.iter()
.map(|param| match *param {
GenericParamAST::Lifetime(ref lifetime_def) => {
hir::GenericParam::Lifetime(self.lower_lifetime_def(lifetime_def))
}
GenericParamAST::Type(ref ty_param) => hir::GenericParam::Type(self.lower_ty_param(
ty_param,
add_bounds.get(&ty_param.id).map_or(&[][..], |x| &x),
itctx,
)),
})
.collect()
} }
fn lower_generics(&mut self, g: &Generics, itctx: ImplTraitContext) -> hir::Generics { fn lower_generics(&mut self, g: &Generics, itctx: ImplTraitContext) -> hir::Generics {
@ -2175,8 +2184,8 @@ impl<'a> LoweringContext<'a> {
let trait_ref = self.with_parent_impl_lifetime_defs( let trait_ref = self.with_parent_impl_lifetime_defs(
&bound_generic_params &bound_generic_params
.iter() .iter()
.filter_map(|p| match *p { .filter_map(|param| match param.kind {
hir::GenericParam::Lifetime(ref ld) => Some(ld.clone()), hir::GenericParamKind::Lifetime { .. } => Some(param.clone()),
_ => None, _ => None,
}) })
.collect::<Vec<_>>(), .collect::<Vec<_>>(),

View file

@ -212,7 +212,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
NodeBlock(n) => EntryBlock(parent, dep_node_index, n), NodeBlock(n) => EntryBlock(parent, dep_node_index, n),
NodeStructCtor(n) => EntryStructCtor(parent, dep_node_index, n), NodeStructCtor(n) => EntryStructCtor(parent, dep_node_index, n),
NodeLifetime(n) => EntryLifetime(parent, dep_node_index, n), NodeLifetime(n) => EntryLifetime(parent, dep_node_index, n),
NodeTyParam(n) => EntryTyParam(parent, dep_node_index, n), NodeGenericParam(n) => EntryGenericParam(parent, dep_node_index, n),
NodeVisibility(n) => EntryVisibility(parent, dep_node_index, n), NodeVisibility(n) => EntryVisibility(parent, dep_node_index, n),
NodeLocal(n) => EntryLocal(parent, dep_node_index, n), NodeLocal(n) => EntryLocal(parent, dep_node_index, n),
NodeMacroDef(n) => EntryMacroDef(dep_node_index, n), NodeMacroDef(n) => EntryMacroDef(dep_node_index, n),
@ -347,12 +347,12 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
} }
fn visit_generic_param(&mut self, param: &'hir GenericParam) { fn visit_generic_param(&mut self, param: &'hir GenericParam) {
match *param { match param.kind {
GenericParam::Lifetime(ref ld) => { GenericParamKind::Lifetime { ref lifetime_deprecated, .. } => {
self.insert(ld.lifetime.id, NodeLifetime(&ld.lifetime)); self.insert(param.id, NodeLifetime(lifetime_deprecated));
} }
GenericParam::Type(ref ty_param) => { GenericParamKind::Type { .. } => {
self.insert(ty_param.id, NodeTyParam(ty_param)); self.insert(param.id, NodeGenericParam(param));
} }
} }
intravisit::walk_generic_param(self, param); intravisit::walk_generic_param(self, param);

View file

@ -68,7 +68,7 @@ pub enum Node<'hir> {
NodeStructCtor(&'hir VariantData), NodeStructCtor(&'hir VariantData),
NodeLifetime(&'hir Lifetime), NodeLifetime(&'hir Lifetime),
NodeTyParam(&'hir TyParam), NodeGenericParam(&'hir GenericParam),
NodeVisibility(&'hir Visibility), NodeVisibility(&'hir Visibility),
} }
@ -96,7 +96,7 @@ enum MapEntry<'hir> {
EntryBlock(NodeId, DepNodeIndex, &'hir Block), EntryBlock(NodeId, DepNodeIndex, &'hir Block),
EntryStructCtor(NodeId, DepNodeIndex, &'hir VariantData), EntryStructCtor(NodeId, DepNodeIndex, &'hir VariantData),
EntryLifetime(NodeId, DepNodeIndex, &'hir Lifetime), EntryLifetime(NodeId, DepNodeIndex, &'hir Lifetime),
EntryTyParam(NodeId, DepNodeIndex, &'hir TyParam), EntryGenericParam(NodeId, DepNodeIndex, &'hir GenericParam),
EntryVisibility(NodeId, DepNodeIndex, &'hir Visibility), EntryVisibility(NodeId, DepNodeIndex, &'hir Visibility),
EntryLocal(NodeId, DepNodeIndex, &'hir Local), EntryLocal(NodeId, DepNodeIndex, &'hir Local),
@ -132,7 +132,7 @@ impl<'hir> MapEntry<'hir> {
EntryBlock(id, _, _) => id, EntryBlock(id, _, _) => id,
EntryStructCtor(id, _, _) => id, EntryStructCtor(id, _, _) => id,
EntryLifetime(id, _, _) => id, EntryLifetime(id, _, _) => id,
EntryTyParam(id, _, _) => id, EntryGenericParam(id, _, _) => id,
EntryVisibility(id, _, _) => id, EntryVisibility(id, _, _) => id,
EntryLocal(id, _, _) => id, EntryLocal(id, _, _) => id,
@ -160,7 +160,7 @@ impl<'hir> MapEntry<'hir> {
EntryBlock(_, _, n) => NodeBlock(n), EntryBlock(_, _, n) => NodeBlock(n),
EntryStructCtor(_, _, n) => NodeStructCtor(n), EntryStructCtor(_, _, n) => NodeStructCtor(n),
EntryLifetime(_, _, n) => NodeLifetime(n), EntryLifetime(_, _, n) => NodeLifetime(n),
EntryTyParam(_, _, n) => NodeTyParam(n), EntryGenericParam(_, _, n) => NodeGenericParam(n),
EntryVisibility(_, _, n) => NodeVisibility(n), EntryVisibility(_, _, n) => NodeVisibility(n),
EntryLocal(_, _, n) => NodeLocal(n), EntryLocal(_, _, n) => NodeLocal(n),
EntryMacroDef(_, n) => NodeMacroDef(n), EntryMacroDef(_, n) => NodeMacroDef(n),
@ -328,7 +328,7 @@ impl<'hir> Map<'hir> {
EntryBlock(_, dep_node_index, _) | EntryBlock(_, dep_node_index, _) |
EntryStructCtor(_, dep_node_index, _) | EntryStructCtor(_, dep_node_index, _) |
EntryLifetime(_, dep_node_index, _) | EntryLifetime(_, dep_node_index, _) |
EntryTyParam(_, dep_node_index, _) | EntryGenericParam(_, dep_node_index, _) |
EntryVisibility(_, dep_node_index, _) | EntryVisibility(_, dep_node_index, _) |
EntryAnonConst(_, dep_node_index, _) | EntryAnonConst(_, dep_node_index, _) |
EntryExpr(_, dep_node_index, _) | EntryExpr(_, dep_node_index, _) |
@ -494,7 +494,7 @@ impl<'hir> Map<'hir> {
Some(Def::Macro(self.local_def_id(macro_def.id), Some(Def::Macro(self.local_def_id(macro_def.id),
MacroKind::Bang)) MacroKind::Bang))
} }
NodeTyParam(param) => { NodeGenericParam(param) => {
Some(Def::TyParam(self.local_def_id(param.id))) Some(Def::TyParam(self.local_def_id(param.id)))
} }
} }
@ -600,7 +600,7 @@ impl<'hir> Map<'hir> {
pub fn ty_param_owner(&self, id: NodeId) -> NodeId { pub fn ty_param_owner(&self, id: NodeId) -> NodeId {
match self.get(id) { match self.get(id) {
NodeItem(&Item { node: ItemTrait(..), .. }) => id, NodeItem(&Item { node: ItemTrait(..), .. }) => id,
NodeTyParam(_) => self.get_parent_node(id), NodeGenericParam(_) => self.get_parent_node(id),
_ => { _ => {
bug!("ty_param_owner: {} not a type parameter", bug!("ty_param_owner: {} not a type parameter",
self.node_to_string(id)) self.node_to_string(id))
@ -613,7 +613,7 @@ impl<'hir> Map<'hir> {
NodeItem(&Item { node: ItemTrait(..), .. }) => { NodeItem(&Item { node: ItemTrait(..), .. }) => {
keywords::SelfType.name() keywords::SelfType.name()
} }
NodeTyParam(tp) => tp.name, NodeGenericParam(param) => param.name(),
_ => { _ => {
bug!("ty_param_name: {} not a type parameter", bug!("ty_param_name: {} not a type parameter",
self.node_to_string(id)) self.node_to_string(id))
@ -954,7 +954,7 @@ impl<'hir> Map<'hir> {
NodeVariant(v) => v.node.name, NodeVariant(v) => v.node.name,
NodeField(f) => f.ident.name, NodeField(f) => f.ident.name,
NodeLifetime(lt) => lt.name.name(), NodeLifetime(lt) => lt.name.name(),
NodeTyParam(tp) => tp.name, NodeGenericParam(param) => param.name(),
NodeBinding(&Pat { node: PatKind::Binding(_,_,l,_), .. }) => l.node, NodeBinding(&Pat { node: PatKind::Binding(_,_,l,_), .. }) => l.node,
NodeStructCtor(_) => self.name(self.get_parent(id)), NodeStructCtor(_) => self.name(self.get_parent(id)),
_ => bug!("no name for {}", self.node_to_string(id)) _ => bug!("no name for {}", self.node_to_string(id))
@ -974,7 +974,12 @@ impl<'hir> Map<'hir> {
Some(NodeField(ref f)) => Some(&f.attrs[..]), Some(NodeField(ref f)) => Some(&f.attrs[..]),
Some(NodeExpr(ref e)) => Some(&*e.attrs), Some(NodeExpr(ref e)) => Some(&*e.attrs),
Some(NodeStmt(ref s)) => Some(s.node.attrs()), Some(NodeStmt(ref s)) => Some(s.node.attrs()),
Some(NodeTyParam(tp)) => Some(&tp.attrs[..]), Some(NodeGenericParam(param)) => {
match param.kind {
GenericParamKind::Type { ref attrs, .. } => Some(&attrs[..]),
_ => bug!("unexpected non-type NodeGenericParam")
}
}
// unit/tuple structs take the attributes straight from // unit/tuple structs take the attributes straight from
// the struct definition. // the struct definition.
Some(NodeStructCtor(_)) => { Some(NodeStructCtor(_)) => {
@ -1021,7 +1026,7 @@ impl<'hir> Map<'hir> {
Some(EntryBlock(_, _, block)) => block.span, Some(EntryBlock(_, _, block)) => block.span,
Some(EntryStructCtor(_, _, _)) => self.expect_item(self.get_parent(id)).span, Some(EntryStructCtor(_, _, _)) => self.expect_item(self.get_parent(id)).span,
Some(EntryLifetime(_, _, lifetime)) => lifetime.span, Some(EntryLifetime(_, _, lifetime)) => lifetime.span,
Some(EntryTyParam(_, _, ty_param)) => ty_param.span, Some(EntryGenericParam(_, _, param)) => param.span,
Some(EntryVisibility(_, _, &Visibility::Restricted { ref path, .. })) => path.span, Some(EntryVisibility(_, _, &Visibility::Restricted { ref path, .. })) => path.span,
Some(EntryVisibility(_, _, v)) => bug!("unexpected Visibility {:?}", v), Some(EntryVisibility(_, _, v)) => bug!("unexpected Visibility {:?}", v),
Some(EntryLocal(_, _, local)) => local.span, Some(EntryLocal(_, _, local)) => local.span,
@ -1249,7 +1254,7 @@ impl<'a> print::State<'a> {
} }
NodeLifetime(a) => self.print_lifetime(&a), NodeLifetime(a) => self.print_lifetime(&a),
NodeVisibility(a) => self.print_visibility(&a), NodeVisibility(a) => self.print_visibility(&a),
NodeTyParam(_) => bug!("cannot print TyParam"), NodeGenericParam(_) => bug!("cannot print NodeGenericParam"),
NodeField(_) => bug!("cannot print StructField"), NodeField(_) => bug!("cannot print StructField"),
// these cases do not carry enough information in the // these cases do not carry enough information in the
// hir_map to reconstruct their full structure for pretty // hir_map to reconstruct their full structure for pretty
@ -1371,8 +1376,8 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
Some(NodeLifetime(_)) => { Some(NodeLifetime(_)) => {
format!("lifetime {}{}", map.node_to_pretty_string(id), id_str) format!("lifetime {}{}", map.node_to_pretty_string(id), id_str)
} }
Some(NodeTyParam(ref ty_param)) => { Some(NodeGenericParam(ref param)) => {
format!("typaram {:?}{}", ty_param, id_str) format!("genericparam {:?}{}", param, id_str)
} }
Some(NodeVisibility(ref vis)) => { Some(NodeVisibility(ref vis)) => {
format!("visibility {:?}{}", vis, id_str) format!("visibility {:?}{}", vis, id_str)

View file

@ -53,8 +53,6 @@ use rustc_data_structures::sync::{ParallelIterator, par_iter, Send, Sync, scope}
use serialize::{self, Encoder, Encodable, Decoder, Decodable}; use serialize::{self, Encoder, Encodable, Decoder, Decodable};
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::fmt; 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. /// 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 /// It can be `Vec`, `P<[T]>` or potentially `Box<[T]>`, or some other container with similar
@ -242,6 +240,24 @@ impl LifetimeName {
Name(name) => name, Name(name) => name,
} }
} }
fn is_elided(&self) -> bool {
use self::LifetimeName::*;
match self {
Implicit | Underscore => true,
// It might seem surprising that `Fresh(_)` counts as
// *not* elided -- but this is because, as far as the code
// in the compiler is concerned -- `Fresh(_)` variants act
// equivalently to "some fresh name". They correspond to
// early-bound regions on an impl, in other words.
Fresh(_) | Static | Name(_) => false,
}
}
fn is_static(&self) -> bool {
self == &LifetimeName::Static
}
} }
impl fmt::Debug for Lifetime { impl fmt::Debug for Lifetime {
@ -255,36 +271,14 @@ impl fmt::Debug for Lifetime {
impl Lifetime { impl Lifetime {
pub fn is_elided(&self) -> bool { pub fn is_elided(&self) -> bool {
use self::LifetimeName::*; self.name.is_elided()
match self.name {
Implicit | Underscore => true,
// It might seem surprising that `Fresh(_)` counts as
// *not* elided -- but this is because, as far as the code
// in the compiler is concerned -- `Fresh(_)` variants act
// equivalently to "some fresh name". They correspond to
// early-bound regions on an impl, in other words.
Fresh(_) | Static | Name(_) => false,
}
} }
pub fn is_static(&self) -> bool { pub fn is_static(&self) -> bool {
self.name == LifetimeName::Static self.name.is_static()
} }
} }
/// A lifetime definition, eg `'a: 'b+'c+'d`
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct LifetimeDef {
pub lifetime: Lifetime,
pub bounds: HirVec<Lifetime>,
pub pure_wrt_drop: bool,
// Indicates that the lifetime definition was synthetically added
// as a result of an in-band lifetime usage like
// `fn foo(x: &'a u8) -> &'a u8 { x }`
pub in_band: bool,
}
/// A "Path" is essentially Rust's notion of a name; for instance: /// A "Path" is essentially Rust's notion of a name; for instance:
/// `std::cmp::PartialEq`. It's represented as a sequence of identifiers, /// `std::cmp::PartialEq`. It's represented as a sequence of identifiers,
/// along with a bunch of supporting information. /// along with a bunch of supporting information.
@ -466,70 +460,62 @@ pub enum TraitBoundModifier {
pub type TyParamBounds = HirVec<TyParamBound>; pub type TyParamBounds = HirVec<TyParamBound>;
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct TyParam { pub enum GenericParamKind {
pub name: Name, /// A lifetime definition, eg `'a: 'b + 'c + 'd`.
pub id: NodeId, Lifetime {
pub bounds: TyParamBounds, /// Either "'a", referring to a named lifetime definition,
pub default: Option<P<Ty>>, /// or "" (aka keywords::Invalid), for elision placeholders.
pub span: Span, ///
pub pure_wrt_drop: bool, /// HIR lowering inserts these placeholders in type paths that
pub synthetic: Option<SyntheticTyParamKind>, /// refer to type definitions needing lifetime parameters,
pub attrs: HirVec<Attribute>, /// `&T` and `&mut T`, and trait objects without `... + 'a`.
name: LifetimeName,
bounds: HirVec<Lifetime>,
// Indicates that the lifetime definition was synthetically added
// as a result of an in-band lifetime usage like:
// `fn foo(x: &'a u8) -> &'a u8 { x }`
in_band: bool,
// We keep a `Lifetime` around for now just so we can `visit_lifetime`.
lifetime_deprecated: Lifetime,
},
Type {
name: Name,
bounds: TyParamBounds,
default: Option<P<Ty>>,
synthetic: Option<SyntheticTyParamKind>,
attrs: HirVec<Attribute>,
}
} }
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum GenericParam { pub struct GenericParam {
Lifetime(LifetimeDef), pub id: NodeId,
Type(TyParam), pub span: Span,
pub pure_wrt_drop: bool,
pub kind: GenericParamKind,
} }
impl GenericParam { impl GenericParam {
pub fn is_lifetime_param(&self) -> bool { pub fn is_lifetime_param(&self) -> bool {
match *self { match self.kind {
GenericParam::Lifetime(_) => true, GenericParamKind::Lifetime { .. } => true,
_ => false, _ => false,
} }
} }
pub fn is_type_param(&self) -> bool { pub fn is_type_param(&self) -> bool {
match *self { match self.kind {
GenericParam::Type(_) => true, GenericParamKind::Type { .. } => true,
_ => false, _ => false,
} }
} }
pub fn name(&self) -> Name {
match self.kind {
GenericParamKind::Lifetime { name, .. } => name.name(),
GenericParamKind::Type { name, .. } => name,
} }
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,
})
} }
} }
@ -555,54 +541,39 @@ impl Generics {
} }
pub fn is_lt_parameterized(&self) -> bool { pub fn is_lt_parameterized(&self) -> bool {
self.params.iter().any(|param| param.is_lifetime_param()) self.params.iter().any(|param| {
match param.kind {
GenericParamKind::Lifetime { .. } => true,
_ => false,
}
})
} }
pub fn is_type_parameterized(&self) -> bool { pub fn is_type_parameterized(&self) -> bool {
self.params.iter().any(|param| param.is_type_param()) self.params.iter().any(|param| {
match param.kind {
GenericParamKind::Type { .. } => true,
_ => false,
}
})
} }
pub fn lifetimes<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a LifetimeDef> { pub fn lifetimes<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a GenericParam> {
self.params.lifetimes() self.params.iter().filter(|param| {
match param.kind {
GenericParamKind::Lifetime { .. } => true,
_ => false,
}
})
} }
pub fn ty_params<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a TyParam> { pub fn ty_params<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a GenericParam> {
self.params.ty_params() self.params.iter().filter(|param| {
match param.kind {
GenericParamKind::Type { .. } => true,
_ => false,
} }
} })
pub enum UnsafeGeneric {
Region(LifetimeDef, &'static str),
Type(TyParam, &'static str),
}
impl UnsafeGeneric {
pub fn attr_name(&self) -> &'static str {
match *self {
UnsafeGeneric::Region(_, s) => s,
UnsafeGeneric::Type(_, s) => s,
}
}
}
impl Generics {
pub fn carries_unsafe_attr(&self) -> Option<UnsafeGeneric> {
for param in &self.params {
match *param {
GenericParam::Lifetime(ref l) => {
if l.pure_wrt_drop {
return Some(UnsafeGeneric::Region(l.clone(), "may_dangle"));
}
}
GenericParam::Type(ref t) => {
if t.pure_wrt_drop {
return Some(UnsafeGeneric::Type(t.clone(), "may_dangle"));
}
}
}
}
None
} }
} }

View file

@ -25,7 +25,7 @@ use syntax_pos::{self, BytePos, FileName};
use hir; use hir;
use hir::{PatKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier, RangeEnd}; use hir::{PatKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier, RangeEnd};
use hir::GenericArg; use hir::{GenericParam, GenericParamKind, GenericArg};
use std::cell::Cell; use std::cell::Cell;
use std::io::{self, Write, Read}; use std::io::{self, Write, Read};
@ -2094,30 +2094,12 @@ impl<'a> State<'a> {
Ok(()) Ok(())
} }
pub fn print_lifetime(&mut self, lifetime: &hir::Lifetime) -> io::Result<()> { pub fn print_generic_params(&mut self, generic_params: &[GenericParam]) -> io::Result<()> {
self.print_name(lifetime.name.name())
}
pub fn print_lifetime_def(&mut self, lifetime: &hir::LifetimeDef) -> io::Result<()> {
self.print_lifetime(&lifetime.lifetime)?;
let mut sep = ":";
for v in &lifetime.bounds {
self.s.word(sep)?;
self.print_lifetime(v)?;
sep = "+";
}
Ok(())
}
pub fn print_generic_params(&mut self, generic_params: &[hir::GenericParam]) -> io::Result<()> {
if !generic_params.is_empty() { if !generic_params.is_empty() {
self.s.word("<")?; self.s.word("<")?;
self.commasep(Inconsistent, generic_params, |s, param| { self.commasep(Inconsistent, generic_params, |s, param| {
match *param { s.print_generic_param(param)
hir::GenericParam::Lifetime(ref ld) => s.print_lifetime_def(ld),
hir::GenericParam::Type(ref tp) => s.print_ty_param(tp),
}
})?; })?;
self.s.word(">")?; self.s.word(">")?;
@ -2125,11 +2107,22 @@ impl<'a> State<'a> {
Ok(()) Ok(())
} }
pub fn print_ty_param(&mut self, param: &hir::TyParam) -> io::Result<()> { pub fn print_generic_param(&mut self, param: &GenericParam) -> io::Result<()> {
self.print_name(param.name)?; self.print_name(param.name())?;
self.print_bounds(":", &param.bounds)?; match param.kind {
match param.default { GenericParamKind::Lifetime { ref bounds, .. } => {
Some(ref default) => { let mut sep = ":";
for bound in bounds {
self.s.word(sep)?;
self.print_lifetime(bound)?;
sep = "+";
}
Ok(())
}
GenericParamKind::Type { ref bounds, ref default, .. } => {
self.print_bounds(":", bounds)?;
match default {
Some(default) => {
self.s.space()?; self.s.space()?;
self.word_space("=")?; self.word_space("=")?;
self.print_type(&default) self.print_type(&default)
@ -2137,6 +2130,12 @@ impl<'a> State<'a> {
_ => Ok(()), _ => Ok(()),
} }
} }
}
}
pub fn print_lifetime(&mut self, lifetime: &hir::Lifetime) -> io::Result<()> {
self.print_name(lifetime.name.name())
}
pub fn print_where_clause(&mut self, where_clause: &hir::WhereClause) -> io::Result<()> { pub fn print_where_clause(&mut self, where_clause: &hir::WhereClause) -> io::Result<()> {
if where_clause.predicates.is_empty() { if where_clause.predicates.is_empty() {

View file

@ -161,13 +161,6 @@ impl_stable_hash_for!(struct hir::Lifetime {
name name
}); });
impl_stable_hash_for!(struct hir::LifetimeDef {
lifetime,
bounds,
pure_wrt_drop,
in_band
});
impl_stable_hash_for!(struct hir::Path { impl_stable_hash_for!(struct hir::Path {
span, span,
def, def,
@ -201,21 +194,36 @@ impl_stable_hash_for!(enum hir::TraitBoundModifier {
Maybe Maybe
}); });
impl_stable_hash_for!(struct hir::TyParam { impl_stable_hash_for!(struct hir::GenericParam {
name,
id, id,
bounds,
default,
span, span,
pure_wrt_drop, pure_wrt_drop,
synthetic, kind
attrs
}); });
impl_stable_hash_for!(enum hir::GenericParam { impl<'a> HashStable<StableHashingContext<'a>> for hir::GenericParamKind {
Lifetime(lifetime_def), fn hash_stable<W: StableHasherResult>(&self,
Type(ty_param) hcx: &mut StableHashingContext<'a>,
}); hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match self {
hir::GenericParamKind::Lifetime { name, ref bounds, in_band,
ref lifetime_deprecated } => {
name.hash_stable(hcx, hasher);
bounds.hash_stable(hcx, hasher);
in_band.hash_stable(hcx, hasher);
lifetime_deprecated.hash_stable(hcx, hasher);
}
hir::GenericParamKind::Type { name, ref bounds, ref default, synthetic, attrs } => {
name.hash_stable(hcx, hasher);
bounds.hash_stable(hcx, hasher);
default.hash_stable(hcx, hasher);
synthetic.hash_stable(hcx, hasher);
attrs.hash_stable(hcx, hasher);
}
}
}
}
impl_stable_hash_for!(struct hir::Generics { impl_stable_hash_for!(struct hir::Generics {
params, params,

View file

@ -61,7 +61,7 @@ use super::region_constraints::GenericKind;
use super::lexical_region_resolve::RegionResolutionError; use super::lexical_region_resolve::RegionResolutionError;
use std::fmt; use std::fmt;
use hir; use hir::{self, GenericParamKind};
use hir::map as hir_map; use hir::map as hir_map;
use hir::def_id::DefId; use hir::def_id::DefId;
use middle::region; use middle::region;
@ -1036,8 +1036,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
// Get the `hir::TyParam` to verify whether it already has any bounds. // Get the `hir::TyParam` to verify whether it already has any bounds.
// We do this to avoid suggesting code that ends up as `T: 'a'b`, // We do this to avoid suggesting code that ends up as `T: 'a'b`,
// instead we suggest `T: 'a + 'b` in that case. // instead we suggest `T: 'a + 'b` in that case.
let has_lifetimes = if let hir_map::NodeTyParam(ref p) = hir.get(id) { let has_lifetimes =
p.bounds.len() > 0 if let hir_map::NodeGenericParam(ref param) = hir.get(id) {
match param.kind {
GenericParamKind::Type { ref bounds, .. } => {
!bounds.is_empty()
}
_ => bug!("unexpected non-type NodeGenericParam"),
}
} else { } else {
false false
}; };

View file

@ -35,7 +35,7 @@ use syntax_pos::Span;
use util::nodemap::{DefIdMap, FxHashMap, FxHashSet, NodeMap, NodeSet}; use util::nodemap::{DefIdMap, FxHashMap, FxHashSet, NodeMap, NodeSet};
use hir::intravisit::{self, NestedVisitorMap, Visitor}; use hir::intravisit::{self, NestedVisitorMap, Visitor};
use hir::{self, GenericParamsExt}; use hir::{self, GenericParamKind};
/// The origin of a named lifetime definition. /// The origin of a named lifetime definition.
/// ///
@ -86,20 +86,30 @@ impl Region {
fn early( fn early(
hir_map: &Map, hir_map: &Map,
index: &mut u32, index: &mut u32,
def: &hir::LifetimeDef, param: &hir::GenericParam,
) -> (hir::LifetimeName, Region) { ) -> (hir::LifetimeName, Region) {
let i = *index; let i = *index;
*index += 1; *index += 1;
let def_id = hir_map.local_def_id(def.lifetime.id); let def_id = hir_map.local_def_id(param.id);
let origin = LifetimeDefOrigin::from_is_in_band(def.in_band); let (name, origin) = match param.kind {
GenericParamKind::Lifetime { name, in_band, .. } => {
(name, LifetimeDefOrigin::from_is_in_band(in_band))
}
_ => bug!("expected a lifetime param"),
};
debug!("Region::early: index={} def_id={:?}", i, def_id); debug!("Region::early: index={} def_id={:?}", i, def_id);
(def.lifetime.name, Region::EarlyBound(i, def_id, origin)) (name, Region::EarlyBound(i, def_id, origin))
} }
fn late(hir_map: &Map, def: &hir::LifetimeDef) -> (hir::LifetimeName, Region) { fn late(hir_map: &Map, param: &hir::GenericParam) -> (hir::LifetimeName, Region) {
let depth = ty::INNERMOST; let depth = ty::INNERMOST;
let def_id = hir_map.local_def_id(def.lifetime.id); let def_id = hir_map.local_def_id(param.id);
let origin = LifetimeDefOrigin::from_is_in_band(def.in_band); let (name, origin) = match param.kind {
GenericParamKind::Lifetime { name, in_band, .. } => {
(name, LifetimeDefOrigin::from_is_in_band(in_band))
}
_ => bug!("expected a lifetime param"),
};
debug!( debug!(
"Region::late: def={:?} depth={:?} def_id={:?} origin={:?}", "Region::late: def={:?} depth={:?} def_id={:?} origin={:?}",
def, def,
@ -107,7 +117,7 @@ impl Region {
def_id, def_id,
origin, origin,
); );
(def.lifetime.name, Region::LateBound(depth, def_id, origin)) (name, Region::LateBound(depth, def_id, origin))
} }
fn late_anon(index: &Cell<u32>) -> Region { fn late_anon(index: &Cell<u32>) -> Region {
@ -567,8 +577,15 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
self.is_in_fn_syntax = true; self.is_in_fn_syntax = true;
let scope = Scope::Binder { let scope = Scope::Binder {
lifetimes: c.generic_params lifetimes: c.generic_params
.lifetimes() .iter()
.map(|def| Region::late(&self.tcx.hir, def)) .filter_map(|param| {
match param.kind {
GenericParamKind::Lifetime { .. } => {
Some(Region::late(&self.tcx.hir, param))
}
_ => None,
}
})
.collect(), .collect(),
s: self.scope, s: self.scope,
next_early_index, next_early_index,
@ -850,12 +867,17 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
self.tcx, self.tcx,
&generics.lifetimes().cloned().collect::<Vec<_>>(), &generics.lifetimes().cloned().collect::<Vec<_>>(),
); );
for ty_param in generics.ty_params() { for param in &generics.params {
walk_list!(self, visit_ty_param_bound, &ty_param.bounds); match param.kind {
if let Some(ref ty) = ty_param.default { GenericParamKind::Lifetime { .. } => {}
GenericParamKind::Type { ref bounds, ref default, .. } => {
walk_list!(self, visit_ty_param_bound, bounds);
if let Some(ref ty) = default {
self.visit_ty(&ty); self.visit_ty(&ty);
} }
} }
}
}
for predicate in &generics.where_clause.predicates { for predicate in &generics.where_clause.predicates {
match predicate { match predicate {
&hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
@ -869,8 +891,15 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
let next_early_index = self.next_early_index(); let next_early_index = self.next_early_index();
let scope = Scope::Binder { let scope = Scope::Binder {
lifetimes: bound_generic_params lifetimes: bound_generic_params
.lifetimes() .iter()
.map(|def| Region::late(&self.tcx.hir, def)) .filter_map(|param| {
match param.kind {
GenericParamKind::Lifetime { .. } => {
Some(Region::late(&self.tcx.hir, param))
}
_ => None,
}
})
.collect(), .collect(),
s: self.scope, s: self.scope,
next_early_index, next_early_index,
@ -936,8 +965,15 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
let scope = Scope::Binder { let scope = Scope::Binder {
lifetimes: trait_ref lifetimes: trait_ref
.bound_generic_params .bound_generic_params
.lifetimes() .iter()
.map(|def| Region::late(&self.tcx.hir, def)) .filter_map(|param| {
match param.kind {
GenericParamKind::Lifetime { .. } => {
Some(Region::late(&self.tcx.hir, param))
}
_ => None,
}
})
.collect(), .collect(),
s: self.scope, s: self.scope,
next_early_index, next_early_index,
@ -987,10 +1023,10 @@ fn original_lifetime(span: Span) -> Original {
span: span, span: span,
} }
} }
fn shadower_lifetime(l: &hir::Lifetime) -> Shadower { fn shadower_lifetime(param: &hir::GenericParam) -> Shadower {
Shadower { Shadower {
kind: ShadowKind::Lifetime, kind: ShadowKind::Lifetime,
span: l.span, span: param.span,
} }
} }
@ -1005,22 +1041,28 @@ impl ShadowKind {
fn check_mixed_explicit_and_in_band_defs( fn check_mixed_explicit_and_in_band_defs(
tcx: TyCtxt<'_, '_, '_>, tcx: TyCtxt<'_, '_, '_>,
lifetime_defs: &[hir::LifetimeDef], params: &[hir::GenericParam],
) { ) {
let oob_def = lifetime_defs.iter().find(|lt| !lt.in_band); let in_bands: Vec<_> = params.iter().map(|param| {
let in_band_def = lifetime_defs.iter().find(|lt| lt.in_band); match param.kind {
GenericParamKind::Lifetime { in_band, .. } => (in_band, param.span),
_ => bug!("expected lifetime param"),
}
}).collect();
let out_of_band = in_bands.iter().find(|(in_band, _)| !in_band);
let in_band = in_bands.iter().find(|(in_band, _)| *in_band);
if let (Some(oob_def), Some(in_band_def)) = (oob_def, in_band_def) { if let (Some((_, out_of_band_span)), Some((_, in_band_span)))
= (out_of_band, in_band) {
struct_span_err!( struct_span_err!(
tcx.sess, tcx.sess,
in_band_def.lifetime.span, *in_band_span,
E0688, E0688,
"cannot mix in-band and explicit lifetime definitions" "cannot mix in-band and explicit lifetime definitions"
).span_label( ).span_label(
in_band_def.lifetime.span, *in_band_span,
"in-band lifetime definition here", "in-band lifetime definition here",
) ).span_label(*out_of_band_span, "explicit lifetime definition here")
.span_label(oob_def.lifetime.span, "explicit lifetime definition here")
.emit(); .emit();
} }
} }
@ -1178,8 +1220,6 @@ fn compute_object_lifetime_defaults(
.lifetimes() .lifetimes()
.nth(i as usize) .nth(i as usize)
.unwrap() .unwrap()
.lifetime
.name
.name() .name()
.to_string(), .to_string(),
Set1::One(_) => bug!(), Set1::One(_) => bug!(),
@ -1213,12 +1253,13 @@ fn object_lifetime_defaults_for_item(
} }
} }
generics generics.params.iter().filter_map(|param| {
.ty_params() match param.kind {
.map(|param| { GenericParamKind::Lifetime { .. } => None,
GenericParamKind::Type { ref bounds, .. } => {
let mut set = Set1::Empty; let mut set = Set1::Empty;
add_bounds(&mut set, &param.bounds); add_bounds(&mut set, &bounds);
let param_def_id = tcx.hir.local_def_id(param.id); let param_def_id = tcx.hir.local_def_id(param.id);
for predicate in &generics.where_clause.predicates { for predicate in &generics.where_clause.predicates {
@ -1244,24 +1285,32 @@ fn object_lifetime_defaults_for_item(
} }
} }
match set { Some(match set {
Set1::Empty => Set1::Empty, Set1::Empty => Set1::Empty,
Set1::One(name) => { Set1::One(name) => {
if name == hir::LifetimeName::Static { if name == hir::LifetimeName::Static {
Set1::One(Region::Static) Set1::One(Region::Static)
} else { } else {
generics generics.params.iter().filter_map(|param| {
.lifetimes() match param.kind {
GenericParamKind::Lifetime { name, in_band, .. } => {
Some((param.id, name, in_band))
}
_ => None,
}
})
.enumerate() .enumerate()
.find(|&(_, def)| def.lifetime.name == name) .find(|&(_, (_, lt_name, _))| lt_name == name)
.map_or(Set1::Many, |(i, def)| { .map_or(Set1::Many, |(i, (id, _, in_band))| {
let def_id = tcx.hir.local_def_id(def.lifetime.id); let def_id = tcx.hir.local_def_id(id);
let origin = LifetimeDefOrigin::from_is_in_band(def.in_band); let origin = LifetimeDefOrigin::from_is_in_band(in_band);
Set1::One(Region::EarlyBound(i as u32, def_id, origin)) Set1::One(Region::EarlyBound(i as u32, def_id, origin))
}) })
} }
} }
Set1::Many => Set1::Many, Set1::Many => Set1::Many,
})
}
} }
}) })
.collect() .collect()
@ -1438,11 +1487,11 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
let lifetimes = generics let lifetimes = generics
.lifetimes() .lifetimes()
.map(|def| { .map(|param| {
if self.map.late_bound.contains(&def.lifetime.id) { if self.map.late_bound.contains(&param.id) {
Region::late(&self.tcx.hir, def) Region::late(&self.tcx.hir, param)
} else { } else {
Region::early(&self.tcx.hir, &mut index, def) Region::early(&self.tcx.hir, &mut index, param)
} }
}) })
.collect(); .collect();
@ -1943,7 +1992,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
} }
fn visit_generic_param(&mut self, param: &hir::GenericParam) { fn visit_generic_param(&mut self, param: &hir::GenericParam) {
if let hir::GenericParam::Lifetime(_) = *param { if let hir::GenericParamKind::Lifetime { .. } = param.kind {
// FIXME(eddyb) Do we want this? It only makes a difference // FIXME(eddyb) Do we want this? It only makes a difference
// if this `for<'a>` lifetime parameter is never used. // if this `for<'a>` lifetime parameter is never used.
self.have_bound_regions = true; self.have_bound_regions = true;
@ -2160,20 +2209,26 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
} }
fn check_lifetime_params(&mut self, old_scope: ScopeRef, params: &'tcx [hir::GenericParam]) { fn check_lifetime_params(&mut self, old_scope: ScopeRef, params: &'tcx [hir::GenericParam]) {
for (i, lifetime_i) in params.lifetimes().enumerate() { let lifetimes: Vec<_> = params.iter().filter_map(|param| {
match lifetime_i.lifetime.name { match param.kind {
GenericParamKind::Lifetime { name, .. } => Some((param, name)),
_ => None,
}
}).collect();
for (i, (lifetime_i, lifetime_i_name)) in lifetimes.iter().enumerate() {
match lifetime_i_name {
hir::LifetimeName::Static | hir::LifetimeName::Underscore => { hir::LifetimeName::Static | hir::LifetimeName::Underscore => {
let lifetime = lifetime_i.lifetime; let lifetime = lifetime_i.lifetime;
let name = lifetime.name.name(); let name = lifetime_i.name();
let mut err = struct_span_err!( let mut err = struct_span_err!(
self.tcx.sess, self.tcx.sess,
lifetime.span, lifetime_i.span,
E0262, E0262,
"invalid lifetime parameter name: `{}`", "invalid lifetime parameter name: `{}`",
name name
); );
err.span_label( err.span_label(
lifetime.span, lifetime_i.span,
format!("{} is a reserved lifetime name", name), format!("{} is a reserved lifetime name", name),
); );
err.emit(); err.emit();
@ -2184,24 +2239,28 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
} }
// It is a hard error to shadow a lifetime within the same scope. // It is a hard error to shadow a lifetime within the same scope.
for lifetime_j in params.lifetimes().skip(i + 1) { for (lifetime_j, lifetime_j_name) in lifetimes.iter().skip(i + 1) {
if lifetime_i.lifetime.name == lifetime_j.lifetime.name { if lifetime_i_name == lifetime_j_name {
struct_span_err!( struct_span_err!(
self.tcx.sess, self.tcx.sess,
lifetime_j.lifetime.span, lifetime_j.span,
E0263, E0263,
"lifetime name `{}` declared twice in the same scope", "lifetime name `{}` declared twice in the same scope",
lifetime_j.lifetime.name.name() lifetime_j.name()
).span_label(lifetime_j.lifetime.span, "declared twice") ).span_label(lifetime_j.span, "declared twice")
.span_label(lifetime_i.lifetime.span, "previous declaration here") .span_label(lifetime_i.span, "previous declaration here")
.emit(); .emit();
} }
} }
// It is a soft error to shadow a lifetime within a parent scope. // It is a soft error to shadow a lifetime within a parent scope.
self.check_lifetime_def_for_shadowing(old_scope, &lifetime_i.lifetime); self.check_lifetime_param_for_shadowing(old_scope, &lifetime_i);
for bound in &lifetime_i.bounds { let bounds = match lifetime_i.kind {
GenericParamKind::Lifetime { ref bounds, .. } => bounds,
_ => bug!(),
};
for bound in bounds {
match bound.name { match bound.name {
hir::LifetimeName::Underscore => { hir::LifetimeName::Underscore => {
let mut err = struct_span_err!( let mut err = struct_span_err!(
@ -2218,16 +2277,16 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
self.tcx self.tcx
.sess .sess
.struct_span_warn( .struct_span_warn(
lifetime_i.lifetime.span.to(bound.span), lifetime_i.span.to(bound.span),
&format!( &format!(
"unnecessary lifetime parameter `{}`", "unnecessary lifetime parameter `{}`",
lifetime_i.lifetime.name.name() lifetime_i.name()
), ),
) )
.help(&format!( .help(&format!(
"you can use the `'static` lifetime directly, in place \ "you can use the `'static` lifetime directly, in place \
of `{}`", of `{}`",
lifetime_i.lifetime.name.name() lifetime_i.name()
)) ))
.emit(); .emit();
} }
@ -2241,24 +2300,29 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
} }
} }
fn check_lifetime_def_for_shadowing( fn check_lifetime_param_for_shadowing(
&self, &self,
mut old_scope: ScopeRef, mut old_scope: ScopeRef,
lifetime: &'tcx hir::Lifetime, param: &'tcx hir::GenericParam,
) { ) {
for &(label, label_span) in &self.labels_in_fn { for &(label, label_span) in &self.labels_in_fn {
// FIXME (#24278): non-hygienic comparison // FIXME (#24278): non-hygienic comparison
if lifetime.name.name() == label { if param.name() == label {
signal_shadowing_problem( signal_shadowing_problem(
self.tcx, self.tcx,
label, label,
original_label(label_span), original_label(label_span),
shadower_lifetime(&lifetime), shadower_lifetime(&param),
); );
return; return;
} }
} }
let name = match param.kind {
GenericParamKind::Lifetime { name, .. } => name,
_ => bug!("expected lifetime param"),
};
loop { loop {
match *old_scope { match *old_scope {
Scope::Body { s, .. } Scope::Body { s, .. }
@ -2274,14 +2338,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
Scope::Binder { Scope::Binder {
ref lifetimes, s, .. ref lifetimes, s, ..
} => { } => {
if let Some(&def) = lifetimes.get(&lifetime.name) { if let Some(&def) = lifetimes.get(&name) {
let node_id = self.tcx.hir.as_local_node_id(def.id().unwrap()).unwrap(); let node_id = self.tcx.hir.as_local_node_id(def.id().unwrap()).unwrap();
signal_shadowing_problem( signal_shadowing_problem(
self.tcx, self.tcx,
lifetime.name.name(), param.name(),
original_lifetime(self.tcx.hir.span(node_id)), original_lifetime(self.tcx.hir.span(node_id)),
shadower_lifetime(&lifetime), shadower_lifetime(&param),
); );
return; return;
} }
@ -2429,14 +2493,14 @@ fn insert_late_bound_lifetimes(
appears_in_where_clause.visit_generics(generics); appears_in_where_clause.visit_generics(generics);
for param in &generics.params { for param in &generics.params {
match *param { match param.kind {
hir::GenericParam::Lifetime(ref lifetime_def) => { hir::GenericParamKind::Lifetime { ref bounds, .. } => {
if !lifetime_def.bounds.is_empty() { if !bounds.is_empty() {
// `'a: 'b` means both `'a` and `'b` are referenced // `'a: 'b` means both `'a` and `'b` are referenced
appears_in_where_clause.regions.insert(lifetime_def.lifetime.name); appears_in_where_clause.regions.insert(lifetime_def.lifetime.name);
} }
} }
hir::GenericParam::Type(_) => {} hir::GenericParamKind::Type { .. } => {}
} }
} }
@ -2450,7 +2514,10 @@ fn insert_late_bound_lifetimes(
// - do not appear in the where-clauses // - do not appear in the where-clauses
// - are not implicitly captured by `impl Trait` // - are not implicitly captured by `impl Trait`
for lifetime in generics.lifetimes() { for lifetime in generics.lifetimes() {
let name = lifetime.lifetime.name; let name = match lifetime.kind {
GenericParamKind::Lifetime { name, .. } => name,
_ => bug!(),
};
// appears in the where clauses? early-bound. // appears in the where clauses? early-bound.
if appears_in_where_clause.regions.contains(&name) { if appears_in_where_clause.regions.contains(&name) {
@ -2464,18 +2531,12 @@ fn insert_late_bound_lifetimes(
continue; continue;
} }
debug!( debug!("insert_late_bound_lifetimes: lifetime {:?} with id {:?} is late-bound",
"insert_late_bound_lifetimes: \ name,
lifetime {:?} with id {:?} is late-bound", lifetime.id);
lifetime.lifetime.name, lifetime.lifetime.id
);
let inserted = map.late_bound.insert(lifetime.lifetime.id); let inserted = map.late_bound.insert(lifetime.id);
assert!( assert!(inserted, "visited lifetime {:?} twice", lifetime.id);
inserted,
"visited lifetime {:?} twice",
lifetime.lifetime.id
);
} }
return; return;

View file

@ -18,7 +18,7 @@ use syntax::ast;
use syntax::attr; use syntax::attr;
use syntax_pos::Span; use syntax_pos::Span;
use rustc::hir::{self, PatKind}; use rustc::hir::{self, GenericParamKind, PatKind};
use rustc::hir::intravisit::FnKind; use rustc::hir::intravisit::FnKind;
#[derive(PartialEq)] #[derive(PartialEq)]
@ -147,9 +147,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCamelCaseTypes {
} }
fn check_generic_param(&mut self, cx: &LateContext, param: &hir::GenericParam) { fn check_generic_param(&mut self, cx: &LateContext, param: &hir::GenericParam) {
if let hir::GenericParam::Type(ref gen) = *param { match param.kind {
if gen.synthetic.is_none() { GenericParamKind::Lifetime { .. } => {}
self.check_case(cx, "type parameter", gen.name, gen.span); GenericParamKind::Type { synthetic, .. } => {
if synthetic.is_none() {
self.check_case(cx, "type parameter", param.name(), param.span);
}
} }
} }
} }
@ -253,13 +256,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase {
} }
fn check_generic_param(&mut self, cx: &LateContext, param: &hir::GenericParam) { fn check_generic_param(&mut self, cx: &LateContext, param: &hir::GenericParam) {
if let hir::GenericParam::Lifetime(ref ld) = *param { match param.kind {
self.check_snake_case( GenericParamKind::Lifetime { .. } => {
cx, self.check_snake_case(cx, "lifetime", &param.name().as_str(), Some(param.span));
"lifetime", }
&ld.lifetime.name.name().as_str(), GenericParamKind::Type { .. } => {}
Some(ld.lifetime.span)
);
} }
} }

View file

@ -49,7 +49,7 @@ use syntax_pos::{BytePos, Span, SyntaxContext};
use syntax::symbol::keywords; use syntax::symbol::keywords;
use syntax::errors::{Applicability, DiagnosticBuilder}; use syntax::errors::{Applicability, DiagnosticBuilder};
use rustc::hir::{self, PatKind}; use rustc::hir::{self, GenericParamKind, PatKind};
use rustc::hir::intravisit::FnKind; use rustc::hir::intravisit::FnKind;
use bad_style::{MethodLateContext, method_context}; use bad_style::{MethodLateContext, method_context};
@ -1531,9 +1531,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeAliasBounds {
} }
// The parameters must not have bounds // The parameters must not have bounds
for param in type_alias_generics.params.iter() { for param in type_alias_generics.params.iter() {
let spans : Vec<_> = match param { let spans: Vec<_> = match param.kind {
&hir::GenericParam::Lifetime(ref l) => l.bounds.iter().map(|b| b.span).collect(), GenericParamKind::Lifetime { ref bounds, .. } => {
&hir::GenericParam::Type(ref ty) => ty.bounds.iter().map(|b| b.span()).collect(), bounds.iter().map(|b| b.span).collect()
}
GenericParamKind::Type { ref bounds, .. } => {
bounds.iter().map(|b| b.span()).collect()
}
}; };
if !spans.is_empty() { if !spans.is_empty() {
let mut err = cx.struct_span_lint( let mut err = cx.struct_span_lint(

View file

@ -1645,10 +1645,17 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
} }
fn encode_info_for_generics(&mut self, generics: &hir::Generics) { fn encode_info_for_generics(&mut self, generics: &hir::Generics) {
for ty_param in generics.ty_params() { for param in &generics.params {
let def_id = self.tcx.hir.local_def_id(ty_param.id); match param.kind {
let has_default = Untracked(ty_param.default.is_some()); hir::GenericParamKind::Lifetime { .. } => {}
self.record(def_id, IsolatedEncoder::encode_info_for_ty_param, (def_id, has_default)); hir::GenericParamKind::Type { ref default, .. } => {
let def_id = self.tcx.hir.local_def_id(param.id);
let has_default = Untracked(default.is_some());
self.record(def_id,
IsolatedEncoder::encode_info_for_ty_param,
(def_id, has_default));
}
}
} }
} }

View file

@ -22,7 +22,7 @@ extern crate rustc_typeck;
extern crate syntax_pos; extern crate syntax_pos;
extern crate rustc_data_structures; extern crate rustc_data_structures;
use rustc::hir::{self, PatKind}; use rustc::hir::{self, GenericParamKind, PatKind};
use rustc::hir::def::Def; use rustc::hir::def::Def;
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId}; use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId};
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
@ -1268,9 +1268,14 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
} }
fn visit_generics(&mut self, generics: &'tcx hir::Generics) { fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
for ty_param in generics.ty_params() { for param in &generics.params {
for bound in ty_param.bounds.iter() { match param.kind {
self.check_ty_param_bound(bound) GenericParamKind::Lifetime { .. } => {}
GenericParamKind::Type { ref bounds, .. } => {
for bound in bounds {
self.check_ty_param_bound(bound);
}
}
} }
} }
for predicate in &generics.where_clause.predicates { for predicate in &generics.where_clause.predicates {

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use rustc::hir::{self, ImplItemKind, TraitItemKind}; use rustc::hir::{self, GenericParamKind, ImplItemKind, TraitItemKind};
use rustc::infer::{self, InferOk}; use rustc::infer::{self, InferOk};
use rustc::ty::{self, TyCtxt, GenericParamDefKind}; use rustc::ty::{self, TyCtxt, GenericParamDefKind};
use rustc::ty::util::ExplicitSelf; use rustc::ty::util::ExplicitSelf;
@ -843,19 +843,19 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
} }
let span = visitor.0?; let span = visitor.0?;
let param = impl_m.generics.params.iter().filter_map(|param| { let bounds = impl_m.generics.params.iter().find_map(|param| {
match param { match param.kind {
hir::GenericParam::Type(param) => { GenericParamKind::Lifetime { .. } => None,
GenericParamKind::Type { ref bounds, .. } => {
if param.id == impl_node_id { if param.id == impl_node_id {
Some(param) Some(bounds)
} else { } else {
None None
} }
},
hir::GenericParam::Lifetime(..) => None,
} }
}).next()?; }
let bounds = param.bounds.first()?.span().to(param.bounds.last()?.span()); })?;
let bounds = bounds.first()?.span().to(bounds.last()?.span());
let bounds = tcx let bounds = tcx
.sess .sess
.codemap() .codemap()

View file

@ -5188,9 +5188,8 @@ 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 { if !used {
struct_span_err!(tcx.sess, param.span, E0091, struct_span_err!(tcx.sess, param.span, E0091, "type parameter `{}` is unused",
"type parameter `{}` is unused", param.name())
param.name)
.span_label(param.span, "unused type parameter") .span_label(param.span, "unused type parameter")
.emit(); .emit();
} }

View file

@ -631,11 +631,8 @@ fn check_variances_for_type_defn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
continue; continue;
} }
let (span, name) = match ast_generics.params[index] { let param = &ast_generics.params[index];
hir::GenericParam::Lifetime(ref ld) => (ld.lifetime.span, ld.lifetime.name.name()), report_bivariance(tcx, param.span, param.name());
hir::GenericParam::Type(ref tp) => (tp.span, tp.name),
};
report_bivariance(tcx, span, name);
} }
} }

View file

@ -35,7 +35,14 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> {
Some(trait_ref) => { Some(trait_ref) => {
let trait_def = self.tcx.trait_def(trait_ref.def_id); let trait_def = self.tcx.trait_def(trait_ref.def_id);
let unsafe_attr = impl_generics.and_then(|g| g.carries_unsafe_attr()); let unsafe_attr = impl_generics.and_then(|g| {
for param in &g.params {
if param.pure_wrt_drop {
return Some("may_dangle");
}
}
None
});
match (trait_def.unsafety, unsafe_attr, unsafety, polarity) { match (trait_def.unsafety, unsafe_attr, unsafety, polarity) {
(Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => { (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
span_err!(self.tcx.sess, span_err!(self.tcx.sess,
@ -53,13 +60,14 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> {
trait_ref); trait_ref);
} }
(Unsafety::Normal, Some(g), Unsafety::Normal, hir::ImplPolarity::Positive) => (Unsafety::Normal, Some(attr_name), Unsafety::Normal,
hir::ImplPolarity::Positive) =>
{ {
span_err!(self.tcx.sess, span_err!(self.tcx.sess,
item.span, item.span,
E0569, E0569,
"requires an `unsafe impl` declaration due to `#[{}]` attribute", "requires an `unsafe impl` declaration due to `#[{}]` attribute",
g.attr_name()); attr_name);
} }
(_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => { (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => {

View file

@ -49,6 +49,7 @@ use syntax::feature_gate;
use syntax_pos::{Span, DUMMY_SP}; use syntax_pos::{Span, DUMMY_SP};
use rustc::hir::{self, map as hir_map, CodegenFnAttrs, CodegenFnAttrFlags, Unsafety}; use rustc::hir::{self, map as hir_map, CodegenFnAttrs, CodegenFnAttrFlags, Unsafety};
use rustc::hir::GenericParamKind;
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::hir::def::{Def, CtorKind}; use rustc::hir::def::{Def, CtorKind};
use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::hir::def_id::{DefId, LOCAL_CRATE};
@ -113,12 +114,17 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> {
} }
fn visit_generics(&mut self, generics: &'tcx hir::Generics) { fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
for param in generics.ty_params() { for param in &generics.params {
if param.default.is_some() { match param.kind {
hir::GenericParamKind::Lifetime { .. } => {}
hir::GenericParamKind::Type { ref default, .. } => {
if default.is_some() {
let def_id = self.tcx.hir.local_def_id(param.id); let def_id = self.tcx.hir.local_def_id(param.id);
self.tcx.type_of(def_id); self.tcx.type_of(def_id);
} }
} }
}
}
intravisit::walk_generics(self, generics); intravisit::walk_generics(self, generics);
} }
@ -308,9 +314,20 @@ impl<'a, 'tcx> ItemCtxt<'a, 'tcx> {
-> Vec<ty::Predicate<'tcx>> -> Vec<ty::Predicate<'tcx>>
{ {
let from_ty_params = let from_ty_params =
ast_generics.ty_params() ast_generics.params.iter()
.filter(|p| p.id == param_id) .filter_map(|param| {
.flat_map(|p| p.bounds.iter()) match param.kind {
GenericParamKind::Type { ref bounds, .. } => {
if param.id == param_id {
Some(bounds)
} else {
None
}
}
_ => None
}
})
.flat_map(|bounds| bounds.iter())
.flat_map(|b| predicates_from_bound(self, ty, b)); .flat_map(|b| predicates_from_bound(self, ty, b));
let from_where_clauses = let from_where_clauses =
@ -740,9 +757,9 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
has_late_bound_regions: None, 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); let hir_id = tcx.hir.node_to_hir_id(lifetime.id);
if tcx.is_late_bound(hir_id) { if tcx.is_late_bound(hir_id) {
return Some(lifetime.lifetime.span); return Some(lifetime.span);
} }
} }
visitor.visit_fn_decl(decl); visitor.visit_fn_decl(decl);
@ -883,12 +900,12 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let mut params: Vec<_> = opt_self.into_iter().collect(); let mut params: Vec<_> = opt_self.into_iter().collect();
let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics); let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics);
params.extend(early_lifetimes.enumerate().map(|(i, l)| { params.extend(early_lifetimes.enumerate().map(|(i, param)| {
ty::GenericParamDef { ty::GenericParamDef {
name: l.lifetime.name.name().as_interned_str(), name: param.name().as_interned_str(),
index: own_start + i as u32, index: own_start + i as u32,
def_id: tcx.hir.local_def_id(l.lifetime.id), def_id: tcx.hir.local_def_id(param.id),
pure_wrt_drop: l.pure_wrt_drop, pure_wrt_drop: param.pure_wrt_drop,
kind: ty::GenericParamDefKind::Lifetime, kind: ty::GenericParamDefKind::Lifetime,
} }
})); }));
@ -898,34 +915,40 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// Now create the real type parameters. // Now create the real type parameters.
let type_start = own_start - has_self as u32 + params.len() as u32; let type_start = own_start - has_self as u32 + params.len() as u32;
params.extend(ast_generics.ty_params().enumerate().map(|(i, p)| { params.extend(ast_generics.ty_params().enumerate().map(|(i, param)| {
if p.name == keywords::SelfType.name() { match param.kind {
span_bug!(p.span, "`Self` should not be the name of a regular parameter"); GenericParamKind::Type { ref default, synthetic, .. } => {
if param.name() == keywords::SelfType.name() {
span_bug!(param.span,
"`Self` should not be the name of a regular parameter");
} }
if !allow_defaults && p.default.is_some() { if !allow_defaults && default.is_some() {
if !tcx.features().default_type_parameter_fallback { if !tcx.features().default_type_parameter_fallback {
tcx.lint_node( tcx.lint_node(
lint::builtin::INVALID_TYPE_PARAM_DEFAULT, lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
p.id, param.id,
p.span, param.span,
&format!("defaults for type parameters are only allowed in `struct`, \ &format!("defaults for type parameters are only allowed in \
`enum`, `type`, or `trait` definitions.")); `struct`, `enum`, `type`, or `trait` definitions."));
} }
} }
ty::GenericParamDef { ty::GenericParamDef {
index: type_start + i as u32, index: type_start + i as u32,
name: p.name.as_interned_str(), name: param.name().as_interned_str(),
def_id: tcx.hir.local_def_id(p.id), def_id: tcx.hir.local_def_id(param.id),
pure_wrt_drop: p.pure_wrt_drop, pure_wrt_drop: param.pure_wrt_drop,
kind: ty::GenericParamDefKind::Type { kind: ty::GenericParamDefKind::Type {
has_default: p.default.is_some(), has_default: default.is_some(),
object_lifetime_default: object_lifetime_default:
object_lifetime_defaults.as_ref().map_or(rl::Set1::Empty, |o| o[i]), object_lifetime_defaults.as_ref().map_or(rl::Set1::Empty, |o| o[i]),
synthetic: p.synthetic, synthetic,
}, },
} }
}
_ => bug!()
}
})); }));
// provide junk type parameter defs - the only place that // provide junk type parameter defs - the only place that
@ -1119,9 +1142,14 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
} }
}, },
NodeTyParam(&hir::TyParam { default: Some(ref ty), .. }) => { NodeGenericParam(param) => {
match param.kind {
hir::GenericParamKind::Type { default: Some(ref ty), .. } => {
icx.to_ty(ty) icx.to_ty(ty)
} }
_ => bug!("unexpected non-type NodeGenericParam"),
}
}
x => { x => {
bug!("unexpected sort of node in type_of_def_id(): {:?}", x); bug!("unexpected sort of node in type_of_def_id(): {:?}", x);
@ -1274,14 +1302,17 @@ fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
/// `resolve_lifetime::early_bound_lifetimes`. /// `resolve_lifetime::early_bound_lifetimes`.
fn early_bound_lifetimes_from_generics<'a, 'tcx>( fn early_bound_lifetimes_from_generics<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
ast_generics: &'a hir::Generics) generics: &'a hir::Generics)
-> impl Iterator<Item=&'a hir::LifetimeDef> + Captures<'tcx> -> impl Iterator<Item=&'a hir::GenericParam> + Captures<'tcx>
{ {
ast_generics generics.params.iter().filter(move |param| {
.lifetimes() match param.kind {
.filter(move |l| { GenericParamKind::Lifetime { .. } => {
let hir_id = tcx.hir.node_to_hir_id(l.lifetime.id); let hir_id = tcx.hir.node_to_hir_id(param.id);
!tcx.is_late_bound(hir_id) !tcx.is_late_bound(hir_id)
}
_ => false,
}
}) })
} }
@ -1410,28 +1441,38 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let mut index = parent_count + has_own_self as u32; let mut index = parent_count + has_own_self as u32;
for param in early_bound_lifetimes_from_generics(tcx, ast_generics) { for param in early_bound_lifetimes_from_generics(tcx, ast_generics) {
let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
def_id: tcx.hir.local_def_id(param.lifetime.id), def_id: tcx.hir.local_def_id(param.id),
index, index,
name: param.lifetime.name.name().as_interned_str(), name: param.name().as_interned_str(),
})); }));
index += 1; index += 1;
for bound in &param.bounds { match param.kind {
GenericParamKind::Lifetime { ref bounds, .. } => {
for bound in bounds {
let bound_region = AstConv::ast_region_to_region(&icx, bound, None); let bound_region = AstConv::ast_region_to_region(&icx, bound, None);
let outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound_region)); let outlives =
ty::Binder::bind(ty::OutlivesPredicate(region, bound_region));
predicates.push(outlives.to_predicate()); predicates.push(outlives.to_predicate());
} }
},
_ => bug!(),
}
} }
// Collect the predicates that were written inline by the user on each // Collect the predicates that were written inline by the user on each
// type parameter (e.g., `<T:Foo>`). // 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.as_interned_str()).to_ty(tcx); let param_ty = ty::ParamTy::new(index, param.name().as_interned_str()).to_ty(tcx);
index += 1; index += 1;
let bounds = match param.kind {
GenericParamKind::Type { ref bounds, .. } => bounds,
_ => bug!(),
};
let bounds = compute_bounds(&icx, let bounds = compute_bounds(&icx,
param_ty, param_ty,
&param.bounds, bounds,
SizedByDefault::Yes, SizedByDefault::Yes,
param.span); param.span);
predicates.extend(bounds.predicates(tcx, param_ty)); predicates.extend(bounds.predicates(tcx, param_ty));

View file

@ -76,6 +76,7 @@ This API is completely unstable and subject to change.
#![feature(crate_visibility_modifier)] #![feature(crate_visibility_modifier)]
#![feature(from_ref)] #![feature(from_ref)]
#![feature(exhaustive_patterns)] #![feature(exhaustive_patterns)]
#![feature(iterator_find_map)]
#![feature(quote)] #![feature(quote)]
#![feature(refcell_replace_swap)] #![feature(refcell_replace_swap)]
#![feature(rustc_diagnostic_macros)] #![feature(rustc_diagnostic_macros)]

View file

@ -1466,14 +1466,19 @@ pub struct TyParam {
pub synthetic: Option<hir::SyntheticTyParamKind>, pub synthetic: Option<hir::SyntheticTyParamKind>,
} }
impl Clean<TyParam> for hir::TyParam { impl Clean<TyParam> for hir::GenericParam {
fn clean(&self, cx: &DocContext) -> TyParam { fn clean(&self, cx: &DocContext) -> TyParam {
match self.kind {
hir::GenericParamKind::Type { ref bounds, ref default, synthetic, .. } => {
TyParam { TyParam {
name: self.name.clean(cx), name: self.name().clean(cx),
did: cx.tcx.hir.local_def_id(self.id), did: cx.tcx.hir.local_def_id(self.id),
bounds: self.bounds.clean(cx), bounds: bounds.clean(cx),
default: self.default.clean(cx), default: default.clean(cx),
synthetic: self.synthetic, synthetic: synthetic,
}
}
_ => panic!(),
} }
} }
} }
@ -1707,18 +1712,21 @@ impl Clean<Lifetime> for hir::Lifetime {
} }
} }
impl Clean<Lifetime> for hir::LifetimeDef { impl Clean<Lifetime> for hir::GenericParam {
fn clean(&self, _: &DocContext) -> Lifetime { fn clean(&self, _: &DocContext) -> Lifetime {
if self.bounds.len() > 0 { match self.kind {
let mut s = format!("{}: {}", hir::GenericParamKind::Lifetime { ref bounds, .. } => {
self.lifetime.name.name(), if bounds.len() > 0 {
self.bounds[0].name.name()); let mut s = format!("{}: {}", self.name(), bounds[0].name.name());
for bound in self.bounds.iter().skip(1) { for bound in bounds.iter().skip(1) {
s.push_str(&format!(" + {}", bound.name.name())); s.push_str(&format!(" + {}", bound.name.name()));
} }
Lifetime(s) Lifetime(s)
} else { } else {
Lifetime(self.lifetime.name.name().to_string()) Lifetime(self.name().to_string())
}
}
_ => panic!(),
} }
} }
} }
@ -1880,9 +1888,11 @@ impl GenericParamDef {
impl Clean<GenericParamDef> for hir::GenericParam { impl Clean<GenericParamDef> for hir::GenericParam {
fn clean(&self, cx: &DocContext) -> GenericParamDef { fn clean(&self, cx: &DocContext) -> GenericParamDef {
match *self { match self.kind {
hir::GenericParam::Lifetime(ref l) => GenericParamDef::Lifetime(l.clean(cx)), hir::GenericParamKind::Lifetime { .. } => {
hir::GenericParam::Type(ref t) => GenericParamDef::Type(t.clean(cx)), GenericParamDef::Lifetime(self.clean(cx))
}
hir::GenericParamKind::Type { .. } => GenericParamDef::Type(self.clean(cx)),
} }
} }
} }
@ -1900,10 +1910,11 @@ impl Clean<Generics> for hir::Generics {
// In order for normal parameters to be able to refer to synthetic ones, // In order for normal parameters to be able to refer to synthetic ones,
// scans them first. // scans them first.
fn is_impl_trait(param: &hir::GenericParam) -> bool { fn is_impl_trait(param: &hir::GenericParam) -> bool {
if let hir::GenericParam::Type(ref tp) = param { match param.kind {
tp.synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) hir::GenericParamKind::Type { synthetic, .. } => {
} else { synthetic == Some(hir::SyntheticTyParamKind::ImplTrait)
false }
_ => false,
} }
} }
let impl_trait_params = self.params let impl_trait_params = self.params
@ -2857,25 +2868,25 @@ impl Clean<Type> for hir::Ty {
types: 0 types: 0
}; };
for param in generics.params.iter() { for param in generics.params.iter() {
match param { match param.kind {
hir::GenericParam::Lifetime(lt_param) => { hir::GenericParamKind::Lifetime { .. } => {
if let Some(lt) = generic_args.lifetimes() if let Some(lt) = generic_args.lifetimes()
.nth(indices.lifetimes).cloned() { .nth(indices.lifetimes).cloned() {
if !lt.is_elided() { if !lt.is_elided() {
let lt_def_id = let lt_def_id =
cx.tcx.hir.local_def_id(lt_param.lifetime.id); cx.tcx.hir.local_def_id(param.id);
lt_substs.insert(lt_def_id, lt.clean(cx)); lt_substs.insert(lt_def_id, lt.clean(cx));
} }
} }
indices.lifetimes += 1; indices.lifetimes += 1;
} }
hir::GenericParam::Type(ty_param) => { hir::GenericParamKind::Type { ref default, .. } => {
let ty_param_def = let ty_param_def =
Def::TyParam(cx.tcx.hir.local_def_id(ty_param.id)); Def::TyParam(cx.tcx.hir.local_def_id(param.id));
if let Some(ty) = generic_args.types() if let Some(ty) = generic_args.types()
.nth(indices.types).cloned() { .nth(indices.types).cloned() {
ty_substs.insert(ty_param_def, ty.into_inner().clean(cx)); ty_substs.insert(ty_param_def, ty.into_inner().clean(cx));
} else if let Some(default) = ty_param.default.clone() { } else if let Some(default) = default.clone() {
ty_substs.insert(ty_param_def, ty_substs.insert(ty_param_def,
default.into_inner().clean(cx)); default.into_inner().clean(cx));
} }

View file

@ -73,7 +73,9 @@ pub trait Visitor<'ast>: Sized {
fn visit_expr(&mut self, ex: &'ast Expr) { walk_expr(self, ex) } fn visit_expr(&mut self, ex: &'ast Expr) { walk_expr(self, ex) }
fn visit_expr_post(&mut self, _ex: &'ast Expr) { } fn visit_expr_post(&mut self, _ex: &'ast Expr) { }
fn visit_ty(&mut self, t: &'ast Ty) { walk_ty(self, t) } fn visit_ty(&mut self, t: &'ast Ty) { walk_ty(self, t) }
fn visit_generic_param(&mut self, param: &'ast GenericParamAST) { walk_generic_param(self, param) } fn visit_generic_param(&mut self, param: &'ast GenericParamAST) {
walk_generic_param(self, param)
}
fn visit_generics(&mut self, g: &'ast Generics) { walk_generics(self, g) } fn visit_generics(&mut self, g: &'ast Generics) { walk_generics(self, g) }
fn visit_where_predicate(&mut self, p: &'ast WherePredicate) { fn visit_where_predicate(&mut self, p: &'ast WherePredicate) {
walk_where_predicate(self, p) walk_where_predicate(self, p)

View file

@ -568,7 +568,8 @@ impl<'a> TraitDef<'a> {
bounds.push((*declared_bound).clone()); bounds.push((*declared_bound).clone());
} }
GenericParamAST::Type(cx.typaram(self.span, ty_param.ident, vec![], bounds, None)) let ty_param = cx.typaram(self.span, ty_param.ident, vec![], bounds, None);
GenericParamAST::Type(ty_param)
} }
} }
})); }));

View file

@ -192,7 +192,9 @@ impl<'a> Ty<'a> {
let ty_params: Vec<P<ast::Ty>> = self_generics.params let ty_params: Vec<P<ast::Ty>> = self_generics.params
.iter() .iter()
.filter_map(|param| match *param { .filter_map(|param| match *param {
GenericParamAST::Type(ref ty_param) => Some(cx.ty_ident(span, ty_param.ident)), GenericParamAST::Type(ref ty_param) => {
Some(cx.ty_ident(span, ty_param.ident))
}
_ => None, _ => None,
}) })
.collect(); .collect();
@ -280,7 +282,8 @@ impl<'a> LifetimeBounds<'a> {
let bounds = bounds.iter() let bounds = bounds.iter()
.map(|b| cx.lifetime(span, Ident::from_str(b))) .map(|b| cx.lifetime(span, Ident::from_str(b)))
.collect(); .collect();
GenericParamAST::Lifetime(cx.lifetime_def(span, Ident::from_str(lt), vec![], bounds)) let lifetime_def = cx.lifetime_def(span, Ident::from_str(lt), vec![], bounds);
GenericParamAST::Lifetime(lifetime_def)
}) })
.chain(self.bounds .chain(self.bounds
.iter() .iter()