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) {
match *param {
GenericParam::Lifetime(ref ld) => {
visitor.visit_id(ld.lifetime.id);
match ld.lifetime.name {
visitor.visit_id(param.id);
match param.kind {
GenericParamKind::Lifetime { ref bounds, ref lifetime_deprecated, .. } => {
match lifetime_deprecated.name {
LifetimeName::Name(name) => {
visitor.visit_name(ld.lifetime.span, name);
visitor.visit_name(param.span, name);
}
LifetimeName::Fresh(_) |
LifetimeName::Static |
LifetimeName::Implicit |
LifetimeName::Underscore => {}
}
walk_list!(visitor, visit_lifetime, &ld.bounds);
walk_list!(visitor, visit_lifetime, bounds);
}
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);
walk_list!(visitor, visit_attribute, ty_param.attrs.iter());
GenericParamKind::Type { name, ref bounds, ref default, ref attrs, .. } => {
visitor.visit_name(param.span, name);
walk_list!(visitor, visit_ty_param_bound, bounds);
walk_list!(visitor, visit_ty, default);
walk_list!(visitor, visit_attribute, attrs.iter());
}
}
}

View file

@ -116,7 +116,7 @@ pub struct LoweringContext<'a> {
// When traversing a signature such as `fn foo(x: impl Trait)`,
// we record `impl Trait` as a new type parameter, then later
// 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.
// 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,
);
hir::GenericParam::Lifetime(hir::LifetimeDef {
lifetime: hir::Lifetime {
hir::GenericParam {
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,
span,
name: hir_name,
},
bounds: Vec::new().into(),
pure_wrt_drop: false,
in_band: true,
}
}
}
})
})
.chain(
in_band_ty_params
.into_iter()
.map(|tp| hir::GenericParam::Type(tp)),
)
.chain(in_band_ty_params.into_iter())
.collect();
(params, res)
@ -778,12 +779,12 @@ impl<'a> LoweringContext<'a> {
// This should only be used with generics that have already had their
// in-band lifetimes added. In practice, this means that this function is
// only used when lowering a child item of a trait or impl.
fn with_parent_impl_lifetime_defs<T, F>(&mut self, lt_defs: &[hir::LifetimeDef], f: F) -> T
fn with_parent_impl_lifetime_defs<T, F>(&mut self, params: &[hir::GenericParam], f: F) -> T
where
F: FnOnce(&mut LoweringContext) -> T,
{
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);
let res = f(self);
@ -1252,15 +1253,17 @@ impl<'a> LoweringContext<'a> {
let hir_bounds = self.lower_bounds(bounds, itctx);
// Set the name to `impl Bound1 + Bound2`
let name = Symbol::intern(&pprust::ty_to_string(t));
self.in_band_ty_params.push(hir::TyParam {
name,
self.in_band_ty_params.push(hir::GenericParam {
id: def_node_id,
bounds: hir_bounds,
default: None,
span,
pure_wrt_drop: false,
kind: hir::GenericParamKind::Type {
name,
bounds: hir_bounds,
default: None,
synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
attrs: P::new(),
}
});
hir::TyPath(hir::QPath::Resolved(
@ -1367,10 +1370,10 @@ impl<'a> LoweringContext<'a> {
fn visit_generic_param(&mut self, param: &'v hir::GenericParam) {
// 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
// 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);
@ -1416,18 +1419,22 @@ impl<'a> LoweringContext<'a> {
Mark::root(),
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,
span: lifetime.span,
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 {
let span = l.ident.span;
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;
self.is_collecting_in_band_lifetimes = false;
let def = hir::LifetimeDef {
lifetime: self.lower_lifetime(&l.lifetime),
bounds: l.bounds.iter().map(|l| self.lower_lifetime(l)).collect(),
pure_wrt_drop: attr::contains_name(&l.attrs, "may_dangle"),
let lifetime = self.lower_lifetime(&lifetime_def.lifetime);
let param = hir::GenericParam {
id: lifetime.id,
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,
lifetime_deprecated: lifetime,
}
};
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(
@ -1984,19 +2005,7 @@ impl<'a> LoweringContext<'a> {
add_bounds: &NodeMap<Vec<TyParamBound>>,
itctx: ImplTraitContext,
) -> hir::HirVec<hir::GenericParam> {
params
.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()
params.iter().map(|param| self.lower_generic_param(param, add_bounds, itctx)).collect()
}
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(
&bound_generic_params
.iter()
.filter_map(|p| match *p {
hir::GenericParam::Lifetime(ref ld) => Some(ld.clone()),
.filter_map(|param| match param.kind {
hir::GenericParamKind::Lifetime { .. } => Some(param.clone()),
_ => None,
})
.collect::<Vec<_>>(),

View file

@ -212,7 +212,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
NodeBlock(n) => EntryBlock(parent, dep_node_index, n),
NodeStructCtor(n) => EntryStructCtor(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),
NodeLocal(n) => EntryLocal(parent, 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) {
match *param {
GenericParam::Lifetime(ref ld) => {
self.insert(ld.lifetime.id, NodeLifetime(&ld.lifetime));
match param.kind {
GenericParamKind::Lifetime { ref lifetime_deprecated, .. } => {
self.insert(param.id, NodeLifetime(lifetime_deprecated));
}
GenericParam::Type(ref ty_param) => {
self.insert(ty_param.id, NodeTyParam(ty_param));
GenericParamKind::Type { .. } => {
self.insert(param.id, NodeGenericParam(param));
}
}
intravisit::walk_generic_param(self, param);

View file

@ -68,7 +68,7 @@ pub enum Node<'hir> {
NodeStructCtor(&'hir VariantData),
NodeLifetime(&'hir Lifetime),
NodeTyParam(&'hir TyParam),
NodeGenericParam(&'hir GenericParam),
NodeVisibility(&'hir Visibility),
}
@ -96,7 +96,7 @@ enum MapEntry<'hir> {
EntryBlock(NodeId, DepNodeIndex, &'hir Block),
EntryStructCtor(NodeId, DepNodeIndex, &'hir VariantData),
EntryLifetime(NodeId, DepNodeIndex, &'hir Lifetime),
EntryTyParam(NodeId, DepNodeIndex, &'hir TyParam),
EntryGenericParam(NodeId, DepNodeIndex, &'hir GenericParam),
EntryVisibility(NodeId, DepNodeIndex, &'hir Visibility),
EntryLocal(NodeId, DepNodeIndex, &'hir Local),
@ -132,7 +132,7 @@ impl<'hir> MapEntry<'hir> {
EntryBlock(id, _, _) => id,
EntryStructCtor(id, _, _) => id,
EntryLifetime(id, _, _) => id,
EntryTyParam(id, _, _) => id,
EntryGenericParam(id, _, _) => id,
EntryVisibility(id, _, _) => id,
EntryLocal(id, _, _) => id,
@ -160,7 +160,7 @@ impl<'hir> MapEntry<'hir> {
EntryBlock(_, _, n) => NodeBlock(n),
EntryStructCtor(_, _, n) => NodeStructCtor(n),
EntryLifetime(_, _, n) => NodeLifetime(n),
EntryTyParam(_, _, n) => NodeTyParam(n),
EntryGenericParam(_, _, n) => NodeGenericParam(n),
EntryVisibility(_, _, n) => NodeVisibility(n),
EntryLocal(_, _, n) => NodeLocal(n),
EntryMacroDef(_, n) => NodeMacroDef(n),
@ -328,7 +328,7 @@ impl<'hir> Map<'hir> {
EntryBlock(_, dep_node_index, _) |
EntryStructCtor(_, dep_node_index, _) |
EntryLifetime(_, dep_node_index, _) |
EntryTyParam(_, dep_node_index, _) |
EntryGenericParam(_, dep_node_index, _) |
EntryVisibility(_, dep_node_index, _) |
EntryAnonConst(_, 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),
MacroKind::Bang))
}
NodeTyParam(param) => {
NodeGenericParam(param) => {
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 {
match self.get(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",
self.node_to_string(id))
@ -613,7 +613,7 @@ impl<'hir> Map<'hir> {
NodeItem(&Item { node: ItemTrait(..), .. }) => {
keywords::SelfType.name()
}
NodeTyParam(tp) => tp.name,
NodeGenericParam(param) => param.name(),
_ => {
bug!("ty_param_name: {} not a type parameter",
self.node_to_string(id))
@ -954,7 +954,7 @@ impl<'hir> Map<'hir> {
NodeVariant(v) => v.node.name,
NodeField(f) => f.ident.name,
NodeLifetime(lt) => lt.name.name(),
NodeTyParam(tp) => tp.name,
NodeGenericParam(param) => param.name(),
NodeBinding(&Pat { node: PatKind::Binding(_,_,l,_), .. }) => l.node,
NodeStructCtor(_) => self.name(self.get_parent(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(NodeExpr(ref e)) => Some(&*e.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
// the struct definition.
Some(NodeStructCtor(_)) => {
@ -1021,7 +1026,7 @@ impl<'hir> Map<'hir> {
Some(EntryBlock(_, _, block)) => block.span,
Some(EntryStructCtor(_, _, _)) => self.expect_item(self.get_parent(id)).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(_, _, v)) => bug!("unexpected Visibility {:?}", v),
Some(EntryLocal(_, _, local)) => local.span,
@ -1249,7 +1254,7 @@ impl<'a> print::State<'a> {
}
NodeLifetime(a) => self.print_lifetime(&a),
NodeVisibility(a) => self.print_visibility(&a),
NodeTyParam(_) => bug!("cannot print TyParam"),
NodeGenericParam(_) => bug!("cannot print NodeGenericParam"),
NodeField(_) => bug!("cannot print StructField"),
// these cases do not carry enough information in the
// 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(_)) => {
format!("lifetime {}{}", map.node_to_pretty_string(id), id_str)
}
Some(NodeTyParam(ref ty_param)) => {
format!("typaram {:?}{}", ty_param, id_str)
Some(NodeGenericParam(ref param)) => {
format!("genericparam {:?}{}", param, id_str)
}
Some(NodeVisibility(ref vis)) => {
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 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
@ -242,6 +240,24 @@ impl LifetimeName {
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 {
@ -255,36 +271,14 @@ impl fmt::Debug for Lifetime {
impl Lifetime {
pub fn is_elided(&self) -> bool {
use self::LifetimeName::*;
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,
}
self.name.is_elided()
}
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:
/// `std::cmp::PartialEq`. It's represented as a sequence of identifiers,
/// along with a bunch of supporting information.
@ -466,70 +460,62 @@ pub enum TraitBoundModifier {
pub type TyParamBounds = HirVec<TyParamBound>;
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct TyParam {
pub name: Name,
pub id: NodeId,
pub bounds: TyParamBounds,
pub default: Option<P<Ty>>,
pub span: Span,
pub pure_wrt_drop: bool,
pub synthetic: Option<SyntheticTyParamKind>,
pub attrs: HirVec<Attribute>,
pub enum GenericParamKind {
/// A lifetime definition, eg `'a: 'b + 'c + 'd`.
Lifetime {
/// Either "'a", referring to a named lifetime definition,
/// or "" (aka keywords::Invalid), for elision placeholders.
///
/// HIR lowering inserts these placeholders in type paths that
/// refer to type definitions needing lifetime parameters,
/// `&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)]
pub enum GenericParam {
Lifetime(LifetimeDef),
Type(TyParam),
pub struct GenericParam {
pub id: NodeId,
pub span: Span,
pub pure_wrt_drop: bool,
pub kind: GenericParamKind,
}
impl GenericParam {
pub fn is_lifetime_param(&self) -> bool {
match *self {
GenericParam::Lifetime(_) => true,
match self.kind {
GenericParamKind::Lifetime { .. } => true,
_ => false,
}
}
pub fn is_type_param(&self) -> bool {
match *self {
GenericParam::Type(_) => true,
match self.kind {
GenericParamKind::Type { .. } => true,
_ => 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 {
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 {
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> {
self.params.lifetimes()
pub fn lifetimes<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a GenericParam> {
self.params.iter().filter(|param| {
match param.kind {
GenericParamKind::Lifetime { .. } => true,
_ => false,
}
})
}
pub fn ty_params<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a TyParam> {
self.params.ty_params()
pub fn ty_params<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a GenericParam> {
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::{PatKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier, RangeEnd};
use hir::GenericArg;
use hir::{GenericParam, GenericParamKind, GenericArg};
use std::cell::Cell;
use std::io::{self, Write, Read};
@ -2094,30 +2094,12 @@ impl<'a> State<'a> {
Ok(())
}
pub fn print_lifetime(&mut self, lifetime: &hir::Lifetime) -> 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<()> {
pub fn print_generic_params(&mut self, generic_params: &[GenericParam]) -> io::Result<()> {
if !generic_params.is_empty() {
self.s.word("<")?;
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),
}
s.print_generic_param(param)
})?;
self.s.word(">")?;
@ -2125,11 +2107,22 @@ impl<'a> State<'a> {
Ok(())
}
pub fn print_ty_param(&mut self, param: &hir::TyParam) -> io::Result<()> {
self.print_name(param.name)?;
self.print_bounds(":", &param.bounds)?;
match param.default {
Some(ref default) => {
pub fn print_generic_param(&mut self, param: &GenericParam) -> io::Result<()> {
self.print_name(param.name())?;
match param.kind {
GenericParamKind::Lifetime { ref bounds, .. } => {
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.word_space("=")?;
self.print_type(&default)
@ -2137,6 +2130,12 @@ impl<'a> State<'a> {
_ => 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<()> {
if where_clause.predicates.is_empty() {

View file

@ -161,13 +161,6 @@ impl_stable_hash_for!(struct hir::Lifetime {
name
});
impl_stable_hash_for!(struct hir::LifetimeDef {
lifetime,
bounds,
pure_wrt_drop,
in_band
});
impl_stable_hash_for!(struct hir::Path {
span,
def,
@ -201,21 +194,36 @@ impl_stable_hash_for!(enum hir::TraitBoundModifier {
Maybe
});
impl_stable_hash_for!(struct hir::TyParam {
name,
impl_stable_hash_for!(struct hir::GenericParam {
id,
bounds,
default,
span,
pure_wrt_drop,
synthetic,
attrs
kind
});
impl_stable_hash_for!(enum hir::GenericParam {
Lifetime(lifetime_def),
Type(ty_param)
});
impl<'a> HashStable<StableHashingContext<'a>> for hir::GenericParamKind {
fn hash_stable<W: StableHasherResult>(&self,
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 {
params,

View file

@ -61,7 +61,7 @@ use super::region_constraints::GenericKind;
use super::lexical_region_resolve::RegionResolutionError;
use std::fmt;
use hir;
use hir::{self, GenericParamKind};
use hir::map as hir_map;
use hir::def_id::DefId;
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.
// We do this to avoid suggesting code that ends up as `T: 'a'b`,
// instead we suggest `T: 'a + 'b` in that case.
let has_lifetimes = if let hir_map::NodeTyParam(ref p) = hir.get(id) {
p.bounds.len() > 0
let has_lifetimes =
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 {
false
};

View file

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

View file

@ -18,7 +18,7 @@ use syntax::ast;
use syntax::attr;
use syntax_pos::Span;
use rustc::hir::{self, PatKind};
use rustc::hir::{self, GenericParamKind, PatKind};
use rustc::hir::intravisit::FnKind;
#[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) {
if let hir::GenericParam::Type(ref gen) = *param {
if gen.synthetic.is_none() {
self.check_case(cx, "type parameter", gen.name, gen.span);
match param.kind {
GenericParamKind::Lifetime { .. } => {}
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) {
if let hir::GenericParam::Lifetime(ref ld) = *param {
self.check_snake_case(
cx,
"lifetime",
&ld.lifetime.name.name().as_str(),
Some(ld.lifetime.span)
);
match param.kind {
GenericParamKind::Lifetime { .. } => {
self.check_snake_case(cx, "lifetime", &param.name().as_str(), Some(param.span));
}
GenericParamKind::Type { .. } => {}
}
}

View file

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

View file

@ -22,7 +22,7 @@ extern crate rustc_typeck;
extern crate syntax_pos;
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_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId};
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) {
for ty_param in generics.ty_params() {
for bound in ty_param.bounds.iter() {
self.check_ty_param_bound(bound)
for param in &generics.params {
match param.kind {
GenericParamKind::Lifetime { .. } => {}
GenericParamKind::Type { ref bounds, .. } => {
for bound in bounds {
self.check_ty_param_bound(bound);
}
}
}
}
for predicate in &generics.where_clause.predicates {

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// 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::ty::{self, TyCtxt, GenericParamDefKind};
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 param = impl_m.generics.params.iter().filter_map(|param| {
match param {
hir::GenericParam::Type(param) => {
let bounds = impl_m.generics.params.iter().find_map(|param| {
match param.kind {
GenericParamKind::Lifetime { .. } => None,
GenericParamKind::Type { ref bounds, .. } => {
if param.id == impl_node_id {
Some(param)
Some(bounds)
} else {
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
.sess
.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()) {
if !used {
struct_span_err!(tcx.sess, param.span, E0091,
"type parameter `{}` is unused",
param.name)
struct_span_err!(tcx.sess, param.span, E0091, "type parameter `{}` is unused",
param.name())
.span_label(param.span, "unused type parameter")
.emit();
}

View file

@ -631,11 +631,8 @@ fn check_variances_for_type_defn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
continue;
}
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),
};
report_bivariance(tcx, span, name);
let param = &ast_generics.params[index];
report_bivariance(tcx, param.span, param.name());
}
}

View file

@ -35,7 +35,14 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> {
Some(trait_ref) => {
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) {
(Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
span_err!(self.tcx.sess,
@ -53,13 +60,14 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> {
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,
item.span,
E0569,
"requires an `unsafe impl` declaration due to `#[{}]` attribute",
g.attr_name());
attr_name);
}
(_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => {

View file

@ -49,6 +49,7 @@ use syntax::feature_gate;
use syntax_pos::{Span, DUMMY_SP};
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::def::{Def, CtorKind};
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) {
for param in generics.ty_params() {
if param.default.is_some() {
for param in &generics.params {
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);
self.tcx.type_of(def_id);
}
}
}
}
intravisit::walk_generics(self, generics);
}
@ -308,9 +314,20 @@ impl<'a, 'tcx> ItemCtxt<'a, 'tcx> {
-> Vec<ty::Predicate<'tcx>>
{
let from_ty_params =
ast_generics.ty_params()
.filter(|p| p.id == param_id)
.flat_map(|p| p.bounds.iter())
ast_generics.params.iter()
.filter_map(|param| {
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));
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,
};
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) {
return Some(lifetime.lifetime.span);
return Some(lifetime.span);
}
}
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 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 {
name: l.lifetime.name.name().as_interned_str(),
name: param.name().as_interned_str(),
index: own_start + i as u32,
def_id: tcx.hir.local_def_id(l.lifetime.id),
pure_wrt_drop: l.pure_wrt_drop,
def_id: tcx.hir.local_def_id(param.id),
pure_wrt_drop: param.pure_wrt_drop,
kind: ty::GenericParamDefKind::Lifetime,
}
}));
@ -898,34 +915,40 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// Now create the real type parameters.
let type_start = own_start - has_self as u32 + params.len() as u32;
params.extend(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");
params.extend(ast_generics.ty_params().enumerate().map(|(i, param)| {
match param.kind {
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 {
tcx.lint_node(
lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
p.id,
p.span,
&format!("defaults for type parameters are only allowed in `struct`, \
`enum`, `type`, or `trait` definitions."));
param.id,
param.span,
&format!("defaults for type parameters are only allowed in \
`struct`, `enum`, `type`, or `trait` definitions."));
}
}
ty::GenericParamDef {
index: type_start + i as u32,
name: p.name.as_interned_str(),
def_id: tcx.hir.local_def_id(p.id),
pure_wrt_drop: p.pure_wrt_drop,
name: param.name().as_interned_str(),
def_id: tcx.hir.local_def_id(param.id),
pure_wrt_drop: param.pure_wrt_drop,
kind: ty::GenericParamDefKind::Type {
has_default: p.default.is_some(),
has_default: default.is_some(),
object_lifetime_default:
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
@ -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)
}
_ => bug!("unexpected non-type NodeGenericParam"),
}
}
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`.
fn early_bound_lifetimes_from_generics<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
ast_generics: &'a hir::Generics)
-> impl Iterator<Item=&'a hir::LifetimeDef> + Captures<'tcx>
generics: &'a hir::Generics)
-> impl Iterator<Item=&'a hir::GenericParam> + Captures<'tcx>
{
ast_generics
.lifetimes()
.filter(move |l| {
let hir_id = tcx.hir.node_to_hir_id(l.lifetime.id);
generics.params.iter().filter(move |param| {
match param.kind {
GenericParamKind::Lifetime { .. } => {
let hir_id = tcx.hir.node_to_hir_id(param.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;
for param in early_bound_lifetimes_from_generics(tcx, ast_generics) {
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,
name: param.lifetime.name.name().as_interned_str(),
name: param.name().as_interned_str(),
}));
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 outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound_region));
let outlives =
ty::Binder::bind(ty::OutlivesPredicate(region, bound_region));
predicates.push(outlives.to_predicate());
}
},
_ => bug!(),
}
}
// 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() {
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;
let bounds = match param.kind {
GenericParamKind::Type { ref bounds, .. } => bounds,
_ => bug!(),
};
let bounds = compute_bounds(&icx,
param_ty,
&param.bounds,
bounds,
SizedByDefault::Yes,
param.span);
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(from_ref)]
#![feature(exhaustive_patterns)]
#![feature(iterator_find_map)]
#![feature(quote)]
#![feature(refcell_replace_swap)]
#![feature(rustc_diagnostic_macros)]

View file

@ -1466,14 +1466,19 @@ pub struct TyParam {
pub synthetic: Option<hir::SyntheticTyParamKind>,
}
impl Clean<TyParam> for hir::TyParam {
impl Clean<TyParam> for hir::GenericParam {
fn clean(&self, cx: &DocContext) -> TyParam {
match self.kind {
hir::GenericParamKind::Type { ref bounds, ref default, synthetic, .. } => {
TyParam {
name: self.name.clean(cx),
name: self.name().clean(cx),
did: cx.tcx.hir.local_def_id(self.id),
bounds: self.bounds.clean(cx),
default: self.default.clean(cx),
synthetic: self.synthetic,
bounds: bounds.clean(cx),
default: default.clean(cx),
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 {
if self.bounds.len() > 0 {
let mut s = format!("{}: {}",
self.lifetime.name.name(),
self.bounds[0].name.name());
for bound in self.bounds.iter().skip(1) {
match self.kind {
hir::GenericParamKind::Lifetime { ref bounds, .. } => {
if bounds.len() > 0 {
let mut s = format!("{}: {}", self.name(), bounds[0].name.name());
for bound in bounds.iter().skip(1) {
s.push_str(&format!(" + {}", bound.name.name()));
}
Lifetime(s)
} 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 {
fn clean(&self, cx: &DocContext) -> GenericParamDef {
match *self {
hir::GenericParam::Lifetime(ref l) => GenericParamDef::Lifetime(l.clean(cx)),
hir::GenericParam::Type(ref t) => GenericParamDef::Type(t.clean(cx)),
match self.kind {
hir::GenericParamKind::Lifetime { .. } => {
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,
// scans them first.
fn is_impl_trait(param: &hir::GenericParam) -> bool {
if let hir::GenericParam::Type(ref tp) = param {
tp.synthetic == Some(hir::SyntheticTyParamKind::ImplTrait)
} else {
false
match param.kind {
hir::GenericParamKind::Type { synthetic, .. } => {
synthetic == Some(hir::SyntheticTyParamKind::ImplTrait)
}
_ => false,
}
}
let impl_trait_params = self.params
@ -2857,25 +2868,25 @@ impl Clean<Type> for hir::Ty {
types: 0
};
for param in generics.params.iter() {
match param {
hir::GenericParam::Lifetime(lt_param) => {
match param.kind {
hir::GenericParamKind::Lifetime { .. } => {
if let Some(lt) = generic_args.lifetimes()
.nth(indices.lifetimes).cloned() {
if !lt.is_elided() {
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));
}
}
indices.lifetimes += 1;
}
hir::GenericParam::Type(ty_param) => {
hir::GenericParamKind::Type { ref default, .. } => {
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()
.nth(indices.types).cloned() {
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,
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_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 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_where_predicate(&mut self, p: &'ast WherePredicate) {
walk_where_predicate(self, p)

View file

@ -568,7 +568,8 @@ impl<'a> TraitDef<'a> {
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
.iter()
.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,
})
.collect();
@ -280,7 +282,8 @@ impl<'a> LifetimeBounds<'a> {
let bounds = bounds.iter()
.map(|b| cx.lifetime(span, Ident::from_str(b)))
.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
.iter()