Refactor hir::GenericParam as a struct
This commit is contained in:
parent
d643946550
commit
82dba3d419
23 changed files with 710 additions and 572 deletions
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<_>>(),
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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(":", ¶m.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() {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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, ¶m.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(¶m.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(¶m),
|
||||
);
|
||||
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(¶m),
|
||||
);
|
||||
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;
|
||||
|
|
|
@ -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", ¶m.name().as_str(), Some(param.span));
|
||||
}
|
||||
GenericParamKind::Type { .. } => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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 ¶m.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,
|
||||
¶m.bounds,
|
||||
bounds,
|
||||
SizedByDefault::Yes,
|
||||
param.span);
|
||||
predicates.extend(bounds.predicates(tcx, param_ty));
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue