Auto merge of #48149 - varkor:generics-generalisation, r=petrochenkov
The Great Generics Generalisation: HIR Edition This is essentially a followup to https://github.com/rust-lang/rust/pull/45930, consolidating the use of separate lifetime and type vectors into single kinds vectors wherever possible. This is intended to provide more of the groundwork for const generics (https://github.com/rust-lang/rust/issues/44580). r? @eddyb cc @yodaldevoid
This commit is contained in:
commit
662c70a59f
76 changed files with 2573 additions and 2492 deletions
|
|
@ -314,8 +314,8 @@ pub trait Visitor<'v> : Sized {
|
|||
fn visit_trait_ref(&mut self, t: &'v TraitRef) {
|
||||
walk_trait_ref(self, t)
|
||||
}
|
||||
fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) {
|
||||
walk_ty_param_bound(self, bounds)
|
||||
fn visit_param_bound(&mut self, bounds: &'v GenericBound) {
|
||||
walk_param_bound(self, bounds)
|
||||
}
|
||||
fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: TraitBoundModifier) {
|
||||
walk_poly_trait_ref(self, t, m)
|
||||
|
|
@ -344,6 +344,12 @@ pub trait Visitor<'v> : Sized {
|
|||
fn visit_label(&mut self, label: &'v Label) {
|
||||
walk_label(self, label)
|
||||
}
|
||||
fn visit_generic_arg(&mut self, generic_arg: &'v GenericArg) {
|
||||
match generic_arg {
|
||||
GenericArg::Lifetime(lt) => self.visit_lifetime(lt),
|
||||
GenericArg::Type(ty) => self.visit_ty(ty),
|
||||
}
|
||||
}
|
||||
fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
|
||||
walk_lifetime(self, lifetime)
|
||||
}
|
||||
|
|
@ -356,8 +362,8 @@ pub trait Visitor<'v> : Sized {
|
|||
fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) {
|
||||
walk_path_segment(self, path_span, path_segment)
|
||||
}
|
||||
fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &'v PathParameters) {
|
||||
walk_path_parameters(self, path_span, path_parameters)
|
||||
fn visit_generic_args(&mut self, path_span: Span, generic_args: &'v GenericArgs) {
|
||||
walk_generic_args(self, path_span, generic_args)
|
||||
}
|
||||
fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding) {
|
||||
walk_assoc_type_binding(self, type_binding)
|
||||
|
|
@ -427,10 +433,10 @@ pub fn walk_label<'v, V: Visitor<'v>>(visitor: &mut V, label: &'v Label) {
|
|||
pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) {
|
||||
visitor.visit_id(lifetime.id);
|
||||
match lifetime.name {
|
||||
LifetimeName::Name(name) => {
|
||||
LifetimeName::Param(ParamName::Plain(name)) => {
|
||||
visitor.visit_name(lifetime.span, name);
|
||||
}
|
||||
LifetimeName::Fresh(_) |
|
||||
LifetimeName::Param(ParamName::Fresh(_)) |
|
||||
LifetimeName::Static |
|
||||
LifetimeName::Implicit |
|
||||
LifetimeName::Underscore => {}
|
||||
|
|
@ -505,7 +511,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
|
|||
ItemExistential(ExistTy {ref generics, ref bounds, impl_trait_fn}) => {
|
||||
visitor.visit_id(item.id);
|
||||
walk_generics(visitor, generics);
|
||||
walk_list!(visitor, visit_ty_param_bound, bounds);
|
||||
walk_list!(visitor, visit_param_bound, bounds);
|
||||
if let Some(impl_trait_fn) = impl_trait_fn {
|
||||
visitor.visit_def_mention(Def::Fn(impl_trait_fn))
|
||||
}
|
||||
|
|
@ -531,13 +537,13 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
|
|||
ItemTrait(.., ref generics, ref bounds, ref trait_item_refs) => {
|
||||
visitor.visit_id(item.id);
|
||||
visitor.visit_generics(generics);
|
||||
walk_list!(visitor, visit_ty_param_bound, bounds);
|
||||
walk_list!(visitor, visit_param_bound, bounds);
|
||||
walk_list!(visitor, visit_trait_item_ref, trait_item_refs);
|
||||
}
|
||||
ItemTraitAlias(ref generics, ref bounds) => {
|
||||
visitor.visit_id(item.id);
|
||||
visitor.visit_generics(generics);
|
||||
walk_list!(visitor, visit_ty_param_bound, bounds);
|
||||
walk_list!(visitor, visit_param_bound, bounds);
|
||||
}
|
||||
}
|
||||
walk_list!(visitor, visit_attribute, &item.attrs);
|
||||
|
|
@ -642,17 +648,16 @@ pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
|
|||
path_span: Span,
|
||||
segment: &'v PathSegment) {
|
||||
visitor.visit_name(path_span, segment.name);
|
||||
if let Some(ref parameters) = segment.parameters {
|
||||
visitor.visit_path_parameters(path_span, parameters);
|
||||
if let Some(ref args) = segment.args {
|
||||
visitor.visit_generic_args(path_span, args);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
|
||||
_path_span: Span,
|
||||
path_parameters: &'v PathParameters) {
|
||||
walk_list!(visitor, visit_lifetime, &path_parameters.lifetimes);
|
||||
walk_list!(visitor, visit_ty, &path_parameters.types);
|
||||
walk_list!(visitor, visit_assoc_type_binding, &path_parameters.bindings);
|
||||
pub fn walk_generic_args<'v, V: Visitor<'v>>(visitor: &mut V,
|
||||
_path_span: Span,
|
||||
generic_args: &'v GenericArgs) {
|
||||
walk_list!(visitor, visit_generic_arg, &generic_args.args);
|
||||
walk_list!(visitor, visit_assoc_type_binding, &generic_args.bindings);
|
||||
}
|
||||
|
||||
pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V,
|
||||
|
|
@ -726,40 +731,27 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v
|
|||
walk_list!(visitor, visit_attribute, &foreign_item.attrs);
|
||||
}
|
||||
|
||||
pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v TyParamBound) {
|
||||
pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericBound) {
|
||||
match *bound {
|
||||
TraitTyParamBound(ref typ, modifier) => {
|
||||
GenericBound::Trait(ref typ, modifier) => {
|
||||
visitor.visit_poly_trait_ref(typ, modifier);
|
||||
}
|
||||
RegionTyParamBound(ref lifetime) => {
|
||||
visitor.visit_lifetime(lifetime);
|
||||
}
|
||||
GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime),
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
LifetimeName::Name(name) => {
|
||||
visitor.visit_name(ld.lifetime.span, name);
|
||||
}
|
||||
LifetimeName::Fresh(_) |
|
||||
LifetimeName::Static |
|
||||
LifetimeName::Implicit |
|
||||
LifetimeName::Underscore => {}
|
||||
}
|
||||
walk_list!(visitor, visit_lifetime, &ld.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());
|
||||
}
|
||||
visitor.visit_id(param.id);
|
||||
walk_list!(visitor, visit_attribute, ¶m.attrs);
|
||||
match param.name {
|
||||
ParamName::Plain(name) => visitor.visit_name(param.span, name),
|
||||
ParamName::Fresh(_) => {}
|
||||
}
|
||||
match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => {}
|
||||
GenericParamKind::Type { ref default, .. } => walk_list!(visitor, visit_ty, default),
|
||||
}
|
||||
walk_list!(visitor, visit_param_bound, ¶m.bounds);
|
||||
}
|
||||
|
||||
pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) {
|
||||
|
|
@ -778,14 +770,14 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>(
|
|||
ref bound_generic_params,
|
||||
..}) => {
|
||||
visitor.visit_ty(bounded_ty);
|
||||
walk_list!(visitor, visit_ty_param_bound, bounds);
|
||||
walk_list!(visitor, visit_param_bound, bounds);
|
||||
walk_list!(visitor, visit_generic_param, bound_generic_params);
|
||||
}
|
||||
&WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime,
|
||||
ref bounds,
|
||||
..}) => {
|
||||
visitor.visit_lifetime(lifetime);
|
||||
walk_list!(visitor, visit_lifetime, bounds);
|
||||
walk_list!(visitor, visit_param_bound, bounds);
|
||||
}
|
||||
&WherePredicate::EqPredicate(WhereEqPredicate{id,
|
||||
ref lhs_ty,
|
||||
|
|
@ -862,7 +854,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
|
|||
}
|
||||
TraitItemKind::Type(ref bounds, ref default) => {
|
||||
visitor.visit_id(trait_item.id);
|
||||
walk_list!(visitor, visit_ty_param_bound, bounds);
|
||||
walk_list!(visitor, visit_param_bound, bounds);
|
||||
walk_list!(visitor, visit_ty, default);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,11 +41,12 @@
|
|||
//! in the HIR, especially for multiple identifiers.
|
||||
|
||||
use dep_graph::DepGraph;
|
||||
use hir;
|
||||
use hir::{self, ParamName};
|
||||
use hir::HirVec;
|
||||
use hir::map::{DefKey, DefPathData, Definitions};
|
||||
use hir::def_id::{DefId, DefIndex, DefIndexAddressSpace, CRATE_DEF_INDEX};
|
||||
use hir::def::{Def, PathResolution, PerNS};
|
||||
use hir::GenericArg;
|
||||
use lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES};
|
||||
use middle::cstore::CrateStore;
|
||||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
|
|
@ -58,6 +59,7 @@ use std::fmt::Debug;
|
|||
use std::iter;
|
||||
use std::mem;
|
||||
use syntax::attr;
|
||||
use syntax::ast;
|
||||
use syntax::ast::*;
|
||||
use syntax::errors;
|
||||
use syntax::ext::hygiene::{Mark, SyntaxContext};
|
||||
|
|
@ -114,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`
|
||||
|
|
@ -123,7 +125,7 @@ pub struct LoweringContext<'a> {
|
|||
// (i.e. it doesn't appear in the in_scope_lifetimes list), it is added
|
||||
// to this list. The results of this list are then added to the list of
|
||||
// lifetime definitions in the corresponding impl or function generics.
|
||||
lifetimes_to_define: Vec<(Span, hir::LifetimeName)>,
|
||||
lifetimes_to_define: Vec<(Span, ParamName)>,
|
||||
|
||||
// Whether or not in-band lifetimes are being collected. This is used to
|
||||
// indicate whether or not we're in a place where new lifetimes will result
|
||||
|
|
@ -322,7 +324,10 @@ impl<'a> LoweringContext<'a> {
|
|||
let count = generics
|
||||
.params
|
||||
.iter()
|
||||
.filter(|param| param.is_lifetime_param())
|
||||
.filter(|param| match param.kind {
|
||||
ast::GenericParamKind::Lifetime { .. } => true,
|
||||
_ => false,
|
||||
})
|
||||
.count();
|
||||
self.lctx.type_def_lifetime_params.insert(def_id, count);
|
||||
}
|
||||
|
|
@ -374,25 +379,24 @@ impl<'a> LoweringContext<'a> {
|
|||
});
|
||||
|
||||
if item_lowered {
|
||||
let item_lifetimes = match self.lctx.items.get(&item.id).unwrap().node {
|
||||
let item_generics = match self.lctx.items.get(&item.id).unwrap().node {
|
||||
hir::Item_::ItemImpl(_, _, _, ref generics, ..)
|
||||
| hir::Item_::ItemTrait(_, _, ref generics, ..) => {
|
||||
generics.lifetimes().cloned().collect::<Vec<_>>()
|
||||
generics.params.clone()
|
||||
}
|
||||
_ => Vec::new(),
|
||||
_ => HirVec::new(),
|
||||
};
|
||||
|
||||
self.lctx
|
||||
.with_parent_impl_lifetime_defs(&item_lifetimes, |this| {
|
||||
let this = &mut ItemLowerer { lctx: this };
|
||||
if let ItemKind::Impl(_, _, _, _, ref opt_trait_ref, _, _) = item.node {
|
||||
this.with_trait_impl_ref(opt_trait_ref, |this| {
|
||||
visit::walk_item(this, item)
|
||||
});
|
||||
} else {
|
||||
visit::walk_item(this, item);
|
||||
}
|
||||
});
|
||||
self.lctx.with_parent_impl_lifetime_defs(&item_generics, |this| {
|
||||
let this = &mut ItemLowerer { lctx: this };
|
||||
if let ItemKind::Impl(_, _, _, _, ref opt_trait_ref, _, _) = item.node {
|
||||
this.with_trait_impl_ref(opt_trait_ref, |this| {
|
||||
visit::walk_item(this, item)
|
||||
});
|
||||
} else {
|
||||
visit::walk_item(this, item);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -674,41 +678,31 @@ impl<'a> LoweringContext<'a> {
|
|||
// that collisions are ok here and this shouldn't
|
||||
// really show up for end-user.
|
||||
let str_name = match hir_name {
|
||||
hir::LifetimeName::Name(n) => n.as_str(),
|
||||
hir::LifetimeName::Fresh(_) => keywords::UnderscoreLifetime.name().as_str(),
|
||||
hir::LifetimeName::Implicit
|
||||
| hir::LifetimeName::Underscore
|
||||
| hir::LifetimeName::Static => {
|
||||
span_bug!(span, "unexpected in-band lifetime name: {:?}", hir_name)
|
||||
}
|
||||
ParamName::Plain(name) => name.as_str(),
|
||||
ParamName::Fresh(_) => keywords::UnderscoreLifetime.name().as_str(),
|
||||
};
|
||||
|
||||
// Add a definition for the in-band lifetime def
|
||||
self.resolver.definitions().create_def_with_parent(
|
||||
parent_id.index,
|
||||
def_node_id,
|
||||
DefPathData::LifetimeDef(str_name.as_interned_str()),
|
||||
DefPathData::LifetimeParam(str_name.as_interned_str()),
|
||||
DefIndexAddressSpace::High,
|
||||
Mark::root(),
|
||||
span,
|
||||
);
|
||||
|
||||
hir::GenericParam::Lifetime(hir::LifetimeDef {
|
||||
lifetime: hir::Lifetime {
|
||||
id: def_node_id,
|
||||
span,
|
||||
name: hir_name,
|
||||
},
|
||||
bounds: Vec::new().into(),
|
||||
hir::GenericParam {
|
||||
id: def_node_id,
|
||||
name: hir_name,
|
||||
attrs: hir_vec![],
|
||||
bounds: hir_vec![],
|
||||
span,
|
||||
pure_wrt_drop: false,
|
||||
in_band: true,
|
||||
})
|
||||
kind: hir::GenericParamKind::Lifetime { 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)
|
||||
|
|
@ -727,12 +721,9 @@ impl<'a> LoweringContext<'a> {
|
|||
return;
|
||||
}
|
||||
|
||||
let hir_name = hir::LifetimeName::Name(name);
|
||||
let hir_name = ParamName::Plain(name);
|
||||
|
||||
if self.lifetimes_to_define
|
||||
.iter()
|
||||
.any(|(_, lt_name)| *lt_name == hir_name)
|
||||
{
|
||||
if self.lifetimes_to_define.iter().any(|(_, lt_name)| *lt_name == hir_name) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -741,28 +732,27 @@ impl<'a> LoweringContext<'a> {
|
|||
|
||||
/// When we have either an elided or `'_` lifetime in an impl
|
||||
/// header, we convert it to
|
||||
fn collect_fresh_in_band_lifetime(&mut self, span: Span) -> hir::LifetimeName {
|
||||
fn collect_fresh_in_band_lifetime(&mut self, span: Span) -> ParamName {
|
||||
assert!(self.is_collecting_in_band_lifetimes);
|
||||
let index = self.lifetimes_to_define.len();
|
||||
let hir_name = hir::LifetimeName::Fresh(index);
|
||||
let hir_name = ParamName::Fresh(index);
|
||||
self.lifetimes_to_define.push((span, hir_name));
|
||||
hir_name
|
||||
}
|
||||
|
||||
// Evaluates `f` with the lifetimes in `lt_defs` in-scope.
|
||||
// Evaluates `f` with the lifetimes in `params` in-scope.
|
||||
// This is used to track which lifetimes have already been defined, and
|
||||
// which are new in-band lifetimes that need to have a definition created
|
||||
// for them.
|
||||
fn with_in_scope_lifetime_defs<'l, T, F>(
|
||||
&mut self,
|
||||
lt_defs: impl Iterator<Item = &'l LifetimeDef>,
|
||||
f: F,
|
||||
) -> T
|
||||
fn with_in_scope_lifetime_defs<T, F>(&mut self, params: &Vec<GenericParam>, f: F) -> T
|
||||
where
|
||||
F: FnOnce(&mut LoweringContext) -> T,
|
||||
{
|
||||
let old_len = self.in_scope_lifetimes.len();
|
||||
let lt_def_names = lt_defs.map(|lt_def| lt_def.lifetime.ident.name);
|
||||
let lt_def_names = params.iter().filter_map(|param| match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => Some(param.ident.name),
|
||||
_ => None,
|
||||
});
|
||||
self.in_scope_lifetimes.extend(lt_def_names);
|
||||
|
||||
let res = f(self);
|
||||
|
|
@ -771,17 +761,22 @@ impl<'a> LoweringContext<'a> {
|
|||
res
|
||||
}
|
||||
|
||||
// Same as the method above, but accepts `hir::LifetimeDef`s
|
||||
// instead of `ast::LifetimeDef`s.
|
||||
// Same as the method above, but accepts `hir::GenericParam`s
|
||||
// instead of `ast::GenericParam`s.
|
||||
// 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
|
||||
where
|
||||
fn with_parent_impl_lifetime_defs<T, F>(&mut self,
|
||||
params: &HirVec<hir::GenericParam>,
|
||||
f: F
|
||||
) -> T where
|
||||
F: FnOnce(&mut LoweringContext) -> T,
|
||||
{
|
||||
let old_len = self.in_scope_lifetimes.len();
|
||||
let lt_def_names = lt_defs.iter().map(|lt_def| lt_def.lifetime.name.name());
|
||||
let lt_def_names = params.iter().filter_map(|param| match param.kind {
|
||||
hir::GenericParamKind::Lifetime { .. } => Some(param.name.name()),
|
||||
_ => None,
|
||||
});
|
||||
self.in_scope_lifetimes.extend(lt_def_names);
|
||||
|
||||
let res = f(self);
|
||||
|
|
@ -807,10 +802,7 @@ impl<'a> LoweringContext<'a> {
|
|||
F: FnOnce(&mut LoweringContext) -> T,
|
||||
{
|
||||
let (in_band_defs, (mut lowered_generics, res)) = self.with_in_scope_lifetime_defs(
|
||||
generics.params.iter().filter_map(|p| match p {
|
||||
GenericParam::Lifetime(ld) => Some(ld),
|
||||
_ => None,
|
||||
}),
|
||||
&generics.params,
|
||||
|this| {
|
||||
let itctx = ImplTraitContext::Universal(parent_id);
|
||||
this.collect_in_band_defs(parent_id, anonymous_lifetime_mode, |this| {
|
||||
|
|
@ -1037,6 +1029,16 @@ impl<'a> LoweringContext<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn lower_generic_arg(&mut self,
|
||||
arg: &ast::GenericArg,
|
||||
itctx: ImplTraitContext)
|
||||
-> hir::GenericArg {
|
||||
match arg {
|
||||
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)),
|
||||
ast::GenericArg::Type(ty) => GenericArg::Type(self.lower_ty(&ty, itctx)),
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P<hir::Ty> {
|
||||
let kind = match t.node {
|
||||
TyKind::Infer => hir::TyInfer,
|
||||
|
|
@ -1052,10 +1054,7 @@ impl<'a> LoweringContext<'a> {
|
|||
hir::TyRptr(lifetime, self.lower_mt(mt, itctx))
|
||||
}
|
||||
TyKind::BareFn(ref f) => self.with_in_scope_lifetime_defs(
|
||||
f.generic_params.iter().filter_map(|p| match p {
|
||||
GenericParam::Lifetime(ld) => Some(ld),
|
||||
_ => None,
|
||||
}),
|
||||
&f.generic_params,
|
||||
|this| {
|
||||
this.with_anonymous_lifetime_mode(
|
||||
AnonymousLifetimeMode::PassThrough,
|
||||
|
|
@ -1110,11 +1109,11 @@ impl<'a> LoweringContext<'a> {
|
|||
let bounds = bounds
|
||||
.iter()
|
||||
.filter_map(|bound| match *bound {
|
||||
TraitTyParamBound(ref ty, TraitBoundModifier::None) => {
|
||||
GenericBound::Trait(ref ty, TraitBoundModifier::None) => {
|
||||
Some(self.lower_poly_trait_ref(ty, itctx))
|
||||
}
|
||||
TraitTyParamBound(_, TraitBoundModifier::Maybe) => None,
|
||||
RegionTyParamBound(ref lifetime) => {
|
||||
GenericBound::Trait(_, TraitBoundModifier::Maybe) => None,
|
||||
GenericBound::Outlives(ref lifetime) => {
|
||||
if lifetime_bound.is_none() {
|
||||
lifetime_bound = Some(self.lower_lifetime(lifetime));
|
||||
}
|
||||
|
|
@ -1166,7 +1165,7 @@ impl<'a> LoweringContext<'a> {
|
|||
self.allocate_hir_id_counter(exist_ty_node_id, t);
|
||||
|
||||
let hir_bounds = self.with_hir_id_owner(exist_ty_node_id, |lctx| {
|
||||
lctx.lower_bounds(bounds, itctx)
|
||||
lctx.lower_param_bounds(bounds, itctx)
|
||||
});
|
||||
|
||||
let (lifetimes, lifetime_defs) = self.lifetimes_from_impl_trait_bounds(
|
||||
|
|
@ -1233,18 +1232,20 @@ impl<'a> LoweringContext<'a> {
|
|||
span,
|
||||
);
|
||||
|
||||
let hir_bounds = self.lower_bounds(bounds, itctx);
|
||||
let hir_bounds = self.lower_param_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,
|
||||
name: ParamName::Plain(name),
|
||||
span,
|
||||
pure_wrt_drop: false,
|
||||
synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
|
||||
attrs: P::new(),
|
||||
attrs: hir_vec![],
|
||||
bounds: hir_bounds,
|
||||
kind: hir::GenericParamKind::Type {
|
||||
default: None,
|
||||
synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
|
||||
}
|
||||
});
|
||||
|
||||
hir::TyPath(hir::QPath::Resolved(
|
||||
|
|
@ -1284,7 +1285,7 @@ impl<'a> LoweringContext<'a> {
|
|||
&mut self,
|
||||
exist_ty_id: NodeId,
|
||||
parent_index: DefIndex,
|
||||
bounds: &hir::TyParamBounds,
|
||||
bounds: &hir::GenericBounds,
|
||||
) -> (HirVec<hir::Lifetime>, HirVec<hir::GenericParam>) {
|
||||
// This visitor walks over impl trait bounds and creates defs for all lifetimes which
|
||||
// appear in the bounds, excluding lifetimes that are created within the bounds.
|
||||
|
|
@ -1307,15 +1308,15 @@ impl<'a> LoweringContext<'a> {
|
|||
hir::intravisit::NestedVisitorMap::None
|
||||
}
|
||||
|
||||
fn visit_path_parameters(&mut self, span: Span, parameters: &'v hir::PathParameters) {
|
||||
fn visit_generic_args(&mut self, span: Span, parameters: &'v hir::GenericArgs) {
|
||||
// Don't collect elided lifetimes used inside of `Fn()` syntax.
|
||||
if parameters.parenthesized {
|
||||
let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
|
||||
self.collect_elided_lifetimes = false;
|
||||
hir::intravisit::walk_path_parameters(self, span, parameters);
|
||||
hir::intravisit::walk_generic_args(self, span, parameters);
|
||||
self.collect_elided_lifetimes = old_collect_elided_lifetimes;
|
||||
} else {
|
||||
hir::intravisit::walk_path_parameters(self, span, parameters);
|
||||
hir::intravisit::walk_generic_args(self, span, parameters);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1351,10 +1352,11 @@ 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 { .. } = 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);
|
||||
let lt_name = hir::LifetimeName::Param(param.name);
|
||||
self.currently_bound_lifetimes.push(lt_name);
|
||||
}
|
||||
|
||||
hir::intravisit::walk_generic_param(self, param);
|
||||
|
|
@ -1371,14 +1373,12 @@ impl<'a> LoweringContext<'a> {
|
|||
return;
|
||||
}
|
||||
}
|
||||
name @ hir::LifetimeName::Fresh(_) => name,
|
||||
name @ hir::LifetimeName::Name(_) => name,
|
||||
hir::LifetimeName::Param(_) => lifetime.name,
|
||||
hir::LifetimeName::Static => return,
|
||||
};
|
||||
|
||||
if !self.currently_bound_lifetimes.contains(&name)
|
||||
&& !self.already_defined_lifetimes.contains(&name)
|
||||
{
|
||||
&& !self.already_defined_lifetimes.contains(&name) {
|
||||
self.already_defined_lifetimes.insert(name);
|
||||
|
||||
self.output_lifetimes.push(hir::Lifetime {
|
||||
|
|
@ -1395,23 +1395,31 @@ impl<'a> LoweringContext<'a> {
|
|||
self.context.resolver.definitions().create_def_with_parent(
|
||||
self.parent,
|
||||
def_node_id,
|
||||
DefPathData::LifetimeDef(name.name().as_interned_str()),
|
||||
DefPathData::LifetimeParam(name.name().as_interned_str()),
|
||||
DefIndexAddressSpace::High,
|
||||
Mark::root(),
|
||||
lifetime.span,
|
||||
);
|
||||
let def_lifetime = hir::Lifetime {
|
||||
id: def_node_id,
|
||||
span: lifetime.span,
|
||||
name,
|
||||
|
||||
let name = match name {
|
||||
hir::LifetimeName::Underscore => {
|
||||
hir::ParamName::Plain(keywords::UnderscoreLifetime.name())
|
||||
}
|
||||
hir::LifetimeName::Param(param_name) => param_name,
|
||||
_ => bug!("expected LifetimeName::Param or ParamName::Plain"),
|
||||
};
|
||||
self.output_lifetime_params
|
||||
.push(hir::GenericParam::Lifetime(hir::LifetimeDef {
|
||||
lifetime: def_lifetime,
|
||||
bounds: Vec::new().into(),
|
||||
pure_wrt_drop: false,
|
||||
|
||||
self.output_lifetime_params.push(hir::GenericParam {
|
||||
id: def_node_id,
|
||||
name,
|
||||
span: lifetime.span,
|
||||
pure_wrt_drop: false,
|
||||
attrs: hir_vec![],
|
||||
bounds: hir_vec![],
|
||||
kind: hir::GenericParamKind::Lifetime {
|
||||
in_band: false,
|
||||
}));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1428,7 +1436,7 @@ impl<'a> LoweringContext<'a> {
|
|||
};
|
||||
|
||||
for bound in bounds {
|
||||
hir::intravisit::walk_ty_param_bound(&mut lifetime_collector, &bound);
|
||||
hir::intravisit::walk_param_bound(&mut lifetime_collector, &bound);
|
||||
}
|
||||
|
||||
(
|
||||
|
|
@ -1669,13 +1677,13 @@ impl<'a> LoweringContext<'a> {
|
|||
parenthesized_generic_args: ParenthesizedGenericArgs,
|
||||
itctx: ImplTraitContext,
|
||||
) -> hir::PathSegment {
|
||||
let (mut parameters, infer_types) = if let Some(ref parameters) = segment.parameters {
|
||||
let (mut generic_args, infer_types) = if let Some(ref generic_args) = segment.args {
|
||||
let msg = "parenthesized parameters may only be used with a trait";
|
||||
match **parameters {
|
||||
PathParameters::AngleBracketed(ref data) => {
|
||||
match **generic_args {
|
||||
GenericArgs::AngleBracketed(ref data) => {
|
||||
self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
|
||||
}
|
||||
PathParameters::Parenthesized(ref data) => match parenthesized_generic_args {
|
||||
GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args {
|
||||
ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data),
|
||||
ParenthesizedGenericArgs::Warn => {
|
||||
self.sess.buffer_lint(
|
||||
|
|
@ -1684,13 +1692,13 @@ impl<'a> LoweringContext<'a> {
|
|||
data.span,
|
||||
msg.into(),
|
||||
);
|
||||
(hir::PathParameters::none(), true)
|
||||
(hir::GenericArgs::none(), true)
|
||||
}
|
||||
ParenthesizedGenericArgs::Err => {
|
||||
struct_span_err!(self.sess, data.span, E0214, "{}", msg)
|
||||
.span_label(data.span, "only traits may use parentheses")
|
||||
.emit();
|
||||
(hir::PathParameters::none(), true)
|
||||
(hir::GenericArgs::none(), true)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
@ -1698,47 +1706,49 @@ impl<'a> LoweringContext<'a> {
|
|||
self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode, itctx)
|
||||
};
|
||||
|
||||
if !parameters.parenthesized && parameters.lifetimes.is_empty() {
|
||||
parameters.lifetimes = self.elided_path_lifetimes(path_span, expected_lifetimes);
|
||||
let has_lifetimes = generic_args.args.iter().any(|arg| match arg {
|
||||
GenericArg::Lifetime(_) => true,
|
||||
_ => false,
|
||||
});
|
||||
if !generic_args.parenthesized && !has_lifetimes {
|
||||
generic_args.args =
|
||||
self.elided_path_lifetimes(path_span, expected_lifetimes)
|
||||
.into_iter()
|
||||
.map(|lt| GenericArg::Lifetime(lt))
|
||||
.chain(generic_args.args.into_iter())
|
||||
.collect();
|
||||
}
|
||||
|
||||
hir::PathSegment::new(
|
||||
self.lower_ident(segment.ident),
|
||||
parameters,
|
||||
generic_args,
|
||||
infer_types,
|
||||
)
|
||||
}
|
||||
|
||||
fn lower_angle_bracketed_parameter_data(
|
||||
&mut self,
|
||||
data: &AngleBracketedParameterData,
|
||||
data: &AngleBracketedArgs,
|
||||
param_mode: ParamMode,
|
||||
itctx: ImplTraitContext,
|
||||
) -> (hir::PathParameters, bool) {
|
||||
let &AngleBracketedParameterData {
|
||||
ref lifetimes,
|
||||
ref types,
|
||||
ref bindings,
|
||||
..
|
||||
} = data;
|
||||
(
|
||||
hir::PathParameters {
|
||||
lifetimes: self.lower_lifetimes(lifetimes),
|
||||
types: types.iter().map(|ty| self.lower_ty(ty, itctx)).collect(),
|
||||
bindings: bindings
|
||||
.iter()
|
||||
.map(|b| self.lower_ty_binding(b, itctx))
|
||||
.collect(),
|
||||
parenthesized: false,
|
||||
},
|
||||
types.is_empty() && param_mode == ParamMode::Optional,
|
||||
)
|
||||
) -> (hir::GenericArgs, bool) {
|
||||
let &AngleBracketedArgs { ref args, ref bindings, .. } = data;
|
||||
let has_types = args.iter().any(|arg| match arg {
|
||||
ast::GenericArg::Type(_) => true,
|
||||
_ => false,
|
||||
});
|
||||
(hir::GenericArgs {
|
||||
args: args.iter().map(|a| self.lower_generic_arg(a, itctx)).collect(),
|
||||
bindings: bindings.iter().map(|b| self.lower_ty_binding(b, itctx)).collect(),
|
||||
parenthesized: false,
|
||||
},
|
||||
!has_types && param_mode == ParamMode::Optional)
|
||||
}
|
||||
|
||||
fn lower_parenthesized_parameter_data(
|
||||
&mut self,
|
||||
data: &ParenthesizedParameterData,
|
||||
) -> (hir::PathParameters, bool) {
|
||||
data: &ParenthesisedArgs,
|
||||
) -> (hir::GenericArgs, bool) {
|
||||
// Switch to `PassThrough` mode for anonymous lifetimes: this
|
||||
// means that we permit things like `&Ref<T>`, where `Ref` has
|
||||
// a hidden lifetime parameter. This is needed for backwards
|
||||
|
|
@ -1748,29 +1758,16 @@ impl<'a> LoweringContext<'a> {
|
|||
AnonymousLifetimeMode::PassThrough,
|
||||
|this| {
|
||||
const DISALLOWED: ImplTraitContext = ImplTraitContext::Disallowed;
|
||||
let &ParenthesizedParameterData {
|
||||
ref inputs,
|
||||
ref output,
|
||||
span,
|
||||
} = data;
|
||||
let inputs = inputs
|
||||
.iter()
|
||||
.map(|ty| this.lower_ty(ty, DISALLOWED))
|
||||
.collect();
|
||||
let &ParenthesisedArgs { ref inputs, ref output, span } = data;
|
||||
let inputs = inputs.iter().map(|ty| this.lower_ty(ty, DISALLOWED)).collect();
|
||||
let mk_tup = |this: &mut Self, tys, span| {
|
||||
let LoweredNodeId { node_id, hir_id } = this.next_id();
|
||||
P(hir::Ty {
|
||||
node: hir::TyTup(tys),
|
||||
id: node_id,
|
||||
hir_id,
|
||||
span,
|
||||
})
|
||||
P(hir::Ty { node: hir::TyTup(tys), id: node_id, hir_id, span })
|
||||
};
|
||||
|
||||
(
|
||||
hir::PathParameters {
|
||||
lifetimes: hir::HirVec::new(),
|
||||
types: hir_vec![mk_tup(this, inputs, span)],
|
||||
hir::GenericArgs {
|
||||
args: hir_vec![GenericArg::Type(mk_tup(this, inputs, span))],
|
||||
bindings: hir_vec![
|
||||
hir::TypeBinding {
|
||||
id: this.next_id().node_id,
|
||||
|
|
@ -1874,63 +1871,22 @@ impl<'a> LoweringContext<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
fn lower_ty_param_bound(
|
||||
fn lower_param_bound(
|
||||
&mut self,
|
||||
tpb: &TyParamBound,
|
||||
tpb: &GenericBound,
|
||||
itctx: ImplTraitContext,
|
||||
) -> hir::TyParamBound {
|
||||
) -> hir::GenericBound {
|
||||
match *tpb {
|
||||
TraitTyParamBound(ref ty, modifier) => hir::TraitTyParamBound(
|
||||
GenericBound::Trait(ref ty, modifier) => hir::GenericBound::Trait(
|
||||
self.lower_poly_trait_ref(ty, itctx),
|
||||
self.lower_trait_bound_modifier(modifier),
|
||||
),
|
||||
RegionTyParamBound(ref lifetime) => {
|
||||
hir::RegionTyParamBound(self.lower_lifetime(lifetime))
|
||||
GenericBound::Outlives(ref lifetime) => {
|
||||
hir::GenericBound::Outlives(self.lower_lifetime(lifetime))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
|
|
@ -1938,7 +1894,7 @@ impl<'a> LoweringContext<'a> {
|
|||
x if x == "'_" => match self.anonymous_lifetime_mode {
|
||||
AnonymousLifetimeMode::CreateParameter => {
|
||||
let fresh_name = self.collect_fresh_in_band_lifetime(span);
|
||||
self.new_named_lifetime(l.id, span, fresh_name)
|
||||
self.new_named_lifetime(l.id, span, hir::LifetimeName::Param(fresh_name))
|
||||
}
|
||||
|
||||
AnonymousLifetimeMode::PassThrough => {
|
||||
|
|
@ -1947,7 +1903,8 @@ impl<'a> LoweringContext<'a> {
|
|||
},
|
||||
name => {
|
||||
self.maybe_collect_in_band_lifetime(span, name);
|
||||
self.new_named_lifetime(l.id, span, hir::LifetimeName::Name(name))
|
||||
let param_name = ParamName::Plain(name);
|
||||
self.new_named_lifetime(l.id, span, hir::LifetimeName::Param(param_name))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1965,57 +1922,98 @@ impl<'a> LoweringContext<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn lower_lifetime_def(&mut self, l: &LifetimeDef) -> hir::LifetimeDef {
|
||||
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: self.lower_lifetimes(&l.bounds),
|
||||
pure_wrt_drop: attr::contains_name(&l.attrs, "may_dangle"),
|
||||
in_band: false,
|
||||
};
|
||||
|
||||
self.is_collecting_in_band_lifetimes = was_collecting_in_band;
|
||||
|
||||
def
|
||||
}
|
||||
|
||||
fn lower_lifetimes(&mut self, lts: &Vec<Lifetime>) -> hir::HirVec<hir::Lifetime> {
|
||||
lts.iter().map(|l| self.lower_lifetime(l)).collect()
|
||||
}
|
||||
|
||||
fn lower_generic_params(
|
||||
&mut self,
|
||||
params: &Vec<GenericParam>,
|
||||
add_bounds: &NodeMap<Vec<TyParamBound>>,
|
||||
add_bounds: &NodeMap<Vec<GenericBound>>,
|
||||
itctx: ImplTraitContext,
|
||||
) -> hir::HirVec<hir::GenericParam> {
|
||||
params
|
||||
.iter()
|
||||
.map(|param| match *param {
|
||||
GenericParam::Lifetime(ref lifetime_def) => {
|
||||
hir::GenericParam::Lifetime(self.lower_lifetime_def(lifetime_def))
|
||||
}
|
||||
GenericParam::Type(ref ty_param) => hir::GenericParam::Type(self.lower_ty_param(
|
||||
ty_param,
|
||||
add_bounds.get(&ty_param.id).map_or(&[][..], |x| &x),
|
||||
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 {
|
||||
fn lower_generic_param(&mut self,
|
||||
param: &GenericParam,
|
||||
add_bounds: &NodeMap<Vec<GenericBound>>,
|
||||
itctx: ImplTraitContext)
|
||||
-> hir::GenericParam {
|
||||
let mut bounds = self.lower_param_bounds(¶m.bounds, itctx);
|
||||
match param.kind {
|
||||
GenericParamKind::Lifetime => {
|
||||
let was_collecting_in_band = self.is_collecting_in_band_lifetimes;
|
||||
self.is_collecting_in_band_lifetimes = false;
|
||||
|
||||
let lt = self.lower_lifetime(&Lifetime { id: param.id, ident: param.ident });
|
||||
let param_name = match lt.name {
|
||||
hir::LifetimeName::Param(param_name) => param_name,
|
||||
_ => hir::ParamName::Plain(lt.name.name()),
|
||||
};
|
||||
let param = hir::GenericParam {
|
||||
id: lt.id,
|
||||
name: param_name,
|
||||
span: lt.span,
|
||||
pure_wrt_drop: attr::contains_name(¶m.attrs, "may_dangle"),
|
||||
attrs: self.lower_attrs(¶m.attrs),
|
||||
bounds,
|
||||
kind: hir::GenericParamKind::Lifetime { in_band: false }
|
||||
};
|
||||
|
||||
self.is_collecting_in_band_lifetimes = was_collecting_in_band;
|
||||
|
||||
param
|
||||
}
|
||||
GenericParamKind::Type { ref default, .. } => {
|
||||
let mut name = self.lower_ident(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 add_bounds = add_bounds.get(¶m.id).map_or(&[][..], |x| &x);
|
||||
if !add_bounds.is_empty() {
|
||||
bounds = bounds.into_iter()
|
||||
.chain(self.lower_param_bounds(add_bounds, itctx).into_iter())
|
||||
.collect();
|
||||
}
|
||||
|
||||
hir::GenericParam {
|
||||
id: self.lower_node_id(param.id).node_id,
|
||||
name: hir::ParamName::Plain(name),
|
||||
span: param.ident.span,
|
||||
pure_wrt_drop: attr::contains_name(¶m.attrs, "may_dangle"),
|
||||
attrs: self.lower_attrs(¶m.attrs),
|
||||
bounds,
|
||||
kind: hir::GenericParamKind::Type {
|
||||
default: default.as_ref().map(|x| {
|
||||
self.lower_ty(x, ImplTraitContext::Disallowed)
|
||||
}),
|
||||
synthetic: param.attrs.iter()
|
||||
.filter(|attr| attr.check_name("rustc_synthetic"))
|
||||
.map(|_| hir::SyntheticTyParamKind::ImplTrait)
|
||||
.next(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_generics(
|
||||
&mut self,
|
||||
generics: &Generics,
|
||||
itctx: ImplTraitContext)
|
||||
-> hir::Generics
|
||||
{
|
||||
// Collect `?Trait` bounds in where clause and move them to parameter definitions.
|
||||
// FIXME: This could probably be done with less rightward drift. Also looks like two control
|
||||
// paths where report_error is called are also the only paths that advance to after
|
||||
// the match statement, so the error reporting could probably just be moved there.
|
||||
let mut add_bounds = NodeMap();
|
||||
for pred in &g.where_clause.predicates {
|
||||
for pred in &generics.where_clause.predicates {
|
||||
if let WherePredicate::BoundPredicate(ref bound_pred) = *pred {
|
||||
'next_bound: for bound in &bound_pred.bounds {
|
||||
if let TraitTyParamBound(_, TraitBoundModifier::Maybe) = *bound {
|
||||
if let GenericBound::Trait(_, TraitBoundModifier::Maybe) = *bound {
|
||||
let report_error = |this: &mut Self| {
|
||||
this.diagnostic().span_err(
|
||||
bound_pred.bounded_ty.span,
|
||||
|
|
@ -2036,15 +2034,17 @@ impl<'a> LoweringContext<'a> {
|
|||
if let Some(node_id) =
|
||||
self.resolver.definitions().as_local_node_id(def_id)
|
||||
{
|
||||
for param in &g.params {
|
||||
if let GenericParam::Type(ref ty_param) = *param {
|
||||
if node_id == ty_param.id {
|
||||
add_bounds
|
||||
.entry(ty_param.id)
|
||||
.or_insert(Vec::new())
|
||||
.push(bound.clone());
|
||||
continue 'next_bound;
|
||||
for param in &generics.params {
|
||||
match param.kind {
|
||||
GenericParamKind::Type { .. } => {
|
||||
if node_id == param.id {
|
||||
add_bounds.entry(param.id)
|
||||
.or_insert(Vec::new())
|
||||
.push(bound.clone());
|
||||
continue 'next_bound;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2059,9 +2059,9 @@ impl<'a> LoweringContext<'a> {
|
|||
}
|
||||
|
||||
hir::Generics {
|
||||
params: self.lower_generic_params(&g.params, &add_bounds, itctx),
|
||||
where_clause: self.lower_where_clause(&g.where_clause),
|
||||
span: g.span,
|
||||
params: self.lower_generic_params(&generics.params, &add_bounds, itctx),
|
||||
where_clause: self.lower_where_clause(&generics.where_clause),
|
||||
span: generics.span,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2084,10 +2084,7 @@ impl<'a> LoweringContext<'a> {
|
|||
span,
|
||||
}) => {
|
||||
self.with_in_scope_lifetime_defs(
|
||||
bound_generic_params.iter().filter_map(|p| match p {
|
||||
GenericParam::Lifetime(ld) => Some(ld),
|
||||
_ => None,
|
||||
}),
|
||||
&bound_generic_params,
|
||||
|this| {
|
||||
hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
|
||||
bound_generic_params: this.lower_generic_params(
|
||||
|
|
@ -2101,8 +2098,8 @@ impl<'a> LoweringContext<'a> {
|
|||
.filter_map(|bound| match *bound {
|
||||
// Ignore `?Trait` bounds.
|
||||
// Tthey were copied into type parameters already.
|
||||
TraitTyParamBound(_, TraitBoundModifier::Maybe) => None,
|
||||
_ => Some(this.lower_ty_param_bound(
|
||||
GenericBound::Trait(_, TraitBoundModifier::Maybe) => None,
|
||||
_ => Some(this.lower_param_bound(
|
||||
bound,
|
||||
ImplTraitContext::Disallowed,
|
||||
)),
|
||||
|
|
@ -2120,10 +2117,7 @@ impl<'a> LoweringContext<'a> {
|
|||
}) => hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
|
||||
span,
|
||||
lifetime: self.lower_lifetime(lifetime),
|
||||
bounds: bounds
|
||||
.iter()
|
||||
.map(|bound| self.lower_lifetime(bound))
|
||||
.collect(),
|
||||
bounds: self.lower_param_bounds(bounds, ImplTraitContext::Disallowed),
|
||||
}),
|
||||
WherePredicate::EqPredicate(WhereEqPredicate {
|
||||
id,
|
||||
|
|
@ -2180,13 +2174,7 @@ impl<'a> LoweringContext<'a> {
|
|||
let bound_generic_params =
|
||||
self.lower_generic_params(&p.bound_generic_params, &NodeMap(), itctx);
|
||||
let trait_ref = self.with_parent_impl_lifetime_defs(
|
||||
&bound_generic_params
|
||||
.iter()
|
||||
.filter_map(|p| match *p {
|
||||
hir::GenericParam::Lifetime(ref ld) => Some(ld.clone()),
|
||||
_ => None,
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
&bound_generic_params,
|
||||
|this| this.lower_trait_ref(&p.trait_ref, itctx),
|
||||
);
|
||||
|
||||
|
|
@ -2229,15 +2217,9 @@ impl<'a> LoweringContext<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn lower_bounds(
|
||||
&mut self,
|
||||
bounds: &[TyParamBound],
|
||||
itctx: ImplTraitContext,
|
||||
) -> hir::TyParamBounds {
|
||||
bounds
|
||||
.iter()
|
||||
.map(|bound| self.lower_ty_param_bound(bound, itctx))
|
||||
.collect()
|
||||
fn lower_param_bounds(&mut self, bounds: &[GenericBound], itctx: ImplTraitContext)
|
||||
-> hir::GenericBounds {
|
||||
bounds.iter().map(|bound| self.lower_param_bound(bound, itctx)).collect()
|
||||
}
|
||||
|
||||
fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block> {
|
||||
|
|
@ -2403,10 +2385,7 @@ impl<'a> LoweringContext<'a> {
|
|||
);
|
||||
|
||||
let new_impl_items = self.with_in_scope_lifetime_defs(
|
||||
ast_generics.params.iter().filter_map(|p| match p {
|
||||
GenericParam::Lifetime(ld) => Some(ld),
|
||||
_ => None,
|
||||
}),
|
||||
&ast_generics.params,
|
||||
|this| {
|
||||
impl_items
|
||||
.iter()
|
||||
|
|
@ -2426,7 +2405,7 @@ impl<'a> LoweringContext<'a> {
|
|||
)
|
||||
}
|
||||
ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref items) => {
|
||||
let bounds = self.lower_bounds(bounds, ImplTraitContext::Disallowed);
|
||||
let bounds = self.lower_param_bounds(bounds, ImplTraitContext::Disallowed);
|
||||
let items = items
|
||||
.iter()
|
||||
.map(|item| self.lower_trait_item_ref(item))
|
||||
|
|
@ -2441,7 +2420,7 @@ impl<'a> LoweringContext<'a> {
|
|||
}
|
||||
ItemKind::TraitAlias(ref generics, ref bounds) => hir::ItemTraitAlias(
|
||||
self.lower_generics(generics, ImplTraitContext::Disallowed),
|
||||
self.lower_bounds(bounds, ImplTraitContext::Disallowed),
|
||||
self.lower_param_bounds(bounds, ImplTraitContext::Disallowed),
|
||||
),
|
||||
ItemKind::MacroDef(..) | ItemKind::Mac(..) => panic!("Shouldn't still be around"),
|
||||
}
|
||||
|
|
@ -2668,7 +2647,7 @@ impl<'a> LoweringContext<'a> {
|
|||
TraitItemKind::Type(ref bounds, ref default) => (
|
||||
self.lower_generics(&i.generics, ImplTraitContext::Disallowed),
|
||||
hir::TraitItemKind::Type(
|
||||
self.lower_bounds(bounds, ImplTraitContext::Disallowed),
|
||||
self.lower_param_bounds(bounds, ImplTraitContext::Disallowed),
|
||||
default
|
||||
.as_ref()
|
||||
.map(|x| self.lower_ty(x, ImplTraitContext::Disallowed)),
|
||||
|
|
@ -4217,7 +4196,7 @@ impl<'a> LoweringContext<'a> {
|
|||
hir::Lifetime {
|
||||
id: self.next_id().node_id,
|
||||
span,
|
||||
name: fresh_name,
|
||||
name: hir::LifetimeName::Param(fresh_name),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,14 +347,7 @@ 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));
|
||||
}
|
||||
GenericParam::Type(ref ty_param) => {
|
||||
self.insert(ty_param.id, NodeTyParam(ty_param));
|
||||
}
|
||||
}
|
||||
self.insert(param.id, NodeGenericParam(param));
|
||||
intravisit::walk_generic_param(self, param);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -171,24 +171,12 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
|||
}
|
||||
|
||||
fn visit_generic_param(&mut self, param: &'a GenericParam) {
|
||||
match *param {
|
||||
GenericParam::Lifetime(ref lifetime_def) => {
|
||||
self.create_def(
|
||||
lifetime_def.lifetime.id,
|
||||
DefPathData::LifetimeDef(lifetime_def.lifetime.ident.name.as_interned_str()),
|
||||
REGULAR_SPACE,
|
||||
lifetime_def.lifetime.ident.span
|
||||
);
|
||||
}
|
||||
GenericParam::Type(ref ty_param) => {
|
||||
self.create_def(
|
||||
ty_param.id,
|
||||
DefPathData::TypeParam(ty_param.ident.name.as_interned_str()),
|
||||
REGULAR_SPACE,
|
||||
ty_param.ident.span
|
||||
);
|
||||
}
|
||||
}
|
||||
let name = param.ident.name.as_interned_str();
|
||||
let def_path_data = match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => DefPathData::LifetimeParam(name),
|
||||
GenericParamKind::Type { .. } => DefPathData::TypeParam(name),
|
||||
};
|
||||
self.create_def(param.id, def_path_data, REGULAR_SPACE, param.ident.span);
|
||||
|
||||
visit::walk_generic_param(self, param);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -360,7 +360,7 @@ pub enum DefPathData {
|
|||
/// A type parameter (generic parameter)
|
||||
TypeParam(InternedString),
|
||||
/// A lifetime definition
|
||||
LifetimeDef(InternedString),
|
||||
LifetimeParam(InternedString),
|
||||
/// A variant of a enum
|
||||
EnumVariant(InternedString),
|
||||
/// A struct field
|
||||
|
|
@ -625,7 +625,7 @@ impl DefPathData {
|
|||
Module(name) |
|
||||
MacroDef(name) |
|
||||
TypeParam(name) |
|
||||
LifetimeDef(name) |
|
||||
LifetimeParam(name) |
|
||||
EnumVariant(name) |
|
||||
Field(name) |
|
||||
GlobalMetaData(name) => Some(name),
|
||||
|
|
@ -652,7 +652,7 @@ impl DefPathData {
|
|||
Module(name) |
|
||||
MacroDef(name) |
|
||||
TypeParam(name) |
|
||||
LifetimeDef(name) |
|
||||
LifetimeParam(name) |
|
||||
EnumVariant(name) |
|
||||
Field(name) |
|
||||
GlobalMetaData(name) => {
|
||||
|
|
|
|||
|
|
@ -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,8 +494,11 @@ impl<'hir> Map<'hir> {
|
|||
Some(Def::Macro(self.local_def_id(macro_def.id),
|
||||
MacroKind::Bang))
|
||||
}
|
||||
NodeTyParam(param) => {
|
||||
Some(Def::TyParam(self.local_def_id(param.id)))
|
||||
NodeGenericParam(param) => {
|
||||
Some(match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => Def::Local(param.id),
|
||||
GenericParamKind::Type { .. } => Def::TyParam(self.local_def_id(param.id)),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -600,7 +603,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,11 +616,8 @@ impl<'hir> Map<'hir> {
|
|||
NodeItem(&Item { node: ItemTrait(..), .. }) => {
|
||||
keywords::SelfType.name()
|
||||
}
|
||||
NodeTyParam(tp) => tp.name,
|
||||
_ => {
|
||||
bug!("ty_param_name: {} not a type parameter",
|
||||
self.node_to_string(id))
|
||||
}
|
||||
NodeGenericParam(param) => param.name.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.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,7 @@ 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)) => Some(¶m.attrs[..]),
|
||||
// unit/tuple structs take the attributes straight from
|
||||
// the struct definition.
|
||||
Some(NodeStructCtor(_)) => {
|
||||
|
|
@ -1021,7 +1021,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,
|
||||
|
|
@ -1226,19 +1226,19 @@ impl<'hir> print::PpAnn for Map<'hir> {
|
|||
impl<'a> print::State<'a> {
|
||||
pub fn print_node(&mut self, node: Node) -> io::Result<()> {
|
||||
match node {
|
||||
NodeItem(a) => self.print_item(&a),
|
||||
NodeForeignItem(a) => self.print_foreign_item(&a),
|
||||
NodeTraitItem(a) => self.print_trait_item(a),
|
||||
NodeImplItem(a) => self.print_impl_item(a),
|
||||
NodeVariant(a) => self.print_variant(&a),
|
||||
NodeAnonConst(a) => self.print_anon_const(&a),
|
||||
NodeExpr(a) => self.print_expr(&a),
|
||||
NodeStmt(a) => self.print_stmt(&a),
|
||||
NodeTy(a) => self.print_type(&a),
|
||||
NodeTraitRef(a) => self.print_trait_ref(&a),
|
||||
NodeItem(a) => self.print_item(&a),
|
||||
NodeForeignItem(a) => self.print_foreign_item(&a),
|
||||
NodeTraitItem(a) => self.print_trait_item(a),
|
||||
NodeImplItem(a) => self.print_impl_item(a),
|
||||
NodeVariant(a) => self.print_variant(&a),
|
||||
NodeAnonConst(a) => self.print_anon_const(&a),
|
||||
NodeExpr(a) => self.print_expr(&a),
|
||||
NodeStmt(a) => self.print_stmt(&a),
|
||||
NodeTy(a) => self.print_type(&a),
|
||||
NodeTraitRef(a) => self.print_trait_ref(&a),
|
||||
NodeBinding(a) |
|
||||
NodePat(a) => self.print_pat(&a),
|
||||
NodeBlock(a) => {
|
||||
NodePat(a) => self.print_pat(&a),
|
||||
NodeBlock(a) => {
|
||||
use syntax::print::pprust::PrintState;
|
||||
|
||||
// containing cbox, will be closed by print-block at }
|
||||
|
|
@ -1247,16 +1247,16 @@ impl<'a> print::State<'a> {
|
|||
self.ibox(0)?;
|
||||
self.print_block(&a)
|
||||
}
|
||||
NodeLifetime(a) => self.print_lifetime(&a),
|
||||
NodeVisibility(a) => self.print_visibility(&a),
|
||||
NodeTyParam(_) => bug!("cannot print TyParam"),
|
||||
NodeField(_) => bug!("cannot print StructField"),
|
||||
NodeLifetime(a) => self.print_lifetime(&a),
|
||||
NodeVisibility(a) => self.print_visibility(&a),
|
||||
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
|
||||
// printing.
|
||||
NodeStructCtor(_) => bug!("cannot print isolated StructCtor"),
|
||||
NodeLocal(a) => self.print_local_decl(&a),
|
||||
NodeMacroDef(_) => bug!("cannot print MacroDef"),
|
||||
NodeStructCtor(_) => bug!("cannot print isolated StructCtor"),
|
||||
NodeLocal(a) => self.print_local_decl(&a),
|
||||
NodeMacroDef(_) => bug!("cannot print MacroDef"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1371,8 +1371,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!("generic_param {:?}{}", param, id_str)
|
||||
}
|
||||
Some(NodeVisibility(ref vis)) => {
|
||||
format!("visibility {:?}{}", vis, id_str)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ pub use self::Mutability::*;
|
|||
pub use self::PrimTy::*;
|
||||
pub use self::Stmt_::*;
|
||||
pub use self::Ty_::*;
|
||||
pub use self::TyParamBound::*;
|
||||
pub use self::UnOp::*;
|
||||
pub use self::UnsafeSource::*;
|
||||
pub use self::Visibility::{Public, Inherited};
|
||||
|
|
@ -53,8 +52,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
|
||||
|
|
@ -203,12 +200,9 @@ pub struct Lifetime {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
|
||||
pub enum LifetimeName {
|
||||
/// User typed nothing. e.g. the lifetime in `&u32`.
|
||||
Implicit,
|
||||
|
||||
/// User typed `'_`.
|
||||
Underscore,
|
||||
pub enum ParamName {
|
||||
/// Some user-given name like `T` or `'x`.
|
||||
Plain(Name),
|
||||
|
||||
/// Synthetic name generated when user elided a lifetime in an impl header,
|
||||
/// e.g. the lifetimes in cases like these:
|
||||
|
|
@ -224,12 +218,30 @@ pub enum LifetimeName {
|
|||
/// where `'f` is something like `Fresh(0)`. The indices are
|
||||
/// unique per impl, but not necessarily continuous.
|
||||
Fresh(usize),
|
||||
}
|
||||
|
||||
impl ParamName {
|
||||
pub fn name(&self) -> Name {
|
||||
match *self {
|
||||
ParamName::Plain(name) => name,
|
||||
ParamName::Fresh(_) => keywords::UnderscoreLifetime.name(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
|
||||
pub enum LifetimeName {
|
||||
/// User-given names or fresh (synthetic) names.
|
||||
Param(ParamName),
|
||||
|
||||
/// User typed nothing. e.g. the lifetime in `&u32`.
|
||||
Implicit,
|
||||
|
||||
/// User typed `'_`.
|
||||
Underscore,
|
||||
|
||||
/// User wrote `'static`
|
||||
Static,
|
||||
|
||||
/// Some user-given name like `'x`
|
||||
Name(Name),
|
||||
}
|
||||
|
||||
impl LifetimeName {
|
||||
|
|
@ -237,11 +249,29 @@ impl LifetimeName {
|
|||
use self::LifetimeName::*;
|
||||
match *self {
|
||||
Implicit => keywords::Invalid.name(),
|
||||
Fresh(_) | Underscore => keywords::UnderscoreLifetime.name(),
|
||||
Underscore => keywords::UnderscoreLifetime.name(),
|
||||
Static => keywords::StaticLifetime.name(),
|
||||
Name(name) => name,
|
||||
Param(param_name) => param_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.
|
||||
Param(_) | Static => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_static(&self) -> bool {
|
||||
self == &LifetimeName::Static
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Lifetime {
|
||||
|
|
@ -255,36 +285,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.
|
||||
|
|
@ -327,7 +335,7 @@ pub struct PathSegment {
|
|||
/// this is more than just simple syntactic sugar; the use of
|
||||
/// parens affects the region binding rules, so we preserve the
|
||||
/// distinction.
|
||||
pub parameters: Option<P<PathParameters>>,
|
||||
pub args: Option<P<GenericArgs>>,
|
||||
|
||||
/// Whether to infer remaining type parameters, if any.
|
||||
/// This only applies to expression and pattern paths, and
|
||||
|
|
@ -342,30 +350,30 @@ impl PathSegment {
|
|||
PathSegment {
|
||||
name,
|
||||
infer_types: true,
|
||||
parameters: None
|
||||
args: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(name: Name, parameters: PathParameters, infer_types: bool) -> Self {
|
||||
pub fn new(name: Name, args: GenericArgs, infer_types: bool) -> Self {
|
||||
PathSegment {
|
||||
name,
|
||||
infer_types,
|
||||
parameters: if parameters.is_empty() {
|
||||
args: if args.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(P(parameters))
|
||||
Some(P(args))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: hack required because you can't create a static
|
||||
// PathParameters, so you can't just return a &PathParameters.
|
||||
pub fn with_parameters<F, R>(&self, f: F) -> R
|
||||
where F: FnOnce(&PathParameters) -> R
|
||||
// GenericArgs, so you can't just return a &GenericArgs.
|
||||
pub fn with_generic_args<F, R>(&self, f: F) -> R
|
||||
where F: FnOnce(&GenericArgs) -> R
|
||||
{
|
||||
let dummy = PathParameters::none();
|
||||
f(if let Some(ref params) = self.parameters {
|
||||
¶ms
|
||||
let dummy = GenericArgs::none();
|
||||
f(if let Some(ref args) = self.args {
|
||||
&args
|
||||
} else {
|
||||
&dummy
|
||||
})
|
||||
|
|
@ -373,63 +381,52 @@ impl PathSegment {
|
|||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub struct PathParameters {
|
||||
/// The lifetime parameters for this path segment.
|
||||
pub lifetimes: HirVec<Lifetime>,
|
||||
/// The type parameters for this path segment, if present.
|
||||
pub types: HirVec<P<Ty>>,
|
||||
pub enum GenericArg {
|
||||
Lifetime(Lifetime),
|
||||
Type(P<Ty>),
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub struct GenericArgs {
|
||||
/// The generic arguments for this path segment.
|
||||
pub args: HirVec<GenericArg>,
|
||||
/// Bindings (equality constraints) on associated types, if present.
|
||||
/// E.g., `Foo<A=Bar>`.
|
||||
pub bindings: HirVec<TypeBinding>,
|
||||
/// Were parameters written in parenthesized form `Fn(T) -> U`?
|
||||
/// Were arguments written in parenthesized form `Fn(T) -> U`?
|
||||
/// This is required mostly for pretty-printing and diagnostics,
|
||||
/// but also for changing lifetime elision rules to be "function-like".
|
||||
pub parenthesized: bool,
|
||||
}
|
||||
|
||||
impl PathParameters {
|
||||
impl GenericArgs {
|
||||
pub fn none() -> Self {
|
||||
Self {
|
||||
lifetimes: HirVec::new(),
|
||||
types: HirVec::new(),
|
||||
args: HirVec::new(),
|
||||
bindings: HirVec::new(),
|
||||
parenthesized: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.lifetimes.is_empty() && self.types.is_empty() &&
|
||||
self.bindings.is_empty() && !self.parenthesized
|
||||
self.args.is_empty() && self.bindings.is_empty() && !self.parenthesized
|
||||
}
|
||||
|
||||
pub fn inputs(&self) -> &[P<Ty>] {
|
||||
if self.parenthesized {
|
||||
if let Some(ref ty) = self.types.get(0) {
|
||||
if let TyTup(ref tys) = ty.node {
|
||||
return tys;
|
||||
for arg in &self.args {
|
||||
match arg {
|
||||
GenericArg::Lifetime(_) => {}
|
||||
GenericArg::Type(ref ty) => {
|
||||
if let TyTup(ref tys) = ty.node {
|
||||
return tys;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bug!("PathParameters::inputs: not a `Fn(T) -> U`");
|
||||
}
|
||||
}
|
||||
|
||||
/// The AST represents all type param bounds as types.
|
||||
/// typeck::collect::compute_bounds matches these against
|
||||
/// the "special" built-in traits (see middle::lang_items) and
|
||||
/// detects Copy, Send and Sync.
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub enum TyParamBound {
|
||||
TraitTyParamBound(PolyTraitRef, TraitBoundModifier),
|
||||
RegionTyParamBound(Lifetime),
|
||||
}
|
||||
|
||||
impl TyParamBound {
|
||||
pub fn span(&self) -> Span {
|
||||
match self {
|
||||
&TraitTyParamBound(ref t, ..) => t.span,
|
||||
&RegionTyParamBound(ref l) => l.span,
|
||||
}
|
||||
bug!("GenericArgs::inputs: not a `Fn(T) -> U`");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -441,74 +438,57 @@ pub enum TraitBoundModifier {
|
|||
Maybe,
|
||||
}
|
||||
|
||||
pub type TyParamBounds = HirVec<TyParamBound>;
|
||||
/// The AST represents all type param bounds as types.
|
||||
/// typeck::collect::compute_bounds matches these against
|
||||
/// the "special" built-in traits (see middle::lang_items) and
|
||||
/// detects Copy, Send and Sync.
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub enum GenericBound {
|
||||
Trait(PolyTraitRef, TraitBoundModifier),
|
||||
Outlives(Lifetime),
|
||||
}
|
||||
|
||||
impl GenericBound {
|
||||
pub fn span(&self) -> Span {
|
||||
match self {
|
||||
&GenericBound::Trait(ref t, ..) => t.span,
|
||||
&GenericBound::Outlives(ref l) => l.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type GenericBounds = HirVec<GenericBound>;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub struct TyParam {
|
||||
pub name: Name,
|
||||
pub enum GenericParamKind {
|
||||
/// A lifetime definition, eg `'a: 'b + 'c + 'd`.
|
||||
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,
|
||||
},
|
||||
Type {
|
||||
default: Option<P<Ty>>,
|
||||
synthetic: Option<SyntheticTyParamKind>,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub struct GenericParam {
|
||||
pub id: NodeId,
|
||||
pub bounds: TyParamBounds,
|
||||
pub default: Option<P<Ty>>,
|
||||
pub name: ParamName,
|
||||
pub attrs: HirVec<Attribute>,
|
||||
pub bounds: GenericBounds,
|
||||
pub span: Span,
|
||||
pub pure_wrt_drop: bool,
|
||||
pub synthetic: Option<SyntheticTyParamKind>,
|
||||
pub attrs: HirVec<Attribute>,
|
||||
|
||||
pub kind: GenericParamKind,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub enum GenericParam {
|
||||
Lifetime(LifetimeDef),
|
||||
Type(TyParam),
|
||||
}
|
||||
|
||||
impl GenericParam {
|
||||
pub fn is_lifetime_param(&self) -> bool {
|
||||
match *self {
|
||||
GenericParam::Lifetime(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_type_param(&self) -> bool {
|
||||
match *self {
|
||||
GenericParam::Type(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GenericParamsExt {
|
||||
fn lifetimes<'a>(&'a self) -> iter::FilterMap<
|
||||
slice::Iter<GenericParam>,
|
||||
fn(&GenericParam) -> Option<&LifetimeDef>,
|
||||
>;
|
||||
|
||||
fn ty_params<'a>(&'a self) -> iter::FilterMap<
|
||||
slice::Iter<GenericParam>,
|
||||
fn(&GenericParam) -> Option<&TyParam>,
|
||||
>;
|
||||
}
|
||||
|
||||
impl GenericParamsExt for [GenericParam] {
|
||||
fn lifetimes<'a>(&'a self) -> iter::FilterMap<
|
||||
slice::Iter<GenericParam>,
|
||||
fn(&GenericParam) -> Option<&LifetimeDef>,
|
||||
> {
|
||||
self.iter().filter_map(|param| match *param {
|
||||
GenericParam::Lifetime(ref l) => Some(l),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
fn ty_params<'a>(&'a self) -> iter::FilterMap<
|
||||
slice::Iter<GenericParam>,
|
||||
fn(&GenericParam) -> Option<&TyParam>,
|
||||
> {
|
||||
self.iter().filter_map(|param| match *param {
|
||||
GenericParam::Type(ref t) => Some(t),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
pub struct GenericParamCount {
|
||||
pub lifetimes: usize,
|
||||
pub types: usize,
|
||||
}
|
||||
|
||||
/// Represents lifetimes and type parameters attached to a declaration
|
||||
|
|
@ -532,55 +512,23 @@ impl Generics {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn is_lt_parameterized(&self) -> bool {
|
||||
self.params.iter().any(|param| param.is_lifetime_param())
|
||||
}
|
||||
pub fn own_counts(&self) -> GenericParamCount {
|
||||
// We could cache this as a property of `GenericParamCount`, but
|
||||
// the aim is to refactor this away entirely eventually and the
|
||||
// presence of this method will be a constant reminder.
|
||||
let mut own_counts = GenericParamCount {
|
||||
lifetimes: 0,
|
||||
types: 0,
|
||||
};
|
||||
|
||||
pub fn is_type_parameterized(&self) -> bool {
|
||||
self.params.iter().any(|param| param.is_type_param())
|
||||
}
|
||||
|
||||
pub fn lifetimes<'a>(&'a self) -> impl Iterator<Item = &'a LifetimeDef> {
|
||||
self.params.lifetimes()
|
||||
}
|
||||
|
||||
pub fn ty_params<'a>(&'a self) -> impl Iterator<Item = &'a TyParam> {
|
||||
self.params.ty_params()
|
||||
}
|
||||
}
|
||||
|
||||
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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => own_counts.lifetimes += 1,
|
||||
GenericParamKind::Type { .. } => own_counts.types += 1,
|
||||
};
|
||||
}
|
||||
|
||||
None
|
||||
own_counts
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -640,7 +588,7 @@ pub struct WhereBoundPredicate {
|
|||
/// The type being bounded
|
||||
pub bounded_ty: P<Ty>,
|
||||
/// Trait and lifetime bounds (`Clone+Send+'static`)
|
||||
pub bounds: TyParamBounds,
|
||||
pub bounds: GenericBounds,
|
||||
}
|
||||
|
||||
/// A lifetime predicate, e.g. `'a: 'b+'c`
|
||||
|
|
@ -648,7 +596,7 @@ pub struct WhereBoundPredicate {
|
|||
pub struct WhereRegionPredicate {
|
||||
pub span: Span,
|
||||
pub lifetime: Lifetime,
|
||||
pub bounds: HirVec<Lifetime>,
|
||||
pub bounds: GenericBounds,
|
||||
}
|
||||
|
||||
/// An equality predicate (unsupported), e.g. `T=int`
|
||||
|
|
@ -1607,7 +1555,7 @@ pub enum TraitItemKind {
|
|||
Method(MethodSig, TraitMethod),
|
||||
/// An associated type with (possibly empty) bounds and optional concrete
|
||||
/// type
|
||||
Type(TyParamBounds, Option<P<Ty>>),
|
||||
Type(GenericBounds, Option<P<Ty>>),
|
||||
}
|
||||
|
||||
// The bodies for items are stored "out of line", in a separate
|
||||
|
|
@ -1692,7 +1640,7 @@ pub struct BareFnTy {
|
|||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub struct ExistTy {
|
||||
pub generics: Generics,
|
||||
pub bounds: TyParamBounds,
|
||||
pub bounds: GenericBounds,
|
||||
pub impl_trait_fn: Option<DefId>,
|
||||
}
|
||||
|
||||
|
|
@ -2101,9 +2049,9 @@ pub enum Item_ {
|
|||
/// A union definition, e.g. `union Foo<A, B> {x: A, y: B}`
|
||||
ItemUnion(VariantData, Generics),
|
||||
/// Represents a Trait Declaration
|
||||
ItemTrait(IsAuto, Unsafety, Generics, TyParamBounds, HirVec<TraitItemRef>),
|
||||
ItemTrait(IsAuto, Unsafety, Generics, GenericBounds, HirVec<TraitItemRef>),
|
||||
/// Represents a Trait Alias Declaration
|
||||
ItemTraitAlias(Generics, TyParamBounds),
|
||||
ItemTraitAlias(Generics, GenericBounds),
|
||||
|
||||
/// An implementation, eg `impl<A> Trait for Foo { .. }`
|
||||
ItemImpl(Unsafety,
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@ use syntax::util::parser::{self, AssocOp, Fixity};
|
|||
use syntax_pos::{self, BytePos, FileName};
|
||||
|
||||
use hir;
|
||||
use hir::{PatKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier, RangeEnd};
|
||||
use hir::{PatKind, GenericBound, TraitBoundModifier, RangeEnd};
|
||||
use hir::{GenericParam, GenericParamKind, GenericArg};
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::io::{self, Write, Read};
|
||||
|
|
@ -513,7 +514,7 @@ impl<'a> State<'a> {
|
|||
|
||||
fn print_associated_type(&mut self,
|
||||
name: ast::Name,
|
||||
bounds: Option<&hir::TyParamBounds>,
|
||||
bounds: Option<&hir::GenericBounds>,
|
||||
ty: Option<&hir::Ty>)
|
||||
-> io::Result<()> {
|
||||
self.word_space("type")?;
|
||||
|
|
@ -661,7 +662,7 @@ impl<'a> State<'a> {
|
|||
self.word_space(":")?;
|
||||
let mut real_bounds = Vec::with_capacity(exist.bounds.len());
|
||||
for b in exist.bounds.iter() {
|
||||
if let TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
|
||||
if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
|
||||
self.s.space()?;
|
||||
self.word_space("for ?")?;
|
||||
self.print_trait_ref(&ptr.trait_ref)?;
|
||||
|
|
@ -739,7 +740,7 @@ impl<'a> State<'a> {
|
|||
self.print_generic_params(&generics.params)?;
|
||||
let mut real_bounds = Vec::with_capacity(bounds.len());
|
||||
for b in bounds.iter() {
|
||||
if let TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
|
||||
if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
|
||||
self.s.space()?;
|
||||
self.word_space("for ?")?;
|
||||
self.print_trait_ref(&ptr.trait_ref)?;
|
||||
|
|
@ -765,7 +766,7 @@ impl<'a> State<'a> {
|
|||
let mut real_bounds = Vec::with_capacity(bounds.len());
|
||||
// FIXME(durka) this seems to be some quite outdated syntax
|
||||
for b in bounds.iter() {
|
||||
if let TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
|
||||
if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
|
||||
self.s.space()?;
|
||||
self.word_space("for ?")?;
|
||||
self.print_trait_ref(&ptr.trait_ref)?;
|
||||
|
|
@ -1268,15 +1269,11 @@ impl<'a> State<'a> {
|
|||
self.s.word(".")?;
|
||||
self.print_name(segment.name)?;
|
||||
|
||||
segment.with_parameters(|parameters| {
|
||||
if !parameters.lifetimes.is_empty() ||
|
||||
!parameters.types.is_empty() ||
|
||||
!parameters.bindings.is_empty()
|
||||
{
|
||||
self.print_path_parameters(¶meters, segment.infer_types, true)
|
||||
} else {
|
||||
Ok(())
|
||||
segment.with_generic_args(|generic_args| {
|
||||
if !generic_args.args.is_empty() || !generic_args.bindings.is_empty() {
|
||||
return self.print_generic_args(&generic_args, segment.infer_types, true);
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
self.print_call_post(base_args)
|
||||
}
|
||||
|
|
@ -1641,10 +1638,9 @@ impl<'a> State<'a> {
|
|||
if segment.name != keywords::CrateRoot.name() &&
|
||||
segment.name != keywords::DollarCrate.name() {
|
||||
self.print_name(segment.name)?;
|
||||
segment.with_parameters(|parameters| {
|
||||
self.print_path_parameters(parameters,
|
||||
segment.infer_types,
|
||||
colons_before_params)
|
||||
segment.with_generic_args(|generic_args| {
|
||||
self.print_generic_args(generic_args, segment.infer_types,
|
||||
colons_before_params)
|
||||
})?;
|
||||
}
|
||||
}
|
||||
|
|
@ -1673,10 +1669,10 @@ impl<'a> State<'a> {
|
|||
if segment.name != keywords::CrateRoot.name() &&
|
||||
segment.name != keywords::DollarCrate.name() {
|
||||
self.print_name(segment.name)?;
|
||||
segment.with_parameters(|parameters| {
|
||||
self.print_path_parameters(parameters,
|
||||
segment.infer_types,
|
||||
colons_before_params)
|
||||
segment.with_generic_args(|generic_args| {
|
||||
self.print_generic_args(generic_args,
|
||||
segment.infer_types,
|
||||
colons_before_params)
|
||||
})?;
|
||||
}
|
||||
}
|
||||
|
|
@ -1685,10 +1681,10 @@ impl<'a> State<'a> {
|
|||
self.s.word("::")?;
|
||||
let item_segment = path.segments.last().unwrap();
|
||||
self.print_name(item_segment.name)?;
|
||||
item_segment.with_parameters(|parameters| {
|
||||
self.print_path_parameters(parameters,
|
||||
item_segment.infer_types,
|
||||
colons_before_params)
|
||||
item_segment.with_generic_args(|generic_args| {
|
||||
self.print_generic_args(generic_args,
|
||||
item_segment.infer_types,
|
||||
colons_before_params)
|
||||
})
|
||||
}
|
||||
hir::QPath::TypeRelative(ref qself, ref item_segment) => {
|
||||
|
|
@ -1697,28 +1693,28 @@ impl<'a> State<'a> {
|
|||
self.s.word(">")?;
|
||||
self.s.word("::")?;
|
||||
self.print_name(item_segment.name)?;
|
||||
item_segment.with_parameters(|parameters| {
|
||||
self.print_path_parameters(parameters,
|
||||
item_segment.infer_types,
|
||||
colons_before_params)
|
||||
item_segment.with_generic_args(|generic_args| {
|
||||
self.print_generic_args(generic_args,
|
||||
item_segment.infer_types,
|
||||
colons_before_params)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn print_path_parameters(&mut self,
|
||||
parameters: &hir::PathParameters,
|
||||
fn print_generic_args(&mut self,
|
||||
generic_args: &hir::GenericArgs,
|
||||
infer_types: bool,
|
||||
colons_before_params: bool)
|
||||
-> io::Result<()> {
|
||||
if parameters.parenthesized {
|
||||
if generic_args.parenthesized {
|
||||
self.s.word("(")?;
|
||||
self.commasep(Inconsistent, parameters.inputs(), |s, ty| s.print_type(&ty))?;
|
||||
self.commasep(Inconsistent, generic_args.inputs(), |s, ty| s.print_type(&ty))?;
|
||||
self.s.word(")")?;
|
||||
|
||||
self.space_if_not_bol()?;
|
||||
self.word_space("->")?;
|
||||
self.print_type(¶meters.bindings[0].ty)?;
|
||||
self.print_type(&generic_args.bindings[0].ty)?;
|
||||
} else {
|
||||
let start = if colons_before_params { "::<" } else { "<" };
|
||||
let empty = Cell::new(true);
|
||||
|
|
@ -1731,16 +1727,31 @@ impl<'a> State<'a> {
|
|||
}
|
||||
};
|
||||
|
||||
if !parameters.lifetimes.iter().all(|lt| lt.is_elided()) {
|
||||
for lifetime in ¶meters.lifetimes {
|
||||
start_or_comma(self)?;
|
||||
self.print_lifetime(lifetime)?;
|
||||
let mut types = vec![];
|
||||
let mut elide_lifetimes = true;
|
||||
for arg in &generic_args.args {
|
||||
match arg {
|
||||
GenericArg::Lifetime(lt) => {
|
||||
if !lt.is_elided() {
|
||||
elide_lifetimes = false;
|
||||
}
|
||||
}
|
||||
GenericArg::Type(ty) => {
|
||||
types.push(ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !parameters.types.is_empty() {
|
||||
if !elide_lifetimes {
|
||||
start_or_comma(self)?;
|
||||
self.commasep(Inconsistent, ¶meters.types, |s, ty| s.print_type(&ty))?;
|
||||
self.commasep(Inconsistent, &generic_args.args, |s, generic_arg| {
|
||||
match generic_arg {
|
||||
GenericArg::Lifetime(lt) => s.print_lifetime(lt),
|
||||
GenericArg::Type(ty) => s.print_type(ty),
|
||||
}
|
||||
})?;
|
||||
} else if !types.is_empty() {
|
||||
start_or_comma(self)?;
|
||||
self.commasep(Inconsistent, &types, |s, ty| s.print_type(&ty))?;
|
||||
}
|
||||
|
||||
// FIXME(eddyb) This would leak into error messages, e.g.:
|
||||
|
|
@ -1750,7 +1761,7 @@ impl<'a> State<'a> {
|
|||
self.s.word("..")?;
|
||||
}
|
||||
|
||||
for binding in parameters.bindings.iter() {
|
||||
for binding in generic_args.bindings.iter() {
|
||||
start_or_comma(self)?;
|
||||
self.print_name(binding.name)?;
|
||||
self.s.space()?;
|
||||
|
|
@ -2060,7 +2071,7 @@ impl<'a> State<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn print_bounds(&mut self, prefix: &str, bounds: &[hir::TyParamBound]) -> io::Result<()> {
|
||||
pub fn print_bounds(&mut self, prefix: &str, bounds: &[hir::GenericBound]) -> io::Result<()> {
|
||||
if !bounds.is_empty() {
|
||||
self.s.word(prefix)?;
|
||||
let mut first = true;
|
||||
|
|
@ -2075,13 +2086,13 @@ impl<'a> State<'a> {
|
|||
}
|
||||
|
||||
match bound {
|
||||
TraitTyParamBound(tref, modifier) => {
|
||||
GenericBound::Trait(tref, modifier) => {
|
||||
if modifier == &TraitBoundModifier::Maybe {
|
||||
self.s.word("?")?;
|
||||
}
|
||||
self.print_poly_trait_ref(tref)?;
|
||||
}
|
||||
RegionTyParamBound(lt) => {
|
||||
GenericBound::Outlives(lt) => {
|
||||
self.print_lifetime(lt)?;
|
||||
}
|
||||
}
|
||||
|
|
@ -2090,30 +2101,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(">")?;
|
||||
|
|
@ -2121,19 +2114,41 @@ 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) => {
|
||||
self.s.space()?;
|
||||
self.word_space("=")?;
|
||||
self.print_type(&default)
|
||||
pub fn print_generic_param(&mut self, param: &GenericParam) -> io::Result<()> {
|
||||
self.print_name(param.name.name())?;
|
||||
match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => {
|
||||
let mut sep = ":";
|
||||
for bound in ¶m.bounds {
|
||||
match bound {
|
||||
GenericBound::Outlives(lt) => {
|
||||
self.s.word(sep)?;
|
||||
self.print_lifetime(lt)?;
|
||||
sep = "+";
|
||||
}
|
||||
_ => bug!(),
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
GenericParamKind::Type { ref default, .. } => {
|
||||
self.print_bounds(":", ¶m.bounds)?;
|
||||
match default {
|
||||
Some(default) => {
|
||||
self.s.space()?;
|
||||
self.word_space("=")?;
|
||||
self.print_type(&default)
|
||||
}
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_lifetime(&mut self, lifetime: &hir::Lifetime) -> io::Result<()> {
|
||||
self.print_name(lifetime.name.name())
|
||||
}
|
||||
|
||||
pub fn print_where_clause(&mut self, where_clause: &hir::WhereClause) -> io::Result<()> {
|
||||
if where_clause.predicates.is_empty() {
|
||||
return Ok(());
|
||||
|
|
@ -2165,7 +2180,12 @@ impl<'a> State<'a> {
|
|||
self.s.word(":")?;
|
||||
|
||||
for (i, bound) in bounds.iter().enumerate() {
|
||||
self.print_lifetime(bound)?;
|
||||
match bound {
|
||||
GenericBound::Outlives(lt) => {
|
||||
self.print_lifetime(lt)?;
|
||||
}
|
||||
_ => bug!(),
|
||||
}
|
||||
|
||||
if i != 0 {
|
||||
self.s.word(":")?;
|
||||
|
|
|
|||
|
|
@ -142,12 +142,16 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItemId {
|
|||
}
|
||||
}
|
||||
|
||||
impl_stable_hash_for!(enum hir::ParamName {
|
||||
Plain(name),
|
||||
Fresh(index)
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(enum hir::LifetimeName {
|
||||
Param(param_name),
|
||||
Implicit,
|
||||
Underscore,
|
||||
Fresh(index),
|
||||
Static,
|
||||
Name(name)
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(struct hir::Label {
|
||||
|
|
@ -161,13 +165,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,
|
||||
|
|
@ -177,19 +174,23 @@ impl_stable_hash_for!(struct hir::Path {
|
|||
impl_stable_hash_for!(struct hir::PathSegment {
|
||||
name,
|
||||
infer_types,
|
||||
parameters
|
||||
args
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(struct hir::PathParameters {
|
||||
lifetimes,
|
||||
types,
|
||||
impl_stable_hash_for!(enum hir::GenericArg {
|
||||
Lifetime(lt),
|
||||
Type(ty)
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(struct hir::GenericArgs {
|
||||
args,
|
||||
bindings,
|
||||
parenthesized
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(enum hir::TyParamBound {
|
||||
TraitTyParamBound(poly_trait_ref, trait_bound_modifier),
|
||||
RegionTyParamBound(lifetime)
|
||||
impl_stable_hash_for!(enum hir::GenericBound {
|
||||
Trait(poly_trait_ref, trait_bound_modifier),
|
||||
Outlives(lifetime)
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(enum hir::TraitBoundModifier {
|
||||
|
|
@ -197,21 +198,32 @@ 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,
|
||||
name,
|
||||
span,
|
||||
pure_wrt_drop,
|
||||
synthetic,
|
||||
attrs
|
||||
attrs,
|
||||
bounds,
|
||||
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 { in_band } => {
|
||||
in_band.hash_stable(hcx, hasher);
|
||||
}
|
||||
hir::GenericParamKind::Type { ref default, synthetic } => {
|
||||
default.hash_stable(hcx, hasher);
|
||||
synthetic.hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_stable_hash_for!(struct hir::Generics {
|
||||
params,
|
||||
|
|
|
|||
|
|
@ -1036,15 +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
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let mut has_bounds = false;
|
||||
if let hir_map::NodeGenericParam(ref param) = hir.get(id) {
|
||||
has_bounds = !param.bounds.is_empty();
|
||||
}
|
||||
let sp = hir.span(id);
|
||||
// `sp` only covers `T`, change it so that it covers
|
||||
// `T:` when appropriate
|
||||
let sp = if has_lifetimes {
|
||||
let sp = if has_bounds {
|
||||
sp.to(self.tcx
|
||||
.sess
|
||||
.codemap()
|
||||
|
|
@ -1052,7 +1051,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
} else {
|
||||
sp
|
||||
};
|
||||
(sp, has_lifetimes)
|
||||
(sp, has_bounds)
|
||||
})
|
||||
} else {
|
||||
None
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ use hir::map as hir_map;
|
|||
use hir::def::Def;
|
||||
use hir::def_id::{DefId, CrateNum};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use ty::{self, TyCtxt};
|
||||
use ty::{self, TyCtxt, GenericParamDefKind};
|
||||
use ty::query::Providers;
|
||||
use middle::privacy;
|
||||
use session::config;
|
||||
|
|
@ -37,21 +37,30 @@ use hir::intravisit;
|
|||
|
||||
// Returns true if the given set of generics implies that the item it's
|
||||
// associated with must be inlined.
|
||||
fn generics_require_inlining(generics: &hir::Generics) -> bool {
|
||||
generics.params.iter().any(|param| param.is_type_param())
|
||||
fn generics_require_inlining(generics: &ty::Generics) -> bool {
|
||||
for param in &generics.params {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime { .. } => {}
|
||||
GenericParamDefKind::Type { .. } => return true,
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
// Returns true if the given item must be inlined because it may be
|
||||
// monomorphized or it was marked with `#[inline]`. This will only return
|
||||
// true for functions.
|
||||
fn item_might_be_inlined(item: &hir::Item, attrs: CodegenFnAttrs) -> bool {
|
||||
fn item_might_be_inlined(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
item: &hir::Item,
|
||||
attrs: CodegenFnAttrs) -> bool {
|
||||
if attrs.requests_inline() {
|
||||
return true
|
||||
}
|
||||
|
||||
match item.node {
|
||||
hir::ItemImpl(_, _, _, ref generics, ..) |
|
||||
hir::ItemFn(.., ref generics, _) => {
|
||||
hir::ItemImpl(..) |
|
||||
hir::ItemFn(..) => {
|
||||
let generics = tcx.generics_of(tcx.hir.local_def_id(item.id));
|
||||
generics_require_inlining(generics)
|
||||
}
|
||||
_ => false,
|
||||
|
|
@ -62,14 +71,14 @@ fn method_might_be_inlined<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
impl_item: &hir::ImplItem,
|
||||
impl_src: DefId) -> bool {
|
||||
let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id.owner_def_id());
|
||||
if codegen_fn_attrs.requests_inline() ||
|
||||
generics_require_inlining(&impl_item.generics) {
|
||||
let generics = tcx.generics_of(tcx.hir.local_def_id(impl_item.id));
|
||||
if codegen_fn_attrs.requests_inline() || generics_require_inlining(generics) {
|
||||
return true
|
||||
}
|
||||
if let Some(impl_node_id) = tcx.hir.as_local_node_id(impl_src) {
|
||||
match tcx.hir.find(impl_node_id) {
|
||||
Some(hir_map::NodeItem(item)) =>
|
||||
item_might_be_inlined(&item, codegen_fn_attrs),
|
||||
item_might_be_inlined(tcx, &item, codegen_fn_attrs),
|
||||
Some(..) | None =>
|
||||
span_bug!(impl_item.span, "impl did is not an item")
|
||||
}
|
||||
|
|
@ -163,7 +172,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
|||
Some(hir_map::NodeItem(item)) => {
|
||||
match item.node {
|
||||
hir::ItemFn(..) =>
|
||||
item_might_be_inlined(&item, self.tcx.codegen_fn_attrs(def_id)),
|
||||
item_might_be_inlined(self.tcx, &item, self.tcx.codegen_fn_attrs(def_id)),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
@ -180,7 +189,8 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
|||
hir::ImplItemKind::Const(..) => true,
|
||||
hir::ImplItemKind::Method(..) => {
|
||||
let attrs = self.tcx.codegen_fn_attrs(def_id);
|
||||
if generics_require_inlining(&impl_item.generics) ||
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
if generics_require_inlining(&generics) ||
|
||||
attrs.requests_inline() {
|
||||
true
|
||||
} else {
|
||||
|
|
@ -192,8 +202,9 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
|||
// does too.
|
||||
let impl_node_id = self.tcx.hir.as_local_node_id(impl_did).unwrap();
|
||||
match self.tcx.hir.expect_item(impl_node_id).node {
|
||||
hir::ItemImpl(_, _, _, ref generics, ..) => {
|
||||
generics_require_inlining(generics)
|
||||
hir::ItemImpl(..) => {
|
||||
let generics = self.tcx.generics_of(impl_did);
|
||||
generics_require_inlining(&generics)
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
|
|
@ -251,7 +262,9 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
|||
match item.node {
|
||||
hir::ItemFn(.., body) => {
|
||||
let def_id = self.tcx.hir.local_def_id(item.id);
|
||||
if item_might_be_inlined(&item, self.tcx.codegen_fn_attrs(def_id)) {
|
||||
if item_might_be_inlined(self.tcx,
|
||||
&item,
|
||||
self.tcx.codegen_fn_attrs(def_id)) {
|
||||
self.visit_nested_body(body);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -224,11 +224,9 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
|
|||
let names_map: FxHashSet<String> = generics
|
||||
.params
|
||||
.iter()
|
||||
.filter_map(|param| {
|
||||
match param.kind {
|
||||
ty::GenericParamDefKind::Lifetime => Some(param.name.to_string()),
|
||||
_ => None
|
||||
}
|
||||
.filter_map(|param| match param.kind {
|
||||
ty::GenericParamDefKind::Lifetime => Some(param.name.to_string()),
|
||||
_ => None
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
data @ DefPathData::ValueNs(..) |
|
||||
data @ DefPathData::Module(..) |
|
||||
data @ DefPathData::TypeParam(..) |
|
||||
data @ DefPathData::LifetimeDef(..) |
|
||||
data @ DefPathData::LifetimeParam(..) |
|
||||
data @ DefPathData::EnumVariant(..) |
|
||||
data @ DefPathData::Field(..) |
|
||||
data @ DefPathData::AnonConst |
|
||||
|
|
|
|||
|
|
@ -287,7 +287,7 @@ impl PrintContext {
|
|||
DefPathData::MacroDef(_) |
|
||||
DefPathData::ClosureExpr |
|
||||
DefPathData::TypeParam(_) |
|
||||
DefPathData::LifetimeDef(_) |
|
||||
DefPathData::LifetimeParam(_) |
|
||||
DefPathData::Field(_) |
|
||||
DefPathData::StructCtor |
|
||||
DefPathData::AnonConst |
|
||||
|
|
@ -336,12 +336,10 @@ impl PrintContext {
|
|||
|
||||
if !verbose {
|
||||
let mut type_params =
|
||||
generics.params.iter().rev().filter_map(|param| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Type { has_default, .. } => {
|
||||
Some((param.def_id, has_default))
|
||||
}
|
||||
GenericParamDefKind::Lifetime => None,
|
||||
generics.params.iter().rev().filter_map(|param| match param.kind {
|
||||
GenericParamDefKind::Lifetime => None,
|
||||
GenericParamDefKind::Type { has_default, .. } => {
|
||||
Some((param.def_id, has_default))
|
||||
}
|
||||
}).peekable();
|
||||
let has_default = {
|
||||
|
|
|
|||
|
|
@ -677,14 +677,20 @@ impl<'a> ReplaceBodyWithLoop<'a> {
|
|||
ast::TyKind::Paren(ref subty) => involves_impl_trait(subty),
|
||||
ast::TyKind::Tup(ref tys) => any_involves_impl_trait(tys.iter()),
|
||||
ast::TyKind::Path(_, ref path) => path.segments.iter().any(|seg| {
|
||||
match seg.parameters.as_ref().map(|p| &**p) {
|
||||
match seg.args.as_ref().map(|generic_arg| &**generic_arg) {
|
||||
None => false,
|
||||
Some(&ast::PathParameters::AngleBracketed(ref data)) =>
|
||||
any_involves_impl_trait(data.types.iter()) ||
|
||||
any_involves_impl_trait(data.bindings.iter().map(|b| &b.ty)),
|
||||
Some(&ast::PathParameters::Parenthesized(ref data)) =>
|
||||
Some(&ast::GenericArgs::AngleBracketed(ref data)) => {
|
||||
let types = data.args.iter().filter_map(|arg| match arg {
|
||||
ast::GenericArg::Type(ty) => Some(ty),
|
||||
_ => None,
|
||||
});
|
||||
any_involves_impl_trait(types.into_iter()) ||
|
||||
any_involves_impl_trait(data.bindings.iter().map(|b| &b.ty))
|
||||
},
|
||||
Some(&ast::GenericArgs::Parenthesized(ref data)) => {
|
||||
any_involves_impl_trait(data.inputs.iter()) ||
|
||||
any_involves_impl_trait(data.output.iter()),
|
||||
any_involves_impl_trait(data.output.iter())
|
||||
}
|
||||
}
|
||||
}),
|
||||
_ => false,
|
||||
|
|
|
|||
|
|
@ -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.name(), param.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -253,13 +256,12 @@ 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 { .. } => {
|
||||
let name = param.name.name().as_str();
|
||||
self.check_snake_case(cx, "lifetime", &name, 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};
|
||||
|
|
@ -1196,15 +1196,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
|
|||
}
|
||||
err.emit();
|
||||
}
|
||||
if generics.is_type_parameterized() {
|
||||
let mut err = cx.struct_span_lint(NO_MANGLE_GENERIC_ITEMS,
|
||||
it.span,
|
||||
"functions generic over \
|
||||
types must be mangled");
|
||||
err.span_suggestion_short(no_mangle_attr.span,
|
||||
"remove this attribute",
|
||||
"".to_owned());
|
||||
err.emit();
|
||||
for param in &generics.params {
|
||||
match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => {}
|
||||
GenericParamKind::Type { .. } => {
|
||||
let mut err = cx.struct_span_lint(NO_MANGLE_GENERIC_ITEMS,
|
||||
it.span,
|
||||
"functions generic over \
|
||||
types must be mangled");
|
||||
err.span_suggestion_short(no_mangle_attr.span,
|
||||
"remove this attribute",
|
||||
"".to_owned());
|
||||
err.emit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1531,10 +1537,7 @@ 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<_> = param.bounds.iter().map(|b| b.span()).collect();
|
||||
if !spans.is_empty() {
|
||||
let mut err = cx.struct_span_lint(
|
||||
TYPE_ALIAS_BOUNDS,
|
||||
|
|
|
|||
|
|
@ -810,52 +810,63 @@ impl LintPass for VariantSizeDifferences {
|
|||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
|
||||
fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
|
||||
if let hir::ItemEnum(ref enum_definition, ref gens) = it.node {
|
||||
if gens.params.iter().all(|param| param.is_lifetime_param()) {
|
||||
// sizes only make sense for non-generic types
|
||||
let item_def_id = cx.tcx.hir.local_def_id(it.id);
|
||||
let t = cx.tcx.type_of(item_def_id);
|
||||
let ty = cx.tcx.erase_regions(&t);
|
||||
let layout = cx.layout_of(ty).unwrap_or_else(|e| {
|
||||
bug!("failed to get layout for `{}`: {}", t, e)
|
||||
});
|
||||
if let hir::ItemEnum(ref enum_definition, _) = it.node {
|
||||
let item_def_id = cx.tcx.hir.local_def_id(it.id);
|
||||
let generics = cx.tcx.generics_of(item_def_id);
|
||||
for param in &generics.params {
|
||||
match param.kind {
|
||||
ty::GenericParamDefKind::Lifetime { .. } => {},
|
||||
ty::GenericParamDefKind::Type { .. } => return,
|
||||
}
|
||||
}
|
||||
// Sizes only make sense for non-generic types.
|
||||
let t = cx.tcx.type_of(item_def_id);
|
||||
let ty = cx.tcx.erase_regions(&t);
|
||||
match cx.layout_of(ty) {
|
||||
Ok(layout) => {
|
||||
let variants = &layout.variants;
|
||||
if let layout::Variants::Tagged { ref variants, ref tag, .. } = variants {
|
||||
let discr_size = tag.value.size(cx.tcx).bytes();
|
||||
|
||||
if let layout::Variants::Tagged { ref variants, ref tag, .. } = layout.variants {
|
||||
let discr_size = tag.value.size(cx.tcx).bytes();
|
||||
debug!("enum `{}` is {} bytes large with layout:\n{:#?}",
|
||||
t, layout.size.bytes(), layout);
|
||||
|
||||
debug!("enum `{}` is {} bytes large with layout:\n{:#?}",
|
||||
t, layout.size.bytes(), layout);
|
||||
let (largest, slargest, largest_index) = enum_definition.variants
|
||||
.iter()
|
||||
.zip(variants)
|
||||
.map(|(variant, variant_layout)| {
|
||||
// Subtract the size of the enum discriminant.
|
||||
let bytes = variant_layout.size.bytes().saturating_sub(discr_size);
|
||||
|
||||
let (largest, slargest, largest_index) = enum_definition.variants
|
||||
.iter()
|
||||
.zip(variants)
|
||||
.map(|(variant, variant_layout)| {
|
||||
// Subtract the size of the enum discriminant
|
||||
let bytes = variant_layout.size.bytes()
|
||||
.saturating_sub(discr_size);
|
||||
debug!("- variant `{}` is {} bytes large",
|
||||
variant.node.name,
|
||||
bytes);
|
||||
bytes
|
||||
})
|
||||
.enumerate()
|
||||
.fold((0, 0, 0), |(l, s, li), (idx, size)| if size > l {
|
||||
(size, l, idx)
|
||||
} else if size > s {
|
||||
(l, size, li)
|
||||
} else {
|
||||
(l, s, li)
|
||||
});
|
||||
|
||||
debug!("- variant `{}` is {} bytes large", variant.node.name, bytes);
|
||||
bytes
|
||||
})
|
||||
.enumerate()
|
||||
.fold((0, 0, 0), |(l, s, li), (idx, size)| if size > l {
|
||||
(size, l, idx)
|
||||
} else if size > s {
|
||||
(l, size, li)
|
||||
} else {
|
||||
(l, s, li)
|
||||
});
|
||||
|
||||
// we only warn if the largest variant is at least thrice as large as
|
||||
// the second-largest.
|
||||
if largest > slargest * 3 && slargest > 0 {
|
||||
cx.span_lint(VARIANT_SIZE_DIFFERENCES,
|
||||
enum_definition.variants[largest_index].span,
|
||||
&format!("enum variant is more than three times larger \
|
||||
({} bytes) than the next largest",
|
||||
largest));
|
||||
// We only warn if the largest variant is at least thrice as large as
|
||||
// the second-largest.
|
||||
if largest > slargest * 3 && slargest > 0 {
|
||||
cx.span_lint(VARIANT_SIZE_DIFFERENCES,
|
||||
enum_definition.variants[largest_index].span,
|
||||
&format!("enum variant is more than three times \
|
||||
larger ({} bytes) than the next largest",
|
||||
largest));
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(ty::layout::LayoutError::Unknown(_)) => return,
|
||||
Err(err @ ty::layout::LayoutError::SizeOverflow(_)) => {
|
||||
bug!("failed to get layout for `{}`: {}", t, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1235,10 +1235,14 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
|||
self.encode_optimized_mir(def_id)
|
||||
}
|
||||
hir::ItemConst(..) => self.encode_optimized_mir(def_id),
|
||||
hir::ItemFn(_, _, constness, _, ref generics, _) => {
|
||||
let has_tps = generics.ty_params().next().is_some();
|
||||
hir::ItemFn(_, _, constness, ..) => {
|
||||
let generics = tcx.generics_of(def_id);
|
||||
let has_types = generics.params.iter().any(|param| match param.kind {
|
||||
ty::GenericParamDefKind::Type { .. } => true,
|
||||
_ => false,
|
||||
});
|
||||
let needs_inline =
|
||||
(has_tps || tcx.codegen_fn_attrs(def_id).requests_inline()) &&
|
||||
(has_types || tcx.codegen_fn_attrs(def_id).requests_inline()) &&
|
||||
!self.metadata_output_only();
|
||||
let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
|
||||
if needs_inline || constness == hir::Constness::Const || always_encode_mir {
|
||||
|
|
@ -1645,11 +1649,15 @@ 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));
|
||||
}
|
||||
generics.params.iter().for_each(|param| match param.kind {
|
||||
hir::GenericParamKind::Lifetime { .. } => {}
|
||||
hir::GenericParamKind::Type { ref default, .. } => {
|
||||
let def_id = self.tcx.hir.local_def_id(param.id);
|
||||
let has_default = Untracked(default.is_some());
|
||||
let encode_info = IsolatedEncoder::encode_info_for_ty_param;
|
||||
self.record(def_id, encode_info, (def_id, has_default));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn encode_info_for_ty(&mut self, ty: &hir::Ty) {
|
||||
|
|
|
|||
|
|
@ -295,7 +295,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
|
|||
);
|
||||
let label_msg = match pat.node {
|
||||
PatKind::Path(hir::QPath::Resolved(None, ref path))
|
||||
if path.segments.len() == 1 && path.segments[0].parameters.is_none() => {
|
||||
if path.segments.len() == 1 && path.segments[0].args.is_none() => {
|
||||
format!("interpreted as a {} pattern, not new variable", path.def.kind_name())
|
||||
}
|
||||
_ => format!("pattern `{}` not covered", pattern_string),
|
||||
|
|
|
|||
|
|
@ -1099,14 +1099,12 @@ fn create_mono_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
item: &'tcx hir::Item,
|
||||
output: &mut Vec<MonoItem<'tcx>>) {
|
||||
match item.node {
|
||||
hir::ItemImpl(_,
|
||||
_,
|
||||
_,
|
||||
ref generics,
|
||||
..,
|
||||
ref impl_item_refs) => {
|
||||
if generics.is_type_parameterized() {
|
||||
return
|
||||
hir::ItemImpl(_, _, _, ref generics, .., ref impl_item_refs) => {
|
||||
for param in &generics.params {
|
||||
match param.kind {
|
||||
hir::GenericParamKind::Lifetime { .. } => {}
|
||||
hir::GenericParamKind::Type { .. } => return,
|
||||
}
|
||||
}
|
||||
|
||||
let impl_def_id = tcx.hir.local_def_id(item.id);
|
||||
|
|
|
|||
|
|
@ -99,9 +99,9 @@ impl<'a> AstValidator<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn no_questions_in_bounds(&self, bounds: &TyParamBounds, where_: &str, is_trait: bool) {
|
||||
fn no_questions_in_bounds(&self, bounds: &GenericBounds, where_: &str, is_trait: bool) {
|
||||
for bound in bounds {
|
||||
if let TraitTyParamBound(ref poly, TraitBoundModifier::Maybe) = *bound {
|
||||
if let GenericBound::Trait(ref poly, TraitBoundModifier::Maybe) = *bound {
|
||||
let mut err = self.err_handler().struct_span_err(poly.span,
|
||||
&format!("`?Trait` is not permitted in {}", where_));
|
||||
if is_trait {
|
||||
|
|
@ -139,29 +139,22 @@ impl<'a> AstValidator<'a> {
|
|||
}
|
||||
|
||||
fn check_late_bound_lifetime_defs(&self, params: &Vec<GenericParam>) {
|
||||
// Check: Only lifetime parameters
|
||||
let non_lifetime_param_spans : Vec<_> = params.iter()
|
||||
.filter_map(|param| match *param {
|
||||
GenericParam::Lifetime(_) => None,
|
||||
GenericParam::Type(ref t) => Some(t.ident.span),
|
||||
}).collect();
|
||||
if !non_lifetime_param_spans.is_empty() {
|
||||
self.err_handler().span_err(non_lifetime_param_spans,
|
||||
"only lifetime parameters can be used in this context");
|
||||
}
|
||||
|
||||
// Check: No bounds on lifetime parameters
|
||||
for param in params.iter() {
|
||||
match *param {
|
||||
GenericParam::Lifetime(ref l) => {
|
||||
if !l.bounds.is_empty() {
|
||||
let spans: Vec<_> = l.bounds.iter().map(|b| b.ident.span).collect();
|
||||
self.err_handler().span_err(spans,
|
||||
"lifetime bounds cannot be used in this context");
|
||||
// Check only lifetime parameters are present and that the lifetime
|
||||
// parameters that are present have no bounds.
|
||||
let non_lt_param_spans: Vec<_> = params.iter().filter_map(|param| match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => {
|
||||
if !param.bounds.is_empty() {
|
||||
let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
|
||||
self.err_handler()
|
||||
.span_err(spans, "lifetime bounds cannot be used in this context");
|
||||
}
|
||||
None
|
||||
}
|
||||
GenericParam::Type(_) => {}
|
||||
}
|
||||
_ => Some(param.ident.span),
|
||||
}).collect();
|
||||
if !non_lt_param_spans.is_empty() {
|
||||
self.err_handler().span_err(non_lt_param_spans,
|
||||
"only lifetime parameters can be used in this context");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -197,7 +190,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
TyKind::TraitObject(ref bounds, ..) => {
|
||||
let mut any_lifetime_bounds = false;
|
||||
for bound in bounds {
|
||||
if let RegionTyParamBound(ref lifetime) = *bound {
|
||||
if let GenericBound::Outlives(ref lifetime) = *bound {
|
||||
if any_lifetime_bounds {
|
||||
span_err!(self.session, lifetime.ident.span, E0226,
|
||||
"only a single explicit lifetime bound is permitted");
|
||||
|
|
@ -210,7 +203,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
}
|
||||
TyKind::ImplTrait(ref bounds) => {
|
||||
if !bounds.iter()
|
||||
.any(|b| if let TraitTyParamBound(..) = *b { true } else { false }) {
|
||||
.any(|b| if let GenericBound::Trait(..) = *b { true } else { false }) {
|
||||
self.err_handler().span_err(ty.span, "at least one trait must be specified");
|
||||
}
|
||||
}
|
||||
|
|
@ -230,9 +223,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
// }
|
||||
// foo!(bar::baz<T>);
|
||||
use_tree.prefix.segments.iter().find(|segment| {
|
||||
segment.parameters.is_some()
|
||||
segment.args.is_some()
|
||||
}).map(|segment| {
|
||||
self.err_handler().span_err(segment.parameters.as_ref().unwrap().span(),
|
||||
self.err_handler().span_err(segment.args.as_ref().unwrap().span(),
|
||||
"generic arguments in import path");
|
||||
});
|
||||
|
||||
|
|
@ -300,7 +293,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
ItemKind::Trait(is_auto, _, ref generics, ref bounds, ref trait_items) => {
|
||||
if is_auto == IsAuto::Yes {
|
||||
// Auto traits cannot have generics, super traits nor contain items.
|
||||
if generics.is_parameterized() {
|
||||
if !generics.params.is_empty() {
|
||||
struct_span_err!(self.session, item.span, E0567,
|
||||
"auto traits cannot have generic parameters").emit();
|
||||
}
|
||||
|
|
@ -335,22 +328,19 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
}
|
||||
ItemKind::TraitAlias(Generics { ref params, .. }, ..) => {
|
||||
for param in params {
|
||||
if let GenericParam::Type(TyParam {
|
||||
ident,
|
||||
ref bounds,
|
||||
ref default,
|
||||
..
|
||||
}) = *param
|
||||
{
|
||||
if !bounds.is_empty() {
|
||||
self.err_handler().span_err(ident.span,
|
||||
"type parameters on the left side of a \
|
||||
trait alias cannot be bounded");
|
||||
}
|
||||
if !default.is_none() {
|
||||
self.err_handler().span_err(ident.span,
|
||||
"type parameters on the left side of a \
|
||||
trait alias cannot have defaults");
|
||||
match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => {}
|
||||
GenericParamKind::Type { ref default, .. } => {
|
||||
if !param.bounds.is_empty() {
|
||||
self.err_handler()
|
||||
.span_err(param.ident.span, "type parameters on the left \
|
||||
side of a trait alias cannot be bounded");
|
||||
}
|
||||
if !default.is_none() {
|
||||
self.err_handler()
|
||||
.span_err(param.ident.span, "type parameters on the left \
|
||||
side of a trait alias cannot have defaults");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -398,8 +388,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
fn visit_vis(&mut self, vis: &'a Visibility) {
|
||||
match vis.node {
|
||||
VisibilityKind::Restricted { ref path, .. } => {
|
||||
path.segments.iter().find(|segment| segment.parameters.is_some()).map(|segment| {
|
||||
self.err_handler().span_err(segment.parameters.as_ref().unwrap().span(),
|
||||
path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| {
|
||||
self.err_handler().span_err(segment.args.as_ref().unwrap().span(),
|
||||
"generic arguments in visibility path");
|
||||
});
|
||||
}
|
||||
|
|
@ -409,41 +399,40 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
visit::walk_vis(self, vis)
|
||||
}
|
||||
|
||||
fn visit_generics(&mut self, g: &'a Generics) {
|
||||
fn visit_generics(&mut self, generics: &'a Generics) {
|
||||
let mut seen_non_lifetime_param = false;
|
||||
let mut seen_default = None;
|
||||
for param in &g.params {
|
||||
match (param, seen_non_lifetime_param) {
|
||||
(&GenericParam::Lifetime(ref ld), true) => {
|
||||
for param in &generics.params {
|
||||
match (¶m.kind, seen_non_lifetime_param) {
|
||||
(GenericParamKind::Lifetime { .. }, true) => {
|
||||
self.err_handler()
|
||||
.span_err(ld.lifetime.ident.span, "lifetime parameters must be leading");
|
||||
.span_err(param.ident.span, "lifetime parameters must be leading");
|
||||
},
|
||||
(&GenericParam::Lifetime(_), false) => {}
|
||||
_ => {
|
||||
(GenericParamKind::Lifetime { .. }, false) => {}
|
||||
(GenericParamKind::Type { ref default, .. }, _) => {
|
||||
seen_non_lifetime_param = true;
|
||||
if default.is_some() {
|
||||
seen_default = Some(param.ident.span);
|
||||
} else if let Some(span) = seen_default {
|
||||
self.err_handler()
|
||||
.span_err(span, "type parameters with a default must be trailing");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let GenericParam::Type(ref ty_param @ TyParam { default: Some(_), .. }) = *param {
|
||||
seen_default = Some(ty_param.ident.span);
|
||||
} else if let Some(span) = seen_default {
|
||||
self.err_handler()
|
||||
.span_err(span, "type parameters with a default must be trailing");
|
||||
break
|
||||
}
|
||||
}
|
||||
for predicate in &g.where_clause.predicates {
|
||||
for predicate in &generics.where_clause.predicates {
|
||||
if let WherePredicate::EqPredicate(ref predicate) = *predicate {
|
||||
self.err_handler().span_err(predicate.span, "equality constraints are not yet \
|
||||
supported in where clauses (#20041)");
|
||||
}
|
||||
}
|
||||
visit::walk_generics(self, g)
|
||||
visit::walk_generics(self, generics)
|
||||
}
|
||||
|
||||
fn visit_generic_param(&mut self, param: &'a GenericParam) {
|
||||
if let GenericParam::Lifetime(ref ld) = *param {
|
||||
self.check_lifetime(ld.lifetime.ident);
|
||||
if let GenericParamKind::Lifetime { .. } = param.kind {
|
||||
self.check_lifetime(param.ident);
|
||||
}
|
||||
visit::walk_generic_param(self, param);
|
||||
}
|
||||
|
|
@ -521,23 +510,24 @@ impl<'a> Visitor<'a> for NestedImplTraitVisitor<'a> {
|
|||
visit::walk_ty(self, t);
|
||||
}
|
||||
}
|
||||
fn visit_path_parameters(&mut self, _: Span, path_parameters: &'a PathParameters) {
|
||||
match *path_parameters {
|
||||
PathParameters::AngleBracketed(ref params) => {
|
||||
for type_ in ¶ms.types {
|
||||
self.visit_ty(type_);
|
||||
}
|
||||
for type_binding in ¶ms.bindings {
|
||||
fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) {
|
||||
match *generic_args {
|
||||
GenericArgs::AngleBracketed(ref data) => {
|
||||
data.args.iter().for_each(|arg| match arg {
|
||||
GenericArg::Type(ty) => self.visit_ty(ty),
|
||||
_ => {}
|
||||
});
|
||||
for type_binding in &data.bindings {
|
||||
// Type bindings such as `Item=impl Debug` in `Iterator<Item=Debug>`
|
||||
// are allowed to contain nested `impl Trait`.
|
||||
self.with_impl_trait(None, |this| visit::walk_ty(this, &type_binding.ty));
|
||||
}
|
||||
}
|
||||
PathParameters::Parenthesized(ref params) => {
|
||||
for type_ in ¶ms.inputs {
|
||||
GenericArgs::Parenthesized(ref data) => {
|
||||
for type_ in &data.inputs {
|
||||
self.visit_ty(type_);
|
||||
}
|
||||
if let Some(ref type_) = params.output {
|
||||
if let Some(ref type_) = data.output {
|
||||
// `-> Foo` syntax is essentially an associated type binding,
|
||||
// so it is also allowed to contain nested `impl Trait`.
|
||||
self.with_impl_trait(None, |this| visit::walk_ty(this, type_));
|
||||
|
|
@ -590,7 +580,7 @@ impl<'a> Visitor<'a> for ImplTraitProjectionVisitor<'a> {
|
|||
//
|
||||
// To implement this, we disallow `impl Trait` from `qself`
|
||||
// (for cases like `<impl Trait>::Foo>`)
|
||||
// but we allow `impl Trait` in `PathParameters`
|
||||
// but we allow `impl Trait` in `GenericArgs`
|
||||
// iff there are no more PathSegments.
|
||||
if let Some(ref qself) = *qself {
|
||||
// `impl Trait` in `qself` is always illegal
|
||||
|
|
|
|||
|
|
@ -203,9 +203,9 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
|
|||
hir_visit::walk_impl_item(self, ii)
|
||||
}
|
||||
|
||||
fn visit_ty_param_bound(&mut self, bounds: &'v hir::TyParamBound) {
|
||||
self.record("TyParamBound", Id::None, bounds);
|
||||
hir_visit::walk_ty_param_bound(self, bounds)
|
||||
fn visit_param_bound(&mut self, bounds: &'v hir::GenericBound) {
|
||||
self.record("GenericBound", Id::None, bounds);
|
||||
hir_visit::walk_param_bound(self, bounds)
|
||||
}
|
||||
|
||||
fn visit_struct_field(&mut self, s: &'v hir::StructField) {
|
||||
|
|
@ -322,9 +322,9 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
|
|||
ast_visit::walk_impl_item(self, ii)
|
||||
}
|
||||
|
||||
fn visit_ty_param_bound(&mut self, bounds: &'v ast::TyParamBound) {
|
||||
self.record("TyParamBound", Id::None, bounds);
|
||||
ast_visit::walk_ty_param_bound(self, bounds)
|
||||
fn visit_param_bound(&mut self, bounds: &'v ast::GenericBound) {
|
||||
self.record("GenericBound", Id::None, bounds);
|
||||
ast_visit::walk_param_bound(self, bounds)
|
||||
}
|
||||
|
||||
fn visit_struct_field(&mut self, s: &'v ast::StructField) {
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
@ -1037,9 +1037,8 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
|
|||
self.access_levels.is_public(trait_id)
|
||||
}
|
||||
|
||||
fn check_ty_param_bound(&mut self,
|
||||
ty_param_bound: &hir::TyParamBound) {
|
||||
if let hir::TraitTyParamBound(ref trait_ref, _) = *ty_param_bound {
|
||||
fn check_generic_bound(&mut self, bound: &hir::GenericBound) {
|
||||
if let hir::GenericBound::Trait(ref trait_ref, _) = *bound {
|
||||
if self.path_is_private_type(&trait_ref.trait_ref.path) {
|
||||
self.old_error_set.insert(trait_ref.trait_ref.ref_id);
|
||||
}
|
||||
|
|
@ -1101,7 +1100,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
|
|||
}
|
||||
|
||||
for bound in bounds.iter() {
|
||||
self.check_ty_param_bound(bound)
|
||||
self.check_generic_bound(bound)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1268,16 +1267,19 @@ 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)
|
||||
generics.params.iter().for_each(|param| match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => {}
|
||||
GenericParamKind::Type { .. } => {
|
||||
for bound in ¶m.bounds {
|
||||
self.check_generic_bound(bound);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
for predicate in &generics.where_clause.predicates {
|
||||
match predicate {
|
||||
&hir::WherePredicate::BoundPredicate(ref bound_pred) => {
|
||||
for bound in bound_pred.bounds.iter() {
|
||||
self.check_ty_param_bound(bound)
|
||||
self.check_generic_bound(bound)
|
||||
}
|
||||
}
|
||||
&hir::WherePredicate::RegionPredicate(_) => {}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ use syntax::util::lev_distance::find_best_match_for_name;
|
|||
use syntax::visit::{self, FnKind, Visitor};
|
||||
use syntax::attr;
|
||||
use syntax::ast::{Arm, BindingMode, Block, Crate, Expr, ExprKind};
|
||||
use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, GenericParam, Generics};
|
||||
use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, GenericParamKind, Generics};
|
||||
use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
|
||||
use syntax::ast::{Label, Local, Mutability, Pat, PatKind, Path};
|
||||
use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
|
||||
|
|
@ -797,31 +797,41 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
|
|||
// put all the parameters on the ban list and then remove
|
||||
// them one by one as they are processed and become available.
|
||||
let mut default_ban_rib = Rib::new(ForwardTyParamBanRibKind);
|
||||
let mut found_default = false;
|
||||
default_ban_rib.bindings.extend(generics.params.iter()
|
||||
.filter_map(|p| if let GenericParam::Type(ref tp) = *p { Some(tp) } else { None })
|
||||
.skip_while(|p| p.default.is_none())
|
||||
.map(|p| (Ident::with_empty_ctxt(p.ident.name), Def::Err)));
|
||||
.filter_map(|param| match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => None,
|
||||
GenericParamKind::Type { ref default, .. } => {
|
||||
if found_default || default.is_some() {
|
||||
found_default = true;
|
||||
return Some((Ident::with_empty_ctxt(param.ident.name), Def::Err));
|
||||
}
|
||||
None
|
||||
}
|
||||
}));
|
||||
|
||||
for param in &generics.params {
|
||||
match *param {
|
||||
GenericParam::Lifetime(_) => self.visit_generic_param(param),
|
||||
GenericParam::Type(ref ty_param) => {
|
||||
for bound in &ty_param.bounds {
|
||||
self.visit_ty_param_bound(bound);
|
||||
match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => self.visit_generic_param(param),
|
||||
GenericParamKind::Type { ref default, .. } => {
|
||||
for bound in ¶m.bounds {
|
||||
self.visit_param_bound(bound);
|
||||
}
|
||||
|
||||
if let Some(ref ty) = ty_param.default {
|
||||
if let Some(ref ty) = default {
|
||||
self.ribs[TypeNS].push(default_ban_rib);
|
||||
self.visit_ty(ty);
|
||||
default_ban_rib = self.ribs[TypeNS].pop().unwrap();
|
||||
}
|
||||
|
||||
// Allow all following defaults to refer to this type parameter.
|
||||
default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(ty_param.ident.name));
|
||||
default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(param.ident.name));
|
||||
}
|
||||
}
|
||||
}
|
||||
for p in &generics.where_clause.predicates { self.visit_where_predicate(p); }
|
||||
for p in &generics.where_clause.predicates {
|
||||
self.visit_where_predicate(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2066,7 +2076,7 @@ impl<'a> Resolver<'a> {
|
|||
let local_def_id = this.definitions.local_def_id(item.id);
|
||||
this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| {
|
||||
this.visit_generics(generics);
|
||||
walk_list!(this, visit_ty_param_bound, bounds);
|
||||
walk_list!(this, visit_param_bound, bounds);
|
||||
|
||||
for trait_item in trait_items {
|
||||
this.check_proc_macro_attrs(&trait_item.attrs);
|
||||
|
|
@ -2109,7 +2119,7 @@ impl<'a> Resolver<'a> {
|
|||
let local_def_id = this.definitions.local_def_id(item.id);
|
||||
this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| {
|
||||
this.visit_generics(generics);
|
||||
walk_list!(this, visit_ty_param_bound, bounds);
|
||||
walk_list!(this, visit_param_bound, bounds);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -2197,10 +2207,11 @@ impl<'a> Resolver<'a> {
|
|||
HasTypeParameters(generics, rib_kind) => {
|
||||
let mut function_type_rib = Rib::new(rib_kind);
|
||||
let mut seen_bindings = FxHashMap();
|
||||
for param in &generics.params {
|
||||
if let GenericParam::Type(ref type_parameter) = *param {
|
||||
let ident = type_parameter.ident.modern();
|
||||
debug!("with_type_parameter_rib: {}", type_parameter.id);
|
||||
generics.params.iter().for_each(|param| match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => {}
|
||||
GenericParamKind::Type { .. } => {
|
||||
let ident = param.ident.modern();
|
||||
debug!("with_type_parameter_rib: {}", param.id);
|
||||
|
||||
if seen_bindings.contains_key(&ident) {
|
||||
let span = seen_bindings.get(&ident).unwrap();
|
||||
|
|
@ -2208,17 +2219,16 @@ impl<'a> Resolver<'a> {
|
|||
ident.name,
|
||||
span,
|
||||
);
|
||||
resolve_error(self, type_parameter.ident.span, err);
|
||||
resolve_error(self, param.ident.span, err);
|
||||
}
|
||||
seen_bindings.entry(ident).or_insert(type_parameter.ident.span);
|
||||
seen_bindings.entry(ident).or_insert(param.ident.span);
|
||||
|
||||
// plain insert (no renaming)
|
||||
let def_id = self.definitions.local_def_id(type_parameter.id);
|
||||
let def = Def::TyParam(def_id);
|
||||
// Plain insert (no renaming).
|
||||
let def = Def::TyParam(self.definitions.local_def_id(param.id));
|
||||
function_type_rib.bindings.insert(ident, def);
|
||||
self.record_def(type_parameter.id, PathResolution::new(def));
|
||||
self.record_def(param.id, PathResolution::new(def));
|
||||
}
|
||||
}
|
||||
});
|
||||
self.ribs[TypeNS].push(function_type_rib);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -437,8 +437,8 @@ impl<'a> Resolver<'a> {
|
|||
let def = self.resolve_macro_to_def_inner(scope, path, kind, force);
|
||||
if def != Err(Determinacy::Undetermined) {
|
||||
// Do not report duplicated errors on every undetermined resolution.
|
||||
path.segments.iter().find(|segment| segment.parameters.is_some()).map(|segment| {
|
||||
self.session.span_err(segment.parameters.as_ref().unwrap().span(),
|
||||
path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| {
|
||||
self.session.span_err(segment.args.as_ref().unwrap().span(),
|
||||
"generic arguments in macro path");
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -370,35 +370,38 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
|
|||
id: NodeId,
|
||||
) {
|
||||
for param in &generics.params {
|
||||
if let ast::GenericParam::Type(ref ty_param) = *param {
|
||||
let param_ss = ty_param.ident.span;
|
||||
let name = escape(self.span.snippet(param_ss));
|
||||
// Append $id to name to make sure each one is unique
|
||||
let qualname = format!("{}::{}${}", prefix, name, id);
|
||||
if !self.span.filter_generated(Some(param_ss), full_span) {
|
||||
let id = ::id_from_node_id(ty_param.id, &self.save_ctxt);
|
||||
let span = self.span_from_span(param_ss);
|
||||
match param.kind {
|
||||
ast::GenericParamKind::Lifetime { .. } => {}
|
||||
ast::GenericParamKind::Type { .. } => {
|
||||
let param_ss = param.ident.span;
|
||||
let name = escape(self.span.snippet(param_ss));
|
||||
// Append $id to name to make sure each one is unique.
|
||||
let qualname = format!("{}::{}${}", prefix, name, id);
|
||||
if !self.span.filter_generated(Some(param_ss), full_span) {
|
||||
let id = ::id_from_node_id(param.id, &self.save_ctxt);
|
||||
let span = self.span_from_span(param_ss);
|
||||
|
||||
self.dumper.dump_def(
|
||||
&Access {
|
||||
public: false,
|
||||
reachable: false,
|
||||
},
|
||||
Def {
|
||||
kind: DefKind::Type,
|
||||
id,
|
||||
span,
|
||||
name,
|
||||
qualname,
|
||||
value: String::new(),
|
||||
parent: None,
|
||||
children: vec![],
|
||||
decl_id: None,
|
||||
docs: String::new(),
|
||||
sig: None,
|
||||
attributes: vec![],
|
||||
},
|
||||
);
|
||||
self.dumper.dump_def(
|
||||
&Access {
|
||||
public: false,
|
||||
reachable: false,
|
||||
},
|
||||
Def {
|
||||
kind: DefKind::Type,
|
||||
id,
|
||||
span,
|
||||
name,
|
||||
qualname,
|
||||
value: String::new(),
|
||||
parent: None,
|
||||
children: vec![],
|
||||
decl_id: None,
|
||||
docs: String::new(),
|
||||
sig: None,
|
||||
attributes: vec![],
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -715,7 +718,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
|
|||
&mut self,
|
||||
item: &'l ast::Item,
|
||||
generics: &'l ast::Generics,
|
||||
trait_refs: &'l ast::TyParamBounds,
|
||||
trait_refs: &'l ast::GenericBounds,
|
||||
methods: &'l [ast::TraitItem],
|
||||
) {
|
||||
let name = item.ident.to_string();
|
||||
|
|
@ -758,10 +761,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
|
|||
// super-traits
|
||||
for super_bound in trait_refs.iter() {
|
||||
let trait_ref = match *super_bound {
|
||||
ast::TraitTyParamBound(ref trait_ref, _) => trait_ref,
|
||||
ast::RegionTyParamBound(..) => {
|
||||
continue;
|
||||
}
|
||||
ast::GenericBound::Trait(ref trait_ref, _) => trait_ref,
|
||||
ast::GenericBound::Outlives(..) => continue,
|
||||
};
|
||||
|
||||
let trait_ref = &trait_ref.trait_ref;
|
||||
|
|
@ -818,14 +819,17 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
|
|||
}
|
||||
self.dump_path_ref(id, path);
|
||||
|
||||
// Type parameters
|
||||
// Type arguments
|
||||
for seg in &path.segments {
|
||||
if let Some(ref params) = seg.parameters {
|
||||
match **params {
|
||||
ast::PathParameters::AngleBracketed(ref data) => for t in &data.types {
|
||||
self.visit_ty(t);
|
||||
},
|
||||
ast::PathParameters::Parenthesized(ref data) => {
|
||||
if let Some(ref generic_args) = seg.args {
|
||||
match **generic_args {
|
||||
ast::GenericArgs::AngleBracketed(ref data) => {
|
||||
data.args.iter().for_each(|arg| match arg {
|
||||
ast::GenericArg::Type(ty) => self.visit_ty(ty),
|
||||
_ => {}
|
||||
});
|
||||
}
|
||||
ast::GenericArgs::Parenthesized(ref data) => {
|
||||
for t in &data.inputs {
|
||||
self.visit_ty(t);
|
||||
}
|
||||
|
|
@ -905,11 +909,12 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
|
|||
}
|
||||
|
||||
// Explicit types in the turbo-fish.
|
||||
if let Some(ref params) = seg.parameters {
|
||||
if let ast::PathParameters::AngleBracketed(ref data) = **params {
|
||||
for t in &data.types {
|
||||
self.visit_ty(t);
|
||||
}
|
||||
if let Some(ref generic_args) = seg.args {
|
||||
if let ast::GenericArgs::AngleBracketed(ref data) = **generic_args {
|
||||
data.args.iter().for_each(|arg| match arg {
|
||||
ast::GenericArg::Type(ty) => self.visit_ty(ty),
|
||||
_ => {}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1478,18 +1483,19 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
|
|||
}
|
||||
|
||||
fn visit_generics(&mut self, generics: &'l ast::Generics) {
|
||||
for param in &generics.params {
|
||||
if let ast::GenericParam::Type(ref ty_param) = *param {
|
||||
for bound in ty_param.bounds.iter() {
|
||||
if let ast::TraitTyParamBound(ref trait_ref, _) = *bound {
|
||||
generics.params.iter().for_each(|param| match param.kind {
|
||||
ast::GenericParamKind::Lifetime { .. } => {}
|
||||
ast::GenericParamKind::Type { ref default, .. } => {
|
||||
for bound in ¶m.bounds {
|
||||
if let ast::GenericBound::Trait(ref trait_ref, _) = *bound {
|
||||
self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path)
|
||||
}
|
||||
}
|
||||
if let Some(ref ty) = ty_param.default {
|
||||
if let Some(ref ty) = default {
|
||||
self.visit_ty(&ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, t: &'l ast::Ty) {
|
||||
|
|
|
|||
|
|
@ -692,8 +692,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
|||
if path.segments.len() != 1 {
|
||||
return false;
|
||||
}
|
||||
if let Some(ref params) = path.segments[0].parameters {
|
||||
if let ast::PathParameters::Parenthesized(_) = **params {
|
||||
if let Some(ref generic_args) = path.segments[0].args {
|
||||
if let ast::GenericArgs::Parenthesized(_) = **generic_args {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -934,10 +934,7 @@ fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String {
|
|||
sig.push_str(&generics
|
||||
.params
|
||||
.iter()
|
||||
.map(|param| match *param {
|
||||
ast::GenericParam::Lifetime(ref l) => l.lifetime.ident.name.to_string(),
|
||||
ast::GenericParam::Type(ref t) => t.ident.to_string(),
|
||||
})
|
||||
.map(|param| param.ident.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "));
|
||||
sig.push_str("> ");
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ pub fn assoc_const_signature(
|
|||
pub fn assoc_type_signature(
|
||||
id: NodeId,
|
||||
ident: ast::Ident,
|
||||
bounds: Option<&ast::TyParamBounds>,
|
||||
bounds: Option<&ast::GenericBounds>,
|
||||
default: Option<&ast::Ty>,
|
||||
scx: &SaveContext,
|
||||
) -> Option<Signature> {
|
||||
|
|
@ -223,9 +223,9 @@ impl Sig for ast::Ty {
|
|||
text.push_str("for<");
|
||||
text.push_str(&f.generic_params
|
||||
.iter()
|
||||
.filter_map(|p| match *p {
|
||||
ast::GenericParam::Lifetime(ref l) => {
|
||||
Some(l.lifetime.ident.to_string())
|
||||
.filter_map(|param| match param.kind {
|
||||
ast::GenericParamKind::Lifetime { .. } => {
|
||||
Some(param.ident.to_string())
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
|
|
@ -617,45 +617,34 @@ impl Sig for ast::Generics {
|
|||
|
||||
let mut defs = vec![];
|
||||
for param in &self.params {
|
||||
match *param {
|
||||
ast::GenericParam::Lifetime(ref l) => {
|
||||
let mut l_text = l.lifetime.ident.to_string();
|
||||
defs.push(SigElement {
|
||||
id: id_from_node_id(l.lifetime.id, scx),
|
||||
start: offset + text.len(),
|
||||
end: offset + text.len() + l_text.len(),
|
||||
});
|
||||
|
||||
if !l.bounds.is_empty() {
|
||||
l_text.push_str(": ");
|
||||
let bounds = l.bounds
|
||||
.iter()
|
||||
.map(|l| l.ident.to_string())
|
||||
let mut param_text = param.ident.to_string();
|
||||
defs.push(SigElement {
|
||||
id: id_from_node_id(param.id, scx),
|
||||
start: offset + text.len(),
|
||||
end: offset + text.len() + param_text.len(),
|
||||
});
|
||||
if !param.bounds.is_empty() {
|
||||
param_text.push_str(": ");
|
||||
match param.kind {
|
||||
ast::GenericParamKind::Lifetime { .. } => {
|
||||
let bounds = param.bounds.iter()
|
||||
.map(|bound| match bound {
|
||||
ast::GenericBound::Outlives(lt) => lt.ident.to_string(),
|
||||
_ => panic!(),
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(" + ");
|
||||
l_text.push_str(&bounds);
|
||||
param_text.push_str(&bounds);
|
||||
// FIXME add lifetime bounds refs.
|
||||
}
|
||||
text.push_str(&l_text);
|
||||
text.push(',');
|
||||
}
|
||||
ast::GenericParam::Type(ref t) => {
|
||||
let mut t_text = t.ident.to_string();
|
||||
defs.push(SigElement {
|
||||
id: id_from_node_id(t.id, scx),
|
||||
start: offset + text.len(),
|
||||
end: offset + text.len() + t_text.len(),
|
||||
});
|
||||
|
||||
if !t.bounds.is_empty() {
|
||||
t_text.push_str(": ");
|
||||
t_text.push_str(&pprust::bounds_to_string(&t.bounds));
|
||||
ast::GenericParamKind::Type { .. } => {
|
||||
param_text.push_str(&pprust::bounds_to_string(¶m.bounds));
|
||||
// FIXME descend properly into bounds.
|
||||
}
|
||||
text.push_str(&t_text);
|
||||
text.push(',');
|
||||
}
|
||||
}
|
||||
text.push_str(¶m_text);
|
||||
text.push(',');
|
||||
}
|
||||
|
||||
text.push('>');
|
||||
|
|
@ -852,7 +841,7 @@ fn name_and_generics(
|
|||
fn make_assoc_type_signature(
|
||||
id: NodeId,
|
||||
ident: ast::Ident,
|
||||
bounds: Option<&ast::TyParamBounds>,
|
||||
bounds: Option<&ast::GenericBounds>,
|
||||
default: Option<&ast::Ty>,
|
||||
scx: &SaveContext,
|
||||
) -> Result {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
//! is parameterized by an instance of `AstConv`.
|
||||
|
||||
use rustc_data_structures::accumulate_vec::AccumulateVec;
|
||||
use hir;
|
||||
use hir::{self, GenericArg};
|
||||
use hir::def::Def;
|
||||
use hir::def_id::DefId;
|
||||
use middle::resolve_lifetime as rl;
|
||||
|
|
@ -177,11 +177,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
{
|
||||
|
||||
let (substs, assoc_bindings) =
|
||||
item_segment.with_parameters(|parameters| {
|
||||
item_segment.with_generic_args(|generic_args| {
|
||||
self.create_substs_for_ast_path(
|
||||
span,
|
||||
def_id,
|
||||
parameters,
|
||||
generic_args,
|
||||
item_segment.infer_types,
|
||||
None)
|
||||
});
|
||||
|
|
@ -199,7 +199,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
fn create_substs_for_ast_path(&self,
|
||||
span: Span,
|
||||
def_id: DefId,
|
||||
parameters: &hir::PathParameters,
|
||||
generic_args: &hir::GenericArgs,
|
||||
infer_types: bool,
|
||||
self_ty: Option<Ty<'tcx>>)
|
||||
-> (&'tcx Substs<'tcx>, Vec<ConvertedBinding<'tcx>>)
|
||||
|
|
@ -207,16 +207,26 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
let tcx = self.tcx();
|
||||
|
||||
debug!("create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \
|
||||
parameters={:?})",
|
||||
def_id, self_ty, parameters);
|
||||
generic_args={:?})",
|
||||
def_id, self_ty, generic_args);
|
||||
|
||||
// If the type is parameterized by this region, then replace this
|
||||
// region with the current anon region binding (in other words,
|
||||
// whatever & would get replaced with).
|
||||
let decl_generics = tcx.generics_of(def_id);
|
||||
let ty_provided = parameters.types.len();
|
||||
let lt_provided = parameters.lifetimes.len();
|
||||
|
||||
// FIXME(varkor): Separating out the parameters is messy.
|
||||
let lifetimes: Vec<_> = generic_args.args.iter().filter_map(|arg| match arg {
|
||||
GenericArg::Lifetime(lt) => Some(lt),
|
||||
_ => None,
|
||||
}).collect();
|
||||
let types: Vec<_> = generic_args.args.iter().filter_map(|arg| match arg {
|
||||
GenericArg::Type(ty) => Some(ty),
|
||||
_ => None,
|
||||
}).collect();
|
||||
let lt_provided = lifetimes.len();
|
||||
let ty_provided = types.len();
|
||||
|
||||
let decl_generics = tcx.generics_of(def_id);
|
||||
let mut lt_accepted = 0;
|
||||
let mut ty_params = ParamRange { required: 0, accepted: 0 };
|
||||
for param in &decl_generics.params {
|
||||
|
|
@ -269,8 +279,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
let i = param.index as usize - own_self;
|
||||
if let Some(lifetime) = parameters.lifetimes.get(i) {
|
||||
self.ast_region_to_region(lifetime, Some(param)).into()
|
||||
if let Some(lt) = lifetimes.get(i) {
|
||||
self.ast_region_to_region(lt, Some(param)).into()
|
||||
} else {
|
||||
tcx.types.re_static.into()
|
||||
}
|
||||
|
|
@ -286,7 +296,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
let i = i - (lt_accepted + own_self);
|
||||
if i < ty_provided {
|
||||
// A provided type parameter.
|
||||
self.ast_ty_to_ty(¶meters.types[i]).into()
|
||||
self.ast_ty_to_ty(&types[i]).into()
|
||||
} else if infer_types {
|
||||
// No type parameters were provided, we can infer all.
|
||||
if !default_needs_object_self(param) {
|
||||
|
|
@ -330,7 +340,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
}
|
||||
});
|
||||
|
||||
let assoc_bindings = parameters.bindings.iter().map(|binding| {
|
||||
let assoc_bindings = generic_args.bindings.iter().map(|binding| {
|
||||
ConvertedBinding {
|
||||
item_name: binding.name,
|
||||
ty: self.ast_ty_to_ty(&binding.ty),
|
||||
|
|
@ -355,7 +365,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
self_ty: Ty<'tcx>)
|
||||
-> ty::TraitRef<'tcx>
|
||||
{
|
||||
self.prohibit_type_params(trait_ref.path.segments.split_last().unwrap().1);
|
||||
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
|
||||
|
||||
let trait_def_id = self.trait_def_id(trait_ref);
|
||||
self.ast_path_to_mono_trait_ref(trait_ref.path.span,
|
||||
|
|
@ -389,7 +399,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
|
||||
debug!("ast_path_to_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);
|
||||
|
||||
self.prohibit_type_params(trait_ref.path.segments.split_last().unwrap().1);
|
||||
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
|
||||
|
||||
let (substs, assoc_bindings) =
|
||||
self.create_substs_for_ast_trait_ref(trait_ref.path.span,
|
||||
|
|
@ -451,7 +461,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
let trait_def = self.tcx().trait_def(trait_def_id);
|
||||
|
||||
if !self.tcx().features().unboxed_closures &&
|
||||
trait_segment.with_parameters(|p| p.parenthesized) != trait_def.paren_sugar {
|
||||
trait_segment.with_generic_args(|generic_args| generic_args.parenthesized)
|
||||
!= trait_def.paren_sugar {
|
||||
// For now, require that parenthetical notation be used only with `Fn()` etc.
|
||||
let msg = if trait_def.paren_sugar {
|
||||
"the precise format of `Fn`-family traits' type parameters is subject to change. \
|
||||
|
|
@ -463,10 +474,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
span, GateIssue::Language, msg);
|
||||
}
|
||||
|
||||
trait_segment.with_parameters(|parameters| {
|
||||
trait_segment.with_generic_args(|generic_args| {
|
||||
self.create_substs_for_ast_path(span,
|
||||
trait_def_id,
|
||||
parameters,
|
||||
generic_args,
|
||||
trait_segment.infer_types,
|
||||
Some(self_ty))
|
||||
})
|
||||
|
|
@ -866,7 +877,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
|
||||
debug!("associated_path_def_to_ty: {:?}::{}", ty, assoc_name);
|
||||
|
||||
self.prohibit_type_params(slice::from_ref(item_segment));
|
||||
self.prohibit_generics(slice::from_ref(item_segment));
|
||||
|
||||
// Find the type of the associated item, and the trait where the associated
|
||||
// item is declared.
|
||||
|
|
@ -943,7 +954,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
let tcx = self.tcx();
|
||||
let trait_def_id = tcx.parent_def_id(item_def_id).unwrap();
|
||||
|
||||
self.prohibit_type_params(slice::from_ref(item_segment));
|
||||
self.prohibit_generics(slice::from_ref(item_segment));
|
||||
|
||||
let self_ty = if let Some(ty) = opt_self_ty {
|
||||
ty
|
||||
|
|
@ -968,25 +979,37 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
self.normalize_ty(span, tcx.mk_projection(item_def_id, trait_ref.substs))
|
||||
}
|
||||
|
||||
pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) {
|
||||
pub fn prohibit_generics(&self, segments: &[hir::PathSegment]) {
|
||||
for segment in segments {
|
||||
segment.with_parameters(|parameters| {
|
||||
for typ in ¶meters.types {
|
||||
struct_span_err!(self.tcx().sess, typ.span, E0109,
|
||||
"type parameters are not allowed on this type")
|
||||
.span_label(typ.span, "type parameter not allowed")
|
||||
.emit();
|
||||
break;
|
||||
segment.with_generic_args(|generic_args| {
|
||||
let (mut err_for_lt, mut err_for_ty) = (false, false);
|
||||
for arg in &generic_args.args {
|
||||
let (mut span_err, span, kind) = match arg {
|
||||
hir::GenericArg::Lifetime(lt) => {
|
||||
if err_for_lt { continue }
|
||||
err_for_lt = true;
|
||||
(struct_span_err!(self.tcx().sess, lt.span, E0110,
|
||||
"lifetime parameters are not allowed on \
|
||||
this type"),
|
||||
lt.span,
|
||||
"lifetime")
|
||||
}
|
||||
hir::GenericArg::Type(ty) => {
|
||||
if err_for_ty { continue }
|
||||
err_for_ty = true;
|
||||
(struct_span_err!(self.tcx().sess, ty.span, E0109,
|
||||
"type parameters are not allowed on this type"),
|
||||
ty.span,
|
||||
"type")
|
||||
}
|
||||
};
|
||||
span_err.span_label(span, format!("{} parameter not allowed", kind))
|
||||
.emit();
|
||||
if err_for_lt && err_for_ty {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for lifetime in ¶meters.lifetimes {
|
||||
struct_span_err!(self.tcx().sess, lifetime.span, E0110,
|
||||
"lifetime parameters are not allowed on this type")
|
||||
.span_label(lifetime.span,
|
||||
"lifetime parameter not allowed on this type")
|
||||
.emit();
|
||||
break;
|
||||
}
|
||||
for binding in ¶meters.bindings {
|
||||
for binding in &generic_args.bindings {
|
||||
self.prohibit_projection(binding.span);
|
||||
break;
|
||||
}
|
||||
|
|
@ -1016,21 +1039,21 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) |
|
||||
Def::Union(did) | Def::TyForeign(did) => {
|
||||
assert_eq!(opt_self_ty, None);
|
||||
self.prohibit_type_params(path.segments.split_last().unwrap().1);
|
||||
self.prohibit_generics(path.segments.split_last().unwrap().1);
|
||||
self.ast_path_to_ty(span, did, path.segments.last().unwrap())
|
||||
}
|
||||
Def::Variant(did) if permit_variants => {
|
||||
// Convert "variant type" as if it were a real type.
|
||||
// The resulting `Ty` is type of the variant's enum for now.
|
||||
assert_eq!(opt_self_ty, None);
|
||||
self.prohibit_type_params(path.segments.split_last().unwrap().1);
|
||||
self.prohibit_generics(path.segments.split_last().unwrap().1);
|
||||
self.ast_path_to_ty(span,
|
||||
tcx.parent_def_id(did).unwrap(),
|
||||
path.segments.last().unwrap())
|
||||
}
|
||||
Def::TyParam(did) => {
|
||||
assert_eq!(opt_self_ty, None);
|
||||
self.prohibit_type_params(&path.segments);
|
||||
self.prohibit_generics(&path.segments);
|
||||
|
||||
let node_id = tcx.hir.as_local_node_id(did).unwrap();
|
||||
let item_id = tcx.hir.get_parent_node(node_id);
|
||||
|
|
@ -1043,18 +1066,18 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
// Self in impl (we know the concrete type).
|
||||
|
||||
assert_eq!(opt_self_ty, None);
|
||||
self.prohibit_type_params(&path.segments);
|
||||
self.prohibit_generics(&path.segments);
|
||||
|
||||
tcx.at(span).type_of(def_id)
|
||||
}
|
||||
Def::SelfTy(Some(_), None) => {
|
||||
// Self in trait.
|
||||
assert_eq!(opt_self_ty, None);
|
||||
self.prohibit_type_params(&path.segments);
|
||||
self.prohibit_generics(&path.segments);
|
||||
tcx.mk_self_type()
|
||||
}
|
||||
Def::AssociatedTy(def_id) => {
|
||||
self.prohibit_type_params(&path.segments[..path.segments.len()-2]);
|
||||
self.prohibit_generics(&path.segments[..path.segments.len()-2]);
|
||||
self.qpath_to_ty(span,
|
||||
opt_self_ty,
|
||||
def_id,
|
||||
|
|
@ -1063,7 +1086,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
}
|
||||
Def::PrimTy(prim_ty) => {
|
||||
assert_eq!(opt_self_ty, None);
|
||||
self.prohibit_type_params(&path.segments);
|
||||
self.prohibit_generics(&path.segments);
|
||||
match prim_ty {
|
||||
hir::TyBool => tcx.types.bool,
|
||||
hir::TyChar => tcx.types.char,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -728,11 +728,9 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
let mut error_found = false;
|
||||
let impl_m_generics = tcx.generics_of(impl_m.def_id);
|
||||
let trait_m_generics = tcx.generics_of(trait_m.def_id);
|
||||
let impl_m_type_params = impl_m_generics.params.iter().filter_map(|param| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)),
|
||||
GenericParamDefKind::Lifetime => None,
|
||||
}
|
||||
let impl_m_type_params = impl_m_generics.params.iter().filter_map(|param| match param.kind {
|
||||
GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)),
|
||||
GenericParamDefKind::Lifetime => None,
|
||||
});
|
||||
let trait_m_type_params = trait_m_generics.params.iter().filter_map(|param| {
|
||||
match param.kind {
|
||||
|
|
@ -843,19 +841,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 { .. } => {
|
||||
if param.id == impl_node_id {
|
||||
Some(param)
|
||||
Some(¶m.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()
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ use super::{probe, MethodCallee};
|
|||
|
||||
use astconv::AstConv;
|
||||
use check::{FnCtxt, PlaceOp, callee, Needs};
|
||||
use hir::GenericArg;
|
||||
use hir::def_id::DefId;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::traits;
|
||||
|
|
@ -59,7 +60,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
"confirm(unadjusted_self_ty={:?}, pick={:?}, generic_args={:?})",
|
||||
unadjusted_self_ty,
|
||||
pick,
|
||||
segment.parameters,
|
||||
segment.args,
|
||||
);
|
||||
|
||||
let mut confirm_cx = ConfirmContext::new(self, span, self_expr, call_expr);
|
||||
|
|
@ -316,36 +317,44 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
|||
let method_generics = self.tcx.generics_of(pick.item.def_id);
|
||||
let mut fn_segment = Some((segment, method_generics));
|
||||
let supress_mismatch = self.fcx.check_impl_trait(self.span, fn_segment);
|
||||
self.fcx.check_path_parameter_count(self.span, &mut fn_segment, true, supress_mismatch);
|
||||
self.fcx.check_generic_arg_count(self.span, &mut fn_segment, true, supress_mismatch);
|
||||
|
||||
// Create subst for early-bound lifetime parameters, combining
|
||||
// parameters from the type and those from the method.
|
||||
assert_eq!(method_generics.parent_count, parent_substs.len());
|
||||
let provided = &segment.parameters;
|
||||
let provided = &segment.args;
|
||||
let own_counts = method_generics.own_counts();
|
||||
Substs::for_item(self.tcx, pick.item.def_id, |param, _| {
|
||||
let i = param.index as usize;
|
||||
let mut i = param.index as usize;
|
||||
if i < parent_substs.len() {
|
||||
parent_substs[i]
|
||||
} else {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
if let Some(lifetime) = provided.as_ref().and_then(|p| {
|
||||
p.lifetimes.get(i - parent_substs.len())
|
||||
}) {
|
||||
return AstConv::ast_region_to_region(
|
||||
self.fcx, lifetime, Some(param)).into();
|
||||
let (is_lt, is_ty) = match param.kind {
|
||||
GenericParamDefKind::Lifetime => (true, false),
|
||||
GenericParamDefKind::Type { .. } => (false, true),
|
||||
};
|
||||
provided.as_ref().and_then(|data| {
|
||||
for arg in &data.args {
|
||||
match arg {
|
||||
GenericArg::Lifetime(lt) if is_lt => {
|
||||
if i == parent_substs.len() {
|
||||
return Some(AstConv::ast_region_to_region(
|
||||
self.fcx, lt, Some(param)).into());
|
||||
}
|
||||
i -= 1;
|
||||
}
|
||||
GenericArg::Lifetime(_) => {}
|
||||
GenericArg::Type(ty) if is_ty => {
|
||||
if i == parent_substs.len() + own_counts.lifetimes {
|
||||
return Some(self.to_ty(ty).into());
|
||||
}
|
||||
i -= 1;
|
||||
}
|
||||
GenericArg::Type(_) => {}
|
||||
}
|
||||
}
|
||||
GenericParamDefKind::Type {..} => {
|
||||
if let Some(ast_ty) = provided.as_ref().and_then(|p| {
|
||||
p.types.get(i - parent_substs.len() - own_counts.lifetimes)
|
||||
}) {
|
||||
return self.to_ty(ast_ty).into();
|
||||
}
|
||||
}
|
||||
}
|
||||
self.var_for_def(self.span, param)
|
||||
None
|
||||
}).unwrap_or_else(|| self.var_for_def(self.span, param))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ use self::method::MethodCallee;
|
|||
use self::TupleArgumentsFlag::*;
|
||||
|
||||
use astconv::AstConv;
|
||||
use hir::GenericArg;
|
||||
use hir::def::Def;
|
||||
use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||
use std::slice;
|
||||
|
|
@ -1260,10 +1261,11 @@ pub fn check_item_type<'a,'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Item
|
|||
hir::ItemUnion(..) => {
|
||||
check_union(tcx, it.id, it.span);
|
||||
}
|
||||
hir::ItemTy(_, ref generics) => {
|
||||
hir::ItemTy(..) => {
|
||||
let def_id = tcx.hir.local_def_id(it.id);
|
||||
let pty_ty = tcx.type_of(def_id);
|
||||
check_bounds_are_used(tcx, generics, pty_ty);
|
||||
let generics = tcx.generics_of(def_id);
|
||||
check_bounds_are_used(tcx, &generics, pty_ty);
|
||||
}
|
||||
hir::ItemForeignMod(ref m) => {
|
||||
check_abi(tcx, it.span, m.abi);
|
||||
|
|
@ -4740,8 +4742,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
Def::Fn(def_id) |
|
||||
Def::Const(def_id) |
|
||||
Def::Static(def_id, _) => {
|
||||
fn_segment = Some((segments.last().unwrap(),
|
||||
self.tcx.generics_of(def_id)));
|
||||
fn_segment = Some((segments.last().unwrap(), self.tcx.generics_of(def_id)));
|
||||
}
|
||||
|
||||
// Case 3. Reference to a method or associated const.
|
||||
|
|
@ -4781,7 +4782,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
// errors if type parameters are provided in an inappropriate place.
|
||||
let poly_segments = type_segment.is_some() as usize +
|
||||
fn_segment.is_some() as usize;
|
||||
AstConv::prohibit_type_params(self, &segments[..segments.len() - poly_segments]);
|
||||
AstConv::prohibit_generics(self, &segments[..segments.len() - poly_segments]);
|
||||
|
||||
match def {
|
||||
Def::Local(nid) | Def::Upvar(nid, ..) => {
|
||||
|
|
@ -4800,8 +4801,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
// to add defaults. If the user provided *too many* types, that's
|
||||
// a problem.
|
||||
let supress_mismatch = self.check_impl_trait(span, fn_segment);
|
||||
self.check_path_parameter_count(span, &mut type_segment, false, supress_mismatch);
|
||||
self.check_path_parameter_count(span, &mut fn_segment, false, supress_mismatch);
|
||||
self.check_generic_arg_count(span, &mut type_segment, false, supress_mismatch);
|
||||
self.check_generic_arg_count(span, &mut fn_segment, false, supress_mismatch);
|
||||
|
||||
let (fn_start, has_self) = match (type_segment, fn_segment) {
|
||||
(_, Some((_, generics))) => {
|
||||
|
|
@ -4812,11 +4813,42 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
(None, None) => (0, false)
|
||||
};
|
||||
// FIXME(varkor): Separating out the parameters is messy.
|
||||
let mut lifetimes_type_seg = vec![];
|
||||
let mut types_type_seg = vec![];
|
||||
let mut infer_types_type_seg = true;
|
||||
if let Some((seg, _)) = type_segment {
|
||||
if let Some(ref data) = seg.args {
|
||||
for arg in &data.args {
|
||||
match arg {
|
||||
GenericArg::Lifetime(lt) => lifetimes_type_seg.push(lt),
|
||||
GenericArg::Type(ty) => types_type_seg.push(ty),
|
||||
}
|
||||
}
|
||||
}
|
||||
infer_types_type_seg = seg.infer_types;
|
||||
}
|
||||
|
||||
let mut lifetimes_fn_seg = vec![];
|
||||
let mut types_fn_seg = vec![];
|
||||
let mut infer_types_fn_seg = true;
|
||||
if let Some((seg, _)) = fn_segment {
|
||||
if let Some(ref data) = seg.args {
|
||||
for arg in &data.args {
|
||||
match arg {
|
||||
GenericArg::Lifetime(lt) => lifetimes_fn_seg.push(lt),
|
||||
GenericArg::Type(ty) => types_fn_seg.push(ty),
|
||||
}
|
||||
}
|
||||
}
|
||||
infer_types_fn_seg = seg.infer_types;
|
||||
}
|
||||
|
||||
let substs = Substs::for_item(self.tcx, def.def_id(), |param, substs| {
|
||||
let mut i = param.index as usize;
|
||||
|
||||
let segment = if i < fn_start {
|
||||
if let GenericParamDefKind::Type {..} = param.kind {
|
||||
let (segment, lifetimes, types, infer_types) = if i < fn_start {
|
||||
if let GenericParamDefKind::Type { .. } = param.kind {
|
||||
// Handle Self first, so we can adjust the index to match the AST.
|
||||
if has_self && i == 0 {
|
||||
return opt_self_ty.map(|ty| ty.into()).unwrap_or_else(|| {
|
||||
|
|
@ -4825,29 +4857,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
i -= has_self as usize;
|
||||
type_segment
|
||||
(type_segment, &lifetimes_type_seg, &types_type_seg, infer_types_type_seg)
|
||||
} else {
|
||||
i -= fn_start;
|
||||
fn_segment
|
||||
(fn_segment, &lifetimes_fn_seg, &types_fn_seg, infer_types_fn_seg)
|
||||
};
|
||||
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
let lifetimes = segment.map_or(&[][..], |(s, _)| {
|
||||
s.parameters.as_ref().map_or(&[][..], |p| &p.lifetimes[..])
|
||||
});
|
||||
|
||||
if let Some(lifetime) = lifetimes.get(i) {
|
||||
AstConv::ast_region_to_region(self, lifetime, Some(param)).into()
|
||||
} else {
|
||||
self.re_infer(span, Some(param)).unwrap().into()
|
||||
}
|
||||
}
|
||||
GenericParamDefKind::Type {..} => {
|
||||
let (types, infer_types) = segment.map_or((&[][..], true), |(s, _)| {
|
||||
(s.parameters.as_ref().map_or(&[][..], |p| &p.types[..]), s.infer_types)
|
||||
});
|
||||
|
||||
GenericParamDefKind::Type { .. } => {
|
||||
// Skip over the lifetimes in the same segment.
|
||||
if let Some((_, generics)) = segment {
|
||||
i -= generics.own_counts().lifetimes;
|
||||
|
|
@ -4955,25 +4979,26 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
/// Report errors if the provided parameters are too few or too many.
|
||||
fn check_path_parameter_count(&self,
|
||||
span: Span,
|
||||
segment: &mut Option<(&hir::PathSegment, &ty::Generics)>,
|
||||
is_method_call: bool,
|
||||
supress_mismatch_error: bool) {
|
||||
fn check_generic_arg_count(&self,
|
||||
span: Span,
|
||||
segment: &mut Option<(&hir::PathSegment, &ty::Generics)>,
|
||||
is_method_call: bool,
|
||||
supress_mismatch_error: bool) {
|
||||
let (lifetimes, types, infer_types, bindings) = segment.map_or(
|
||||
(&[][..], &[][..], true, &[][..]),
|
||||
|(s, _)| s.parameters.as_ref().map_or(
|
||||
(&[][..], &[][..], s.infer_types, &[][..]),
|
||||
|p| (&p.lifetimes[..], &p.types[..],
|
||||
s.infer_types, &p.bindings[..])));
|
||||
let infer_lifetimes = lifetimes.len() == 0;
|
||||
|
||||
let count_lifetime_params = |n| {
|
||||
format!("{} lifetime parameter{}", n, if n == 1 { "" } else { "s" })
|
||||
};
|
||||
let count_type_params = |n| {
|
||||
format!("{} type parameter{}", n, if n == 1 { "" } else { "s" })
|
||||
};
|
||||
(vec![], vec![], true, &[][..]),
|
||||
|(s, _)| {
|
||||
s.args.as_ref().map_or(
|
||||
(vec![], vec![], s.infer_types, &[][..]),
|
||||
|data| {
|
||||
let (mut lifetimes, mut types) = (vec![], vec![]);
|
||||
data.args.iter().for_each(|arg| match arg {
|
||||
GenericArg::Lifetime(lt) => lifetimes.push(lt),
|
||||
GenericArg::Type(ty) => types.push(ty),
|
||||
});
|
||||
(lifetimes, types, s.infer_types, &data.bindings[..])
|
||||
}
|
||||
)
|
||||
});
|
||||
|
||||
// Check provided parameters.
|
||||
let ((ty_required, ty_accepted), lt_accepted) =
|
||||
|
|
@ -4987,9 +5012,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
let mut ty_params = ParamRange { required: 0, accepted: 0 };
|
||||
for param in &generics.params {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
lt_accepted += 1;
|
||||
}
|
||||
GenericParamDefKind::Lifetime => lt_accepted += 1,
|
||||
GenericParamDefKind::Type { has_default, .. } => {
|
||||
ty_params.accepted += 1;
|
||||
if !has_default {
|
||||
|
|
@ -5006,36 +5029,37 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
((ty_params.required, ty_params.accepted), lt_accepted)
|
||||
});
|
||||
|
||||
if types.len() > ty_accepted {
|
||||
let span = types[ty_accepted].span;
|
||||
let expected_text = count_type_params(ty_accepted);
|
||||
let actual_text = count_type_params(types.len());
|
||||
struct_span_err!(self.tcx.sess, span, E0087,
|
||||
"too many type parameters provided: \
|
||||
expected at most {}, found {}",
|
||||
expected_text, actual_text)
|
||||
.span_label(span, format!("expected {}", expected_text))
|
||||
.emit();
|
||||
|
||||
let count_type_params = |n| {
|
||||
format!("{} type parameter{}", n, if n == 1 { "" } else { "s" })
|
||||
};
|
||||
let expected_text = count_type_params(ty_accepted);
|
||||
let actual_text = count_type_params(types.len());
|
||||
if let Some((mut err, span)) = if types.len() > ty_accepted {
|
||||
// To prevent derived errors to accumulate due to extra
|
||||
// type parameters, we force instantiate_value_path to
|
||||
// use inference variables instead of the provided types.
|
||||
*segment = None;
|
||||
let span = types[ty_accepted].span;
|
||||
Some((struct_span_err!(self.tcx.sess, span, E0087,
|
||||
"too many type parameters provided: \
|
||||
expected at most {}, found {}",
|
||||
expected_text, actual_text), span))
|
||||
} else if types.len() < ty_required && !infer_types && !supress_mismatch_error {
|
||||
let expected_text = count_type_params(ty_required);
|
||||
let actual_text = count_type_params(types.len());
|
||||
struct_span_err!(self.tcx.sess, span, E0089,
|
||||
"too few type parameters provided: \
|
||||
expected {}, found {}",
|
||||
expected_text, actual_text)
|
||||
.span_label(span, format!("expected {}", expected_text))
|
||||
.emit();
|
||||
Some((struct_span_err!(self.tcx.sess, span, E0089,
|
||||
"too few type parameters provided: \
|
||||
expected {}, found {}",
|
||||
expected_text, actual_text), span))
|
||||
} else {
|
||||
None
|
||||
} {
|
||||
err.span_label(span, format!("expected {}", expected_text)).emit();
|
||||
}
|
||||
|
||||
if !bindings.is_empty() {
|
||||
AstConv::prohibit_projection(self, bindings[0].span);
|
||||
}
|
||||
|
||||
let infer_lifetimes = lifetimes.len() == 0;
|
||||
// Prohibit explicit lifetime arguments if late bound lifetime parameters are present.
|
||||
let has_late_bound_lifetime_defs =
|
||||
segment.map_or(None, |(_, generics)| generics.has_late_bound_regions);
|
||||
|
|
@ -5059,25 +5083,26 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
return;
|
||||
}
|
||||
|
||||
if lifetimes.len() > lt_accepted {
|
||||
let count_lifetime_params = |n| {
|
||||
format!("{} lifetime parameter{}", n, if n == 1 { "" } else { "s" })
|
||||
};
|
||||
let expected_text = count_lifetime_params(lt_accepted);
|
||||
let actual_text = count_lifetime_params(lifetimes.len());
|
||||
if let Some((mut err, span)) = if lifetimes.len() > lt_accepted {
|
||||
let span = lifetimes[lt_accepted].span;
|
||||
let expected_text = count_lifetime_params(lt_accepted);
|
||||
let actual_text = count_lifetime_params(lifetimes.len());
|
||||
struct_span_err!(self.tcx.sess, span, E0088,
|
||||
"too many lifetime parameters provided: \
|
||||
expected at most {}, found {}",
|
||||
expected_text, actual_text)
|
||||
.span_label(span, format!("expected {}", expected_text))
|
||||
.emit();
|
||||
Some((struct_span_err!(self.tcx.sess, span, E0088,
|
||||
"too many lifetime parameters provided: \
|
||||
expected at most {}, found {}",
|
||||
expected_text, actual_text), span))
|
||||
} else if lifetimes.len() < lt_accepted && !infer_lifetimes {
|
||||
let expected_text = count_lifetime_params(lt_accepted);
|
||||
let actual_text = count_lifetime_params(lifetimes.len());
|
||||
struct_span_err!(self.tcx.sess, span, E0090,
|
||||
"too few lifetime parameters provided: \
|
||||
expected {}, found {}",
|
||||
expected_text, actual_text)
|
||||
.span_label(span, format!("expected {}", expected_text))
|
||||
.emit();
|
||||
Some((struct_span_err!(self.tcx.sess, span, E0090,
|
||||
"too few lifetime parameters provided: \
|
||||
expected {}, found {}",
|
||||
expected_text, actual_text), span))
|
||||
} else {
|
||||
None
|
||||
} {
|
||||
err.span_label(span, format!("expected {}", expected_text)).emit();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5088,13 +5113,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
-> bool {
|
||||
let segment = segment.map(|(path_segment, generics)| {
|
||||
let explicit = !path_segment.infer_types;
|
||||
let impl_trait = generics.params.iter().any(|param| {
|
||||
match param.kind {
|
||||
ty::GenericParamDefKind::Type {
|
||||
synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), ..
|
||||
} => true,
|
||||
_ => false,
|
||||
}
|
||||
let impl_trait = generics.params.iter().any(|param| match param.kind {
|
||||
ty::GenericParamDefKind::Type {
|
||||
synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), ..
|
||||
} => true,
|
||||
_ => false,
|
||||
});
|
||||
|
||||
if explicit && impl_trait {
|
||||
|
|
@ -5155,34 +5178,39 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
generics: &hir::Generics,
|
||||
generics: &ty::Generics,
|
||||
ty: Ty<'tcx>) {
|
||||
debug!("check_bounds_are_used(n_tps={}, ty={:?})",
|
||||
generics.ty_params().count(), ty);
|
||||
let own_counts = generics.own_counts();
|
||||
debug!("check_bounds_are_used(n_tps={}, ty={:?})", own_counts.types, ty);
|
||||
|
||||
// make a vector of booleans initially false, set to true when used
|
||||
if generics.ty_params().next().is_none() { return; }
|
||||
let mut tps_used = vec![false; generics.ty_params().count()];
|
||||
|
||||
let lifetime_count = generics.lifetimes().count();
|
||||
if own_counts.types == 0 {
|
||||
return;
|
||||
}
|
||||
// Make a vector of booleans initially false, set to true when used.
|
||||
let mut types_used = vec![false; own_counts.types];
|
||||
|
||||
for leaf_ty in ty.walk() {
|
||||
if let ty::TyParam(ty::ParamTy {idx, ..}) = leaf_ty.sty {
|
||||
if let ty::TyParam(ty::ParamTy { idx, .. }) = leaf_ty.sty {
|
||||
debug!("Found use of ty param num {}", idx);
|
||||
tps_used[idx as usize - lifetime_count] = true;
|
||||
types_used[idx as usize - own_counts.lifetimes] = true;
|
||||
} else if let ty::TyError = leaf_ty.sty {
|
||||
// If there already another error, do not emit an error for not using a type Parameter
|
||||
// If there is already another error, do not emit
|
||||
// an error for not using a type Parameter.
|
||||
assert!(tcx.sess.err_count() > 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (&used, param) in tps_used.iter().zip(generics.ty_params()) {
|
||||
let types = generics.params.iter().filter(|param| match param.kind {
|
||||
ty::GenericParamDefKind::Type { .. } => true,
|
||||
_ => false,
|
||||
});
|
||||
for (&used, param) in types_used.iter().zip(types) {
|
||||
if !used {
|
||||
struct_span_err!(tcx.sess, param.span, E0091,
|
||||
"type parameter `{}` is unused",
|
||||
param.name)
|
||||
.span_label(param.span, "unused type parameter")
|
||||
let id = tcx.hir.as_local_node_id(param.def_id).unwrap();
|
||||
let span = tcx.hir.span(id);
|
||||
struct_span_err!(tcx.sess, span, E0091, "type parameter `{}` is unused", param.name)
|
||||
.span_label(span, "unused type parameter")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -602,8 +602,8 @@ fn check_method_receiver<'fcx, 'gcx, 'tcx>(fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
|
|||
}
|
||||
|
||||
fn check_variances_for_type_defn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
item: &hir::Item,
|
||||
ast_generics: &hir::Generics)
|
||||
item: &hir::Item,
|
||||
hir_generics: &hir::Generics)
|
||||
{
|
||||
let item_def_id = tcx.hir.local_def_id(item.id);
|
||||
let ty = tcx.type_of(item_def_id);
|
||||
|
|
@ -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 = &hir_generics.params[index];
|
||||
report_bivariance(tcx, param.span, param.name.name());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -663,17 +660,12 @@ fn report_bivariance<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
fn reject_shadowing_parameters(tcx: TyCtxt, def_id: DefId) {
|
||||
let generics = tcx.generics_of(def_id);
|
||||
let parent = tcx.generics_of(generics.parent.unwrap());
|
||||
let impl_params: FxHashMap<_, _> =
|
||||
parent.params.iter()
|
||||
.flat_map(|param| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => None,
|
||||
GenericParamDefKind::Type {..} => Some((param.name, param.def_id)),
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let impl_params: FxHashMap<_, _> = parent.params.iter().flat_map(|param| match param.kind {
|
||||
GenericParamDefKind::Lifetime => None,
|
||||
GenericParamDefKind::Type {..} => Some((param.name, param.def_id)),
|
||||
}).collect();
|
||||
|
||||
for method_param in generics.params.iter() {
|
||||
for method_param in &generics.params {
|
||||
match method_param.kind {
|
||||
// Shadowing is checked in resolve_lifetime.
|
||||
GenericParamDefKind::Lifetime => continue,
|
||||
|
|
|
|||
|
|
@ -35,7 +35,9 @@ 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(|generics| {
|
||||
generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle")
|
||||
});
|
||||
match (trait_def.unsafety, unsafe_attr, unsafety, polarity) {
|
||||
(Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => {
|
||||
span_err!(self.tcx.sess,
|
||||
|
|
@ -53,13 +55,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,10 +114,14 @@ 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() {
|
||||
let def_id = self.tcx.hir.local_def_id(param.id);
|
||||
self.tcx.type_of(def_id);
|
||||
for param in &generics.params {
|
||||
match param.kind {
|
||||
hir::GenericParamKind::Lifetime { .. } => {}
|
||||
hir::GenericParamKind::Type { default: Some(_), .. } => {
|
||||
let def_id = self.tcx.hir.local_def_id(param.id);
|
||||
self.tcx.type_of(def_id);
|
||||
}
|
||||
hir::GenericParamKind::Type { .. } => {}
|
||||
}
|
||||
}
|
||||
intravisit::walk_generics(self, generics);
|
||||
|
|
@ -308,9 +313,12 @@ 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 { .. } if param.id == param_id => Some(¶m.bounds),
|
||||
_ => None
|
||||
})
|
||||
.flat_map(|bounds| bounds.iter())
|
||||
.flat_map(|b| predicates_from_bound(self, ty, b));
|
||||
|
||||
let from_where_clauses =
|
||||
|
|
@ -739,10 +747,15 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
outer_index: ty::INNERMOST,
|
||||
has_late_bound_regions: None,
|
||||
};
|
||||
for lifetime in generics.lifetimes() {
|
||||
let hir_id = tcx.hir.node_to_hir_id(lifetime.lifetime.id);
|
||||
if tcx.is_late_bound(hir_id) {
|
||||
return Some(lifetime.lifetime.span);
|
||||
for param in &generics.params {
|
||||
match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => {
|
||||
let hir_id = tcx.hir.node_to_hir_id(param.id);
|
||||
if tcx.is_late_bound(hir_id) {
|
||||
return Some(param.span);
|
||||
}
|
||||
}
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
visitor.visit_fn_decl(decl);
|
||||
|
|
@ -883,12 +896,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.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 +911,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");
|
||||
}
|
||||
|
||||
if !allow_defaults && p.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."));
|
||||
let mut i = 0;
|
||||
params.extend(ast_generics.params.iter().filter_map(|param| match param.kind {
|
||||
GenericParamKind::Type { ref default, synthetic, .. } => {
|
||||
if param.name.name() == keywords::SelfType.name() {
|
||||
span_bug!(param.span, "`Self` should not be the name of a regular parameter");
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
kind: ty::GenericParamDefKind::Type {
|
||||
has_default: p.default.is_some(),
|
||||
object_lifetime_default:
|
||||
object_lifetime_defaults.as_ref().map_or(rl::Set1::Empty, |o| o[i]),
|
||||
synthetic: p.synthetic,
|
||||
},
|
||||
if !allow_defaults && default.is_some() {
|
||||
if !tcx.features().default_type_parameter_fallback {
|
||||
tcx.lint_node(
|
||||
lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
|
||||
param.id,
|
||||
param.span,
|
||||
&format!("defaults for type parameters are only allowed in \
|
||||
`struct`, `enum`, `type`, or `trait` definitions."));
|
||||
}
|
||||
}
|
||||
|
||||
let ty_param = ty::GenericParamDef {
|
||||
index: type_start + i as u32,
|
||||
name: param.name.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: default.is_some(),
|
||||
object_lifetime_default:
|
||||
object_lifetime_defaults.as_ref().map_or(rl::Set1::Empty, |o| o[i]),
|
||||
synthetic,
|
||||
},
|
||||
};
|
||||
i += 1;
|
||||
Some(ty_param)
|
||||
}
|
||||
_ => None,
|
||||
}));
|
||||
|
||||
// provide junk type parameter defs - the only place that
|
||||
|
|
@ -1119,8 +1138,13 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
}
|
||||
},
|
||||
|
||||
NodeTyParam(&hir::TyParam { default: Some(ref ty), .. }) => {
|
||||
icx.to_ty(ty)
|
||||
NodeGenericParam(param) => {
|
||||
match param.kind {
|
||||
hir::GenericParamKind::Type { default: Some(ref ty), .. } => {
|
||||
icx.to_ty(ty)
|
||||
}
|
||||
_ => bug!("unexpected non-type NodeGenericParam"),
|
||||
}
|
||||
}
|
||||
|
||||
x => {
|
||||
|
|
@ -1225,7 +1249,7 @@ fn impl_polarity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
|
||||
// Is it marked with ?Sized
|
||||
fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
|
||||
ast_bounds: &[hir::TyParamBound],
|
||||
ast_bounds: &[hir::GenericBound],
|
||||
span: Span) -> bool
|
||||
{
|
||||
let tcx = astconv.tcx();
|
||||
|
|
@ -1233,7 +1257,7 @@ fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
|
|||
// Try to find an unbound in bounds.
|
||||
let mut unbound = None;
|
||||
for ab in ast_bounds {
|
||||
if let &hir::TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = ab {
|
||||
if let &hir::GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = ab {
|
||||
if unbound.is_none() {
|
||||
unbound = Some(ptr.trait_ref.clone());
|
||||
} else {
|
||||
|
|
@ -1274,15 +1298,16 @@ 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,
|
||||
})
|
||||
}
|
||||
|
||||
fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
|
@ -1410,31 +1435,42 @@ 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.name().as_interned_str(),
|
||||
}));
|
||||
index += 1;
|
||||
|
||||
for bound in ¶m.bounds {
|
||||
let bound_region = AstConv::ast_region_to_region(&icx, bound, None);
|
||||
let outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound_region));
|
||||
predicates.push(outlives.to_predicate());
|
||||
match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => {
|
||||
param.bounds.iter().for_each(|bound| match bound {
|
||||
hir::GenericBound::Outlives(lt) => {
|
||||
let bound = AstConv::ast_region_to_region(&icx, <, None);
|
||||
let outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound));
|
||||
predicates.push(outlives.to_predicate());
|
||||
}
|
||||
_ => bug!(),
|
||||
});
|
||||
},
|
||||
_ => 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);
|
||||
index += 1;
|
||||
for param in &ast_generics.params {
|
||||
match param.kind {
|
||||
GenericParamKind::Type { .. } => {
|
||||
let name = param.name.name().as_interned_str();
|
||||
let param_ty = ty::ParamTy::new(index, name).to_ty(tcx);
|
||||
index += 1;
|
||||
|
||||
let bounds = compute_bounds(&icx,
|
||||
param_ty,
|
||||
¶m.bounds,
|
||||
SizedByDefault::Yes,
|
||||
param.span);
|
||||
predicates.extend(bounds.predicates(tcx, param_ty));
|
||||
let sized = SizedByDefault::Yes;
|
||||
let bounds = compute_bounds(&icx, param_ty, ¶m.bounds, sized, param.span);
|
||||
predicates.extend(bounds.predicates(tcx, param_ty));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// Add in the bounds that appear in the where-clause
|
||||
|
|
@ -1446,7 +1482,7 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
|
||||
for bound in bound_pred.bounds.iter() {
|
||||
match bound {
|
||||
&hir::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => {
|
||||
&hir::GenericBound::Trait(ref poly_trait_ref, _) => {
|
||||
let mut projections = Vec::new();
|
||||
|
||||
let trait_ref =
|
||||
|
|
@ -1462,7 +1498,7 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
}
|
||||
}
|
||||
|
||||
&hir::TyParamBound::RegionTyParamBound(ref lifetime) => {
|
||||
&hir::GenericBound::Outlives(ref lifetime) => {
|
||||
let region = AstConv::ast_region_to_region(&icx,
|
||||
lifetime,
|
||||
None);
|
||||
|
|
@ -1476,7 +1512,12 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
&hir::WherePredicate::RegionPredicate(ref region_pred) => {
|
||||
let r1 = AstConv::ast_region_to_region(&icx, ®ion_pred.lifetime, None);
|
||||
for bound in ®ion_pred.bounds {
|
||||
let r2 = AstConv::ast_region_to_region(&icx, bound, None);
|
||||
let r2 = match bound {
|
||||
hir::GenericBound::Outlives(lt) => {
|
||||
AstConv::ast_region_to_region(&icx, lt, None)
|
||||
}
|
||||
_ => bug!(),
|
||||
};
|
||||
let pred = ty::Binder::bind(ty::OutlivesPredicate(r1, r2));
|
||||
predicates.push(ty::Predicate::RegionOutlives(pred))
|
||||
}
|
||||
|
|
@ -1541,7 +1582,7 @@ pub enum SizedByDefault { Yes, No, }
|
|||
/// built-in trait (formerly known as kind): Send.
|
||||
pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
|
||||
param_ty: Ty<'tcx>,
|
||||
ast_bounds: &[hir::TyParamBound],
|
||||
ast_bounds: &[hir::GenericBound],
|
||||
sized_by_default: SizedByDefault,
|
||||
span: Span)
|
||||
-> Bounds<'tcx>
|
||||
|
|
@ -1550,22 +1591,16 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
|
|||
let mut trait_bounds = vec![];
|
||||
for ast_bound in ast_bounds {
|
||||
match *ast_bound {
|
||||
hir::TraitTyParamBound(ref b, hir::TraitBoundModifier::None) => {
|
||||
trait_bounds.push(b);
|
||||
}
|
||||
hir::TraitTyParamBound(_, hir::TraitBoundModifier::Maybe) => {}
|
||||
hir::RegionTyParamBound(ref l) => {
|
||||
region_bounds.push(l);
|
||||
}
|
||||
hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => trait_bounds.push(b),
|
||||
hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {}
|
||||
hir::GenericBound::Outlives(ref l) => region_bounds.push(l),
|
||||
}
|
||||
}
|
||||
|
||||
let mut projection_bounds = vec![];
|
||||
|
||||
let mut trait_bounds: Vec<_> = trait_bounds.iter().map(|&bound| {
|
||||
astconv.instantiate_poly_trait_ref(bound,
|
||||
param_ty,
|
||||
&mut projection_bounds)
|
||||
astconv.instantiate_poly_trait_ref(bound, param_ty, &mut projection_bounds)
|
||||
}).collect();
|
||||
|
||||
let region_bounds = region_bounds.into_iter().map(|r| {
|
||||
|
|
@ -1588,18 +1623,18 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
|
|||
}
|
||||
}
|
||||
|
||||
/// Converts a specific TyParamBound from the AST into a set of
|
||||
/// Converts a specific GenericBound from the AST into a set of
|
||||
/// predicates that apply to the self-type. A vector is returned
|
||||
/// because this can be anywhere from 0 predicates (`T:?Sized` adds no
|
||||
/// predicates) to 1 (`T:Foo`) to many (`T:Bar<X=i32>` adds `T:Bar`
|
||||
/// and `<T as Bar>::X == i32`).
|
||||
fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
|
||||
param_ty: Ty<'tcx>,
|
||||
bound: &hir::TyParamBound)
|
||||
bound: &hir::GenericBound)
|
||||
-> Vec<ty::Predicate<'tcx>>
|
||||
{
|
||||
match *bound {
|
||||
hir::TraitTyParamBound(ref tr, hir::TraitBoundModifier::None) => {
|
||||
hir::GenericBound::Trait(ref tr, hir::TraitBoundModifier::None) => {
|
||||
let mut projections = Vec::new();
|
||||
let pred = astconv.instantiate_poly_trait_ref(tr,
|
||||
param_ty,
|
||||
|
|
@ -1609,14 +1644,12 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
|
|||
.chain(Some(pred.to_predicate()))
|
||||
.collect()
|
||||
}
|
||||
hir::RegionTyParamBound(ref lifetime) => {
|
||||
hir::GenericBound::Outlives(ref lifetime) => {
|
||||
let region = astconv.ast_region_to_region(lifetime, None);
|
||||
let pred = ty::Binder::bind(ty::OutlivesPredicate(param_ty, region));
|
||||
vec![ty::Predicate::TypeOutlives(pred)]
|
||||
}
|
||||
hir::TraitTyParamBound(_, hir::TraitBoundModifier::Maybe) => {
|
||||
Vec::new()
|
||||
}
|
||||
hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => vec![],
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1501,12 +1501,12 @@ struct Foo {
|
|||
"##,
|
||||
|
||||
E0131: r##"
|
||||
It is not possible to define `main` with type parameters, or even with function
|
||||
parameters. When `main` is present, it must take no arguments and return `()`.
|
||||
It is not possible to define `main` with generic parameters.
|
||||
When `main` is present, it must take no arguments and return `()`.
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0131
|
||||
fn main<T>() { // error: main function is not allowed to have type parameters
|
||||
fn main<T>() { // error: main function is not allowed to have generic parameters
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
@ -190,16 +191,9 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
hir::ItemFn(.., ref generics, _) => {
|
||||
let mut error = false;
|
||||
if !generics.params.is_empty() {
|
||||
let param_type = if generics.is_lt_parameterized() {
|
||||
"lifetime"
|
||||
} else {
|
||||
"type"
|
||||
};
|
||||
let msg =
|
||||
format!("`main` function is not allowed to have {} parameters",
|
||||
param_type);
|
||||
let label =
|
||||
format!("`main` cannot have {} parameters", param_type);
|
||||
let msg = format!("`main` function is not allowed to have generic \
|
||||
parameters");
|
||||
let label = format!("`main` cannot have generic parameters");
|
||||
struct_span_err!(tcx.sess, generics.span, E0131, "{}", msg)
|
||||
.span_label(generics.span, label)
|
||||
.emit();
|
||||
|
|
|
|||
|
|
@ -244,34 +244,32 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
|||
None
|
||||
}
|
||||
|
||||
fn generics_to_path_params(&self, generics: ty::Generics) -> hir::PathParameters {
|
||||
let mut lifetimes = vec![];
|
||||
let mut types = vec![];
|
||||
fn generics_to_path_params(&self, generics: ty::Generics) -> hir::GenericArgs {
|
||||
let mut args = vec![];
|
||||
|
||||
for param in generics.params.iter() {
|
||||
match param.kind {
|
||||
ty::GenericParamDefKind::Lifetime => {
|
||||
let name = if param.name == "" {
|
||||
hir::LifetimeName::Static
|
||||
hir::ParamName::Plain(keywords::StaticLifetime.name())
|
||||
} else {
|
||||
hir::LifetimeName::Name(param.name.as_symbol())
|
||||
hir::ParamName::Plain(param.name.as_symbol())
|
||||
};
|
||||
|
||||
lifetimes.push(hir::Lifetime {
|
||||
args.push(hir::GenericArg::Lifetime(hir::Lifetime {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: DUMMY_SP,
|
||||
name,
|
||||
});
|
||||
name: hir::LifetimeName::Param(name),
|
||||
}));
|
||||
}
|
||||
ty::GenericParamDefKind::Type {..} => {
|
||||
types.push(P(self.ty_param_to_ty(param.clone())));
|
||||
args.push(hir::GenericArg::Type(P(self.ty_param_to_ty(param.clone()))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hir::PathParameters {
|
||||
lifetimes: HirVec::from_vec(lifetimes),
|
||||
types: HirVec::from_vec(types),
|
||||
hir::GenericArgs {
|
||||
args: HirVec::from_vec(args),
|
||||
bindings: HirVec::new(),
|
||||
parenthesized: false,
|
||||
}
|
||||
|
|
@ -488,11 +486,8 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
|||
.iter()
|
||||
.flat_map(|(name, lifetime)| {
|
||||
let empty = Vec::new();
|
||||
let bounds: FxHashSet<Lifetime> = finished
|
||||
.get(name)
|
||||
.unwrap_or(&empty)
|
||||
.iter()
|
||||
.map(|region| self.get_lifetime(region, names_map))
|
||||
let bounds: FxHashSet<GenericBound> = finished.get(name).unwrap_or(&empty).iter()
|
||||
.map(|region| GenericBound::Outlives(self.get_lifetime(region, names_map)))
|
||||
.collect();
|
||||
|
||||
if bounds.is_empty() {
|
||||
|
|
@ -523,7 +518,10 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
|||
// We only care about late bound regions, as we need to add them
|
||||
// to the 'for<>' section
|
||||
&ty::ReLateBound(_, ty::BoundRegion::BrNamed(_, name)) => {
|
||||
Some(GenericParamDef::Lifetime(Lifetime(name.to_string())))
|
||||
Some(GenericParamDef {
|
||||
name: name.to_string(),
|
||||
kind: GenericParamDefKind::Lifetime,
|
||||
})
|
||||
}
|
||||
&ty::ReVar(_) | &ty::ReEarlyBound(_) => None,
|
||||
_ => panic!("Unexpected region type {:?}", r),
|
||||
|
|
@ -535,9 +533,9 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
|||
|
||||
fn make_final_bounds<'b, 'c, 'cx>(
|
||||
&self,
|
||||
ty_to_bounds: FxHashMap<Type, FxHashSet<TyParamBound>>,
|
||||
ty_to_bounds: FxHashMap<Type, FxHashSet<GenericBound>>,
|
||||
ty_to_fn: FxHashMap<Type, (Option<PolyTrait>, Option<Type>)>,
|
||||
lifetime_to_bounds: FxHashMap<Lifetime, FxHashSet<Lifetime>>,
|
||||
lifetime_to_bounds: FxHashMap<Lifetime, FxHashSet<GenericBound>>,
|
||||
) -> Vec<WherePredicate> {
|
||||
ty_to_bounds
|
||||
.into_iter()
|
||||
|
|
@ -555,9 +553,9 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
|||
let mut new_path = path.clone();
|
||||
let last_segment = new_path.segments.pop().unwrap();
|
||||
|
||||
let (old_input, old_output) = match last_segment.params {
|
||||
PathParameters::AngleBracketed { types, .. } => (types, None),
|
||||
PathParameters::Parenthesized { inputs, output, .. } => {
|
||||
let (old_input, old_output) = match last_segment.args {
|
||||
GenericArgs::AngleBracketed { types, .. } => (types, None),
|
||||
GenericArgs::Parenthesized { inputs, output, .. } => {
|
||||
(inputs, output)
|
||||
}
|
||||
};
|
||||
|
|
@ -569,14 +567,14 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
|||
);
|
||||
}
|
||||
|
||||
let new_params = PathParameters::Parenthesized {
|
||||
let new_params = GenericArgs::Parenthesized {
|
||||
inputs: old_input,
|
||||
output,
|
||||
};
|
||||
|
||||
new_path.segments.push(PathSegment {
|
||||
name: last_segment.name,
|
||||
params: new_params,
|
||||
args: new_params,
|
||||
});
|
||||
|
||||
Type::ResolvedPath {
|
||||
|
|
@ -588,7 +586,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
|||
}
|
||||
_ => panic!("Unexpected data: {:?}, {:?}", ty, data),
|
||||
};
|
||||
bounds.insert(TyParamBound::TraitBound(
|
||||
bounds.insert(GenericBound::TraitBound(
|
||||
PolyTrait {
|
||||
trait_: new_ty,
|
||||
generic_params: poly_trait.generic_params,
|
||||
|
|
@ -614,7 +612,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
|||
.filter(|&(_, ref bounds)| !bounds.is_empty())
|
||||
.map(|(lifetime, bounds)| {
|
||||
let mut bounds_vec = bounds.into_iter().collect();
|
||||
self.sort_where_lifetimes(&mut bounds_vec);
|
||||
self.sort_where_bounds(&mut bounds_vec);
|
||||
WherePredicate::RegionPredicate {
|
||||
lifetime,
|
||||
bounds: bounds_vec,
|
||||
|
|
@ -731,7 +729,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
|||
// later
|
||||
|
||||
let is_fn = match &mut b {
|
||||
&mut TyParamBound::TraitBound(ref mut p, _) => {
|
||||
&mut GenericBound::TraitBound(ref mut p, _) => {
|
||||
// Insert regions into the for_generics hash map first, to ensure
|
||||
// that we don't end up with duplicate bounds (e.g. for<'b, 'b>)
|
||||
for_generics.extend(p.generic_params.clone());
|
||||
|
|
@ -793,13 +791,13 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
|||
|
||||
// FIXME: Remove this scope when NLL lands
|
||||
{
|
||||
let params =
|
||||
&mut new_trait_path.segments.last_mut().unwrap().params;
|
||||
let args =
|
||||
&mut new_trait_path.segments.last_mut().unwrap().args;
|
||||
|
||||
match params {
|
||||
match args {
|
||||
// Convert somethiung like '<T as Iterator::Item> = u8'
|
||||
// to 'T: Iterator<Item=u8>'
|
||||
&mut PathParameters::AngleBracketed {
|
||||
&mut GenericArgs::AngleBracketed {
|
||||
ref mut bindings,
|
||||
..
|
||||
} => {
|
||||
|
|
@ -808,7 +806,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
|||
ty: rhs,
|
||||
});
|
||||
}
|
||||
&mut PathParameters::Parenthesized { .. } => {
|
||||
&mut GenericArgs::Parenthesized { .. } => {
|
||||
existing_predicates.push(
|
||||
WherePredicate::EqPredicate {
|
||||
lhs: lhs.clone(),
|
||||
|
|
@ -825,7 +823,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
|||
.entry(*ty.clone())
|
||||
.or_insert_with(|| FxHashSet());
|
||||
|
||||
bounds.insert(TyParamBound::TraitBound(
|
||||
bounds.insert(GenericBound::TraitBound(
|
||||
PolyTrait {
|
||||
trait_: Type::ResolvedPath {
|
||||
path: new_trait_path,
|
||||
|
|
@ -842,7 +840,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
|||
// that we don't see a
|
||||
// duplicate bound like `T: Iterator + Iterator<Item=u8>`
|
||||
// on the docs page.
|
||||
bounds.remove(&TyParamBound::TraitBound(
|
||||
bounds.remove(&GenericBound::TraitBound(
|
||||
PolyTrait {
|
||||
trait_: *trait_.clone(),
|
||||
generic_params: Vec::new(),
|
||||
|
|
@ -869,19 +867,17 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
|||
|
||||
existing_predicates.extend(final_bounds);
|
||||
|
||||
for p in generic_params.iter_mut() {
|
||||
match p {
|
||||
&mut GenericParamDef::Type(ref mut ty) => {
|
||||
// We never want something like 'impl<T=Foo>'
|
||||
ty.default.take();
|
||||
|
||||
let generic_ty = Type::Generic(ty.name.clone());
|
||||
|
||||
for param in generic_params.iter_mut() {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Type { ref mut default, ref mut bounds, .. } => {
|
||||
// We never want something like `impl<T=Foo>`.
|
||||
default.take();
|
||||
let generic_ty = Type::Generic(param.name.clone());
|
||||
if !has_sized.contains(&generic_ty) {
|
||||
ty.bounds.insert(0, TyParamBound::maybe_sized(self.cx));
|
||||
bounds.insert(0, GenericBound::maybe_sized(self.cx));
|
||||
}
|
||||
}
|
||||
GenericParamDef::Lifetime(_) => {}
|
||||
GenericParamDefKind::Lifetime => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -912,15 +908,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
|||
// both for visual consistency between 'rustdoc' runs, and to
|
||||
// make writing tests much easier
|
||||
#[inline]
|
||||
fn sort_where_bounds(&self, mut bounds: &mut Vec<TyParamBound>) {
|
||||
// We should never have identical bounds - and if we do,
|
||||
// they're visually identical as well. Therefore, using
|
||||
// an unstable sort is fine.
|
||||
self.unstable_debug_sort(&mut bounds);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sort_where_lifetimes(&self, mut bounds: &mut Vec<Lifetime>) {
|
||||
fn sort_where_bounds(&self, mut bounds: &mut Vec<GenericBound>) {
|
||||
// We should never have identical bounds - and if we do,
|
||||
// they're visually identical as well. Therefore, using
|
||||
// an unstable sort is fine.
|
||||
|
|
@ -940,7 +928,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
|||
// to end users, it makes writing tests much more difficult, as predicates
|
||||
// can appear in any order in the final result.
|
||||
//
|
||||
// To solve this problem, we sort WherePredicates and TyParamBounds
|
||||
// To solve this problem, we sort WherePredicates and GenericBounds
|
||||
// by their Debug string. The thing to keep in mind is that we don't really
|
||||
// care what the final order is - we're synthesizing an impl or bound
|
||||
// ourselves, so any order can be considered equally valid. By sorting the
|
||||
|
|
@ -950,7 +938,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
|||
// Using the Debug impementation for sorting prevents us from needing to
|
||||
// write quite a bit of almost entirely useless code (e.g. how should two
|
||||
// Types be sorted relative to each other). It also allows us to solve the
|
||||
// problem for both WherePredicates and TyParamBounds at the same time. This
|
||||
// problem for both WherePredicates and GenericBounds at the same time. This
|
||||
// approach is probably somewhat slower, but the small number of items
|
||||
// involved (impls rarely have more than a few bounds) means that it
|
||||
// shouldn't matter in practice.
|
||||
|
|
|
|||
|
|
@ -374,8 +374,8 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
|
|||
let polarity = tcx.impl_polarity(did);
|
||||
let trait_ = associated_trait.clean(cx).map(|bound| {
|
||||
match bound {
|
||||
clean::TraitBound(polyt, _) => polyt.trait_,
|
||||
clean::RegionBound(..) => unreachable!(),
|
||||
clean::GenericBound::TraitBound(polyt, _) => polyt.trait_,
|
||||
clean::GenericBound::Outlives(..) => unreachable!(),
|
||||
}
|
||||
});
|
||||
if trait_.def_id() == tcx.lang_items().deref_trait() {
|
||||
|
|
@ -387,9 +387,9 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
|
|||
|
||||
let provided = trait_.def_id().map(|did| {
|
||||
tcx.provided_trait_methods(did)
|
||||
.into_iter()
|
||||
.map(|meth| meth.name.to_string())
|
||||
.collect()
|
||||
.into_iter()
|
||||
.map(|meth| meth.name.to_string())
|
||||
.collect()
|
||||
}).unwrap_or(FxHashSet());
|
||||
|
||||
ret.push(clean::Item {
|
||||
|
|
@ -474,7 +474,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean:
|
|||
} if *s == "Self" => {
|
||||
bounds.retain(|bound| {
|
||||
match *bound {
|
||||
clean::TyParamBound::TraitBound(clean::PolyTrait {
|
||||
clean::GenericBound::TraitBound(clean::PolyTrait {
|
||||
trait_: clean::ResolvedPath { did, .. },
|
||||
..
|
||||
}, _) => did != trait_did,
|
||||
|
|
@ -505,7 +505,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean:
|
|||
/// the metadata for a crate, so we want to separate those out and create a new
|
||||
/// list of explicit supertrait bounds to render nicely.
|
||||
fn separate_supertrait_bounds(mut g: clean::Generics)
|
||||
-> (clean::Generics, Vec<clean::TyParamBound>) {
|
||||
-> (clean::Generics, Vec<clean::GenericBound>) {
|
||||
let mut ty_bounds = Vec::new();
|
||||
g.where_predicates.retain(|pred| {
|
||||
match *pred {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
pub use self::Type::*;
|
||||
pub use self::Mutability::*;
|
||||
pub use self::ItemEnum::*;
|
||||
pub use self::TyParamBound::*;
|
||||
pub use self::SelfTy::*;
|
||||
pub use self::FunctionRetTy::*;
|
||||
pub use self::Visibility::{Public, Inherited};
|
||||
|
|
@ -36,12 +35,12 @@ use rustc::middle::resolve_lifetime as rl;
|
|||
use rustc::ty::fold::TypeFolder;
|
||||
use rustc::middle::lang_items;
|
||||
use rustc::mir::interpret::GlobalId;
|
||||
use rustc::hir::{self, HirVec};
|
||||
use rustc::hir::{self, GenericArg, HirVec};
|
||||
use rustc::hir::def::{self, Def, CtorKind};
|
||||
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||
use rustc::hir::def_id::DefIndexAddressSpace;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind, GenericParamCount};
|
||||
use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind};
|
||||
use rustc::middle::stability;
|
||||
use rustc::util::nodemap::{FxHashMap, FxHashSet};
|
||||
use rustc_typeck::hir_ty_to_ty;
|
||||
|
|
@ -532,7 +531,7 @@ pub enum ItemEnum {
|
|||
MacroItem(Macro),
|
||||
PrimitiveItem(PrimitiveType),
|
||||
AssociatedConstItem(Type, Option<String>),
|
||||
AssociatedTypeItem(Vec<TyParamBound>, Option<Type>),
|
||||
AssociatedTypeItem(Vec<GenericBound>, Option<Type>),
|
||||
/// An item that has been stripped by a rustdoc pass
|
||||
StrippedItem(Box<ItemEnum>),
|
||||
KeywordItem(String),
|
||||
|
|
@ -1458,61 +1457,19 @@ impl Clean<Attributes> for [ast::Attribute] {
|
|||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct TyParam {
|
||||
pub name: String,
|
||||
pub did: DefId,
|
||||
pub bounds: Vec<TyParamBound>,
|
||||
pub default: Option<Type>,
|
||||
pub synthetic: Option<hir::SyntheticTyParamKind>,
|
||||
pub enum GenericBound {
|
||||
TraitBound(PolyTrait, hir::TraitBoundModifier),
|
||||
Outlives(Lifetime),
|
||||
}
|
||||
|
||||
impl Clean<TyParam> for hir::TyParam {
|
||||
fn clean(&self, cx: &DocContext) -> TyParam {
|
||||
TyParam {
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<TyParam> for ty::GenericParamDef {
|
||||
fn clean(&self, cx: &DocContext) -> TyParam {
|
||||
cx.renderinfo.borrow_mut().external_typarams.insert(self.def_id, self.name.clean(cx));
|
||||
let has_default = match self.kind {
|
||||
ty::GenericParamDefKind::Type { has_default, .. } => has_default,
|
||||
_ => panic!("tried to convert a non-type GenericParamDef as a type")
|
||||
};
|
||||
TyParam {
|
||||
name: self.name.clean(cx),
|
||||
did: self.def_id,
|
||||
bounds: vec![], // these are filled in from the where-clauses
|
||||
default: if has_default {
|
||||
Some(cx.tcx.type_of(self.def_id).clean(cx))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
synthetic: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum TyParamBound {
|
||||
RegionBound(Lifetime),
|
||||
TraitBound(PolyTrait, hir::TraitBoundModifier)
|
||||
}
|
||||
|
||||
impl TyParamBound {
|
||||
fn maybe_sized(cx: &DocContext) -> TyParamBound {
|
||||
impl GenericBound {
|
||||
fn maybe_sized(cx: &DocContext) -> GenericBound {
|
||||
let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem);
|
||||
let empty = cx.tcx.intern_substs(&[]);
|
||||
let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
|
||||
Some(did), false, vec![], empty);
|
||||
inline::record_extern_fqn(cx, did, TypeKind::Trait);
|
||||
TraitBound(PolyTrait {
|
||||
GenericBound::TraitBound(PolyTrait {
|
||||
trait_: ResolvedPath {
|
||||
path,
|
||||
typarams: None,
|
||||
|
|
@ -1525,7 +1482,7 @@ impl TyParamBound {
|
|||
|
||||
fn is_sized_bound(&self, cx: &DocContext) -> bool {
|
||||
use rustc::hir::TraitBoundModifier as TBM;
|
||||
if let TyParamBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
|
||||
if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
|
||||
if trait_.def_id() == cx.tcx.lang_items().sized_trait() {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1534,7 +1491,7 @@ impl TyParamBound {
|
|||
}
|
||||
|
||||
fn get_poly_trait(&self) -> Option<PolyTrait> {
|
||||
if let TyParamBound::TraitBound(ref p, _) = *self {
|
||||
if let GenericBound::TraitBound(ref p, _) = *self {
|
||||
return Some(p.clone())
|
||||
}
|
||||
None
|
||||
|
|
@ -1542,24 +1499,26 @@ impl TyParamBound {
|
|||
|
||||
fn get_trait_type(&self) -> Option<Type> {
|
||||
|
||||
if let TyParamBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
|
||||
if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
|
||||
return Some(trait_.clone());
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl Clean<TyParamBound> for hir::TyParamBound {
|
||||
fn clean(&self, cx: &DocContext) -> TyParamBound {
|
||||
impl Clean<GenericBound> for hir::GenericBound {
|
||||
fn clean(&self, cx: &DocContext) -> GenericBound {
|
||||
match *self {
|
||||
hir::RegionTyParamBound(lt) => RegionBound(lt.clean(cx)),
|
||||
hir::TraitTyParamBound(ref t, modifier) => TraitBound(t.clean(cx), modifier),
|
||||
hir::GenericBound::Outlives(lt) => GenericBound::Outlives(lt.clean(cx)),
|
||||
hir::GenericBound::Trait(ref t, modifier) => {
|
||||
GenericBound::TraitBound(t.clean(cx), modifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn external_path_params(cx: &DocContext, trait_did: Option<DefId>, has_self: bool,
|
||||
bindings: Vec<TypeBinding>, substs: &Substs) -> PathParameters {
|
||||
fn external_generic_args(cx: &DocContext, trait_did: Option<DefId>, has_self: bool,
|
||||
bindings: Vec<TypeBinding>, substs: &Substs) -> GenericArgs {
|
||||
let lifetimes = substs.regions().filter_map(|v| v.clean(cx)).collect();
|
||||
let types = substs.types().skip(has_self as usize).collect::<Vec<_>>();
|
||||
|
||||
|
|
@ -1570,7 +1529,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option<DefId>, has_self: boo
|
|||
let inputs = match types[0].sty {
|
||||
ty::TyTuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(),
|
||||
_ => {
|
||||
return PathParameters::AngleBracketed {
|
||||
return GenericArgs::AngleBracketed {
|
||||
lifetimes,
|
||||
types: types.clean(cx),
|
||||
bindings,
|
||||
|
|
@ -1583,13 +1542,13 @@ fn external_path_params(cx: &DocContext, trait_did: Option<DefId>, has_self: boo
|
|||
// ty::TyTuple(ref v) if v.is_empty() => None, // -> ()
|
||||
// _ => Some(types[1].clean(cx))
|
||||
// };
|
||||
PathParameters::Parenthesized {
|
||||
GenericArgs::Parenthesized {
|
||||
inputs,
|
||||
output,
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
PathParameters::AngleBracketed {
|
||||
GenericArgs::AngleBracketed {
|
||||
lifetimes,
|
||||
types: types.clean(cx),
|
||||
bindings,
|
||||
|
|
@ -1607,13 +1566,13 @@ fn external_path(cx: &DocContext, name: &str, trait_did: Option<DefId>, has_self
|
|||
def: Def::Err,
|
||||
segments: vec![PathSegment {
|
||||
name: name.to_string(),
|
||||
params: external_path_params(cx, trait_did, has_self, bindings, substs)
|
||||
args: external_generic_args(cx, trait_did, has_self, bindings, substs)
|
||||
}],
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Clean<TyParamBound> for (&'a ty::TraitRef<'tcx>, Vec<TypeBinding>) {
|
||||
fn clean(&self, cx: &DocContext) -> TyParamBound {
|
||||
impl<'a, 'tcx> Clean<GenericBound> for (&'a ty::TraitRef<'tcx>, Vec<TypeBinding>) {
|
||||
fn clean(&self, cx: &DocContext) -> GenericBound {
|
||||
let (trait_ref, ref bounds) = *self;
|
||||
inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait);
|
||||
let path = external_path(cx, &cx.tcx.item_name(trait_ref.def_id).as_str(),
|
||||
|
|
@ -1629,8 +1588,11 @@ impl<'a, 'tcx> Clean<TyParamBound> for (&'a ty::TraitRef<'tcx>, Vec<TypeBinding>
|
|||
if let ty::TyRef(ref reg, _, _) = ty_s.sty {
|
||||
if let &ty::RegionKind::ReLateBound(..) = *reg {
|
||||
debug!(" hit an ReLateBound {:?}", reg);
|
||||
if let Some(lt) = reg.clean(cx) {
|
||||
late_bounds.push(GenericParamDef::Lifetime(lt));
|
||||
if let Some(Lifetime(name)) = reg.clean(cx) {
|
||||
late_bounds.push(GenericParamDef {
|
||||
name,
|
||||
kind: GenericParamDefKind::Lifetime,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1638,7 +1600,7 @@ impl<'a, 'tcx> Clean<TyParamBound> for (&'a ty::TraitRef<'tcx>, Vec<TypeBinding>
|
|||
}
|
||||
}
|
||||
|
||||
TraitBound(
|
||||
GenericBound::TraitBound(
|
||||
PolyTrait {
|
||||
trait_: ResolvedPath {
|
||||
path,
|
||||
|
|
@ -1653,18 +1615,17 @@ impl<'a, 'tcx> Clean<TyParamBound> for (&'a ty::TraitRef<'tcx>, Vec<TypeBinding>
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
|
||||
fn clean(&self, cx: &DocContext) -> TyParamBound {
|
||||
impl<'tcx> Clean<GenericBound> for ty::TraitRef<'tcx> {
|
||||
fn clean(&self, cx: &DocContext) -> GenericBound {
|
||||
(self, vec![]).clean(cx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<Option<Vec<TyParamBound>>> for Substs<'tcx> {
|
||||
fn clean(&self, cx: &DocContext) -> Option<Vec<TyParamBound>> {
|
||||
impl<'tcx> Clean<Option<Vec<GenericBound>>> for Substs<'tcx> {
|
||||
fn clean(&self, cx: &DocContext) -> Option<Vec<GenericBound>> {
|
||||
let mut v = Vec::new();
|
||||
v.extend(self.regions().filter_map(|r| r.clean(cx))
|
||||
.map(RegionBound));
|
||||
v.extend(self.types().map(|t| TraitBound(PolyTrait {
|
||||
v.extend(self.regions().filter_map(|r| r.clean(cx)).map(GenericBound::Outlives));
|
||||
v.extend(self.types().map(|t| GenericBound::TraitBound(PolyTrait {
|
||||
trait_: t.clean(cx),
|
||||
generic_params: Vec::new(),
|
||||
}, hir::TraitBoundModifier::None)));
|
||||
|
|
@ -1707,18 +1668,26 @@ 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) {
|
||||
s.push_str(&format!(" + {}", bound.name.name()));
|
||||
match self.kind {
|
||||
hir::GenericParamKind::Lifetime { .. } => {
|
||||
if self.bounds.len() > 0 {
|
||||
let mut bounds = self.bounds.iter().map(|bound| match bound {
|
||||
hir::GenericBound::Outlives(lt) => lt,
|
||||
_ => panic!(),
|
||||
});
|
||||
let name = bounds.next().unwrap().name.name();
|
||||
let mut s = format!("{}: {}", self.name.name(), name);
|
||||
for bound in bounds {
|
||||
s.push_str(&format!(" + {}", bound.name.name()));
|
||||
}
|
||||
Lifetime(s)
|
||||
} else {
|
||||
Lifetime(self.name.name().to_string())
|
||||
}
|
||||
}
|
||||
Lifetime(s)
|
||||
} else {
|
||||
Lifetime(self.lifetime.name.name().to_string())
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1751,8 +1720,8 @@ impl Clean<Option<Lifetime>> for ty::RegionKind {
|
|||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum WherePredicate {
|
||||
BoundPredicate { ty: Type, bounds: Vec<TyParamBound> },
|
||||
RegionPredicate { lifetime: Lifetime, bounds: Vec<Lifetime>},
|
||||
BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
|
||||
RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
|
||||
EqPredicate { lhs: Type, rhs: Type },
|
||||
}
|
||||
|
||||
|
|
@ -1822,7 +1791,7 @@ impl<'tcx> Clean<WherePredicate> for ty::OutlivesPredicate<ty::Region<'tcx>, ty:
|
|||
let ty::OutlivesPredicate(ref a, ref b) = *self;
|
||||
WherePredicate::RegionPredicate {
|
||||
lifetime: a.clean(cx).unwrap(),
|
||||
bounds: vec![b.clean(cx).unwrap()]
|
||||
bounds: vec![GenericBound::Outlives(b.clean(cx).unwrap())]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1833,7 +1802,7 @@ impl<'tcx> Clean<WherePredicate> for ty::OutlivesPredicate<Ty<'tcx>, ty::Region<
|
|||
|
||||
WherePredicate::BoundPredicate {
|
||||
ty: ty.clean(cx),
|
||||
bounds: vec![TyParamBound::RegionBound(lt.clean(cx).unwrap())]
|
||||
bounds: vec![GenericBound::Outlives(lt.clean(cx).unwrap())]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1850,10 +1819,8 @@ impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> {
|
|||
impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
|
||||
fn clean(&self, cx: &DocContext) -> Type {
|
||||
let trait_ = match self.trait_ref(cx.tcx).clean(cx) {
|
||||
TyParamBound::TraitBound(t, _) => t.trait_,
|
||||
TyParamBound::RegionBound(_) => {
|
||||
panic!("cleaning a trait got a region")
|
||||
}
|
||||
GenericBound::TraitBound(t, _) => t.trait_,
|
||||
GenericBound::Outlives(_) => panic!("cleaning a trait got a lifetime"),
|
||||
};
|
||||
Type::QPath {
|
||||
name: cx.tcx.associated_item(self.item_def_id).name.clean(cx),
|
||||
|
|
@ -1864,25 +1831,95 @@ impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
|
|||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum GenericParamDef {
|
||||
Lifetime(Lifetime),
|
||||
Type(TyParam),
|
||||
pub enum GenericParamDefKind {
|
||||
Lifetime,
|
||||
Type {
|
||||
did: DefId,
|
||||
bounds: Vec<GenericBound>,
|
||||
default: Option<Type>,
|
||||
synthetic: Option<hir::SyntheticTyParamKind>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct GenericParamDef {
|
||||
pub name: String,
|
||||
|
||||
pub kind: GenericParamDefKind,
|
||||
}
|
||||
|
||||
impl GenericParamDef {
|
||||
pub fn is_synthetic_type_param(&self) -> bool {
|
||||
match self {
|
||||
GenericParamDef::Type(ty) => ty.synthetic.is_some(),
|
||||
GenericParamDef::Lifetime(_) => false,
|
||||
match self.kind {
|
||||
GenericParamDefKind::Lifetime => false,
|
||||
GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<GenericParamDef> for ty::GenericParamDef {
|
||||
fn clean(&self, cx: &DocContext) -> GenericParamDef {
|
||||
let (name, kind) = match self.kind {
|
||||
ty::GenericParamDefKind::Lifetime => {
|
||||
(self.name.to_string(), GenericParamDefKind::Lifetime)
|
||||
}
|
||||
ty::GenericParamDefKind::Type { has_default, .. } => {
|
||||
cx.renderinfo.borrow_mut().external_typarams
|
||||
.insert(self.def_id, self.name.clean(cx));
|
||||
let default = if has_default {
|
||||
Some(cx.tcx.type_of(self.def_id).clean(cx))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
(self.name.clean(cx), GenericParamDefKind::Type {
|
||||
did: self.def_id,
|
||||
bounds: vec![], // These are filled in from the where-clauses.
|
||||
default,
|
||||
synthetic: None,
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
GenericParamDef {
|
||||
name,
|
||||
kind,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clean<GenericParamDef> for hir::GenericParam {
|
||||
fn clean(&self, cx: &DocContext) -> GenericParamDef {
|
||||
match *self {
|
||||
hir::GenericParam::Lifetime(ref l) => GenericParamDef::Lifetime(l.clean(cx)),
|
||||
hir::GenericParam::Type(ref t) => GenericParamDef::Type(t.clean(cx)),
|
||||
let (name, kind) = match self.kind {
|
||||
hir::GenericParamKind::Lifetime { .. } => {
|
||||
let name = if self.bounds.len() > 0 {
|
||||
let mut bounds = self.bounds.iter().map(|bound| match bound {
|
||||
hir::GenericBound::Outlives(lt) => lt,
|
||||
_ => panic!(),
|
||||
});
|
||||
let name = bounds.next().unwrap().name.name();
|
||||
let mut s = format!("{}: {}", self.name.name(), name);
|
||||
for bound in bounds {
|
||||
s.push_str(&format!(" + {}", bound.name.name()));
|
||||
}
|
||||
s
|
||||
} else {
|
||||
self.name.name().to_string()
|
||||
};
|
||||
(name, GenericParamDefKind::Lifetime)
|
||||
}
|
||||
hir::GenericParamKind::Type { ref default, synthetic, .. } => {
|
||||
(self.name.name().clean(cx), GenericParamDefKind::Type {
|
||||
did: cx.tcx.hir.local_def_id(self.id),
|
||||
bounds: self.bounds.clean(cx),
|
||||
default: default.clean(cx),
|
||||
synthetic: synthetic,
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
GenericParamDef {
|
||||
name,
|
||||
kind,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1900,25 +1937,25 @@ 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
|
||||
.iter()
|
||||
.filter(|p| is_impl_trait(p))
|
||||
.map(|p| {
|
||||
let p = p.clean(cx);
|
||||
if let GenericParamDef::Type(ref tp) = p {
|
||||
cx.impl_trait_bounds
|
||||
.borrow_mut()
|
||||
.insert(tp.did, tp.bounds.clone());
|
||||
} else {
|
||||
unreachable!()
|
||||
.filter(|param| is_impl_trait(param))
|
||||
.map(|param| {
|
||||
let param: GenericParamDef = param.clean(cx);
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => unreachable!(),
|
||||
GenericParamDefKind::Type { did, ref bounds, .. } => {
|
||||
cx.impl_trait_bounds.borrow_mut().insert(did, bounds.clone());
|
||||
}
|
||||
}
|
||||
p
|
||||
param
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
|
|
@ -1929,23 +1966,26 @@ impl Clean<Generics> for hir::Generics {
|
|||
}
|
||||
params.extend(impl_trait_params);
|
||||
|
||||
let mut g = Generics {
|
||||
let mut generics = Generics {
|
||||
params,
|
||||
where_predicates: self.where_clause.predicates.clean(cx)
|
||||
where_predicates: self.where_clause.predicates.clean(cx),
|
||||
};
|
||||
|
||||
// Some duplicates are generated for ?Sized bounds between type params and where
|
||||
// predicates. The point in here is to move the bounds definitions from type params
|
||||
// to where predicates when such cases occur.
|
||||
for where_pred in &mut g.where_predicates {
|
||||
for where_pred in &mut generics.where_predicates {
|
||||
match *where_pred {
|
||||
WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds } => {
|
||||
if bounds.is_empty() {
|
||||
for param in &mut g.params {
|
||||
if let GenericParamDef::Type(ref mut type_param) = *param {
|
||||
if &type_param.name == name {
|
||||
mem::swap(bounds, &mut type_param.bounds);
|
||||
break
|
||||
for param in &mut generics.params {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {}
|
||||
GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => {
|
||||
if ¶m.name == name {
|
||||
mem::swap(bounds, ty_bounds);
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1954,7 +1994,7 @@ impl Clean<Generics> for hir::Generics {
|
|||
_ => continue,
|
||||
}
|
||||
}
|
||||
g
|
||||
generics
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1968,18 +2008,16 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
|
|||
// Bounds in the type_params and lifetimes fields are repeated in the
|
||||
// predicates field (see rustc_typeck::collect::ty_generics), so remove
|
||||
// them.
|
||||
let stripped_typarams = gens.params.iter().filter_map(|param| {
|
||||
if let ty::GenericParamDefKind::Type {..} = param.kind {
|
||||
let stripped_typarams = gens.params.iter().filter_map(|param| match param.kind {
|
||||
ty::GenericParamDefKind::Lifetime => None,
|
||||
ty::GenericParamDefKind::Type { .. } => {
|
||||
if param.name == keywords::SelfType.name().as_str() {
|
||||
assert_eq!(param.index, 0);
|
||||
None
|
||||
} else {
|
||||
Some(param.clean(cx))
|
||||
return None;
|
||||
}
|
||||
} else {
|
||||
None
|
||||
Some(param.clean(cx))
|
||||
}
|
||||
}).collect::<Vec<TyParam>>();
|
||||
}).collect::<Vec<GenericParamDef>>();
|
||||
|
||||
let mut where_predicates = preds.predicates.to_vec().clean(cx);
|
||||
|
||||
|
|
@ -2011,7 +2049,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
|
|||
if !sized_params.contains(&tp.name) {
|
||||
where_predicates.push(WP::BoundPredicate {
|
||||
ty: Type::Generic(tp.name.clone()),
|
||||
bounds: vec![TyParamBound::maybe_sized(cx)],
|
||||
bounds: vec![GenericBound::maybe_sized(cx)],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -2023,17 +2061,10 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
|
|||
Generics {
|
||||
params: gens.params
|
||||
.iter()
|
||||
.flat_map(|param| {
|
||||
if let ty::GenericParamDefKind::Lifetime = param.kind {
|
||||
Some(GenericParamDef::Lifetime(param.clean(cx)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).chain(
|
||||
simplify::ty_params(stripped_typarams)
|
||||
.into_iter()
|
||||
.map(|tp| GenericParamDef::Type(tp))
|
||||
)
|
||||
.flat_map(|param| match param.kind {
|
||||
ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)),
|
||||
ty::GenericParamDefKind::Type { .. } => None,
|
||||
}).chain(simplify::ty_params(stripped_typarams).into_iter())
|
||||
.collect(),
|
||||
where_predicates: simplify::where_clauses(cx, where_predicates),
|
||||
}
|
||||
|
|
@ -2259,7 +2290,7 @@ pub struct Trait {
|
|||
pub unsafety: hir::Unsafety,
|
||||
pub items: Vec<Item>,
|
||||
pub generics: Generics,
|
||||
pub bounds: Vec<TyParamBound>,
|
||||
pub bounds: Vec<GenericBound>,
|
||||
pub is_spotlight: bool,
|
||||
pub is_auto: bool,
|
||||
}
|
||||
|
|
@ -2481,7 +2512,7 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem {
|
|||
// at the end.
|
||||
match bounds.iter().position(|b| b.is_sized_bound(cx)) {
|
||||
Some(i) => { bounds.remove(i); }
|
||||
None => bounds.push(TyParamBound::maybe_sized(cx)),
|
||||
None => bounds.push(GenericBound::maybe_sized(cx)),
|
||||
}
|
||||
|
||||
let ty = if self.defaultness.has_value() {
|
||||
|
|
@ -2536,7 +2567,7 @@ pub enum Type {
|
|||
/// structs/enums/traits (most that'd be an hir::TyPath)
|
||||
ResolvedPath {
|
||||
path: Path,
|
||||
typarams: Option<Vec<TyParamBound>>,
|
||||
typarams: Option<Vec<GenericBound>>,
|
||||
did: DefId,
|
||||
/// true if is a `T::Name` path for associated types
|
||||
is_generic: bool,
|
||||
|
|
@ -2572,7 +2603,7 @@ pub enum Type {
|
|||
Infer,
|
||||
|
||||
// impl TraitA+TraitB
|
||||
ImplTrait(Vec<TyParamBound>),
|
||||
ImplTrait(Vec<GenericBound>),
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)]
|
||||
|
|
@ -2656,7 +2687,7 @@ impl Type {
|
|||
match *self {
|
||||
ResolvedPath { ref path, .. } => {
|
||||
path.segments.last().and_then(|seg| {
|
||||
if let PathParameters::AngleBracketed { ref types, .. } = seg.params {
|
||||
if let GenericArgs::AngleBracketed { ref types, .. } = seg.args {
|
||||
Some(&**types)
|
||||
} else {
|
||||
None
|
||||
|
|
@ -2851,31 +2882,55 @@ impl Clean<Type> for hir::Ty {
|
|||
let provided_params = &path.segments.last().unwrap();
|
||||
let mut ty_substs = FxHashMap();
|
||||
let mut lt_substs = FxHashMap();
|
||||
provided_params.with_parameters(|provided_params| {
|
||||
let mut indices = GenericParamCount {
|
||||
provided_params.with_generic_args(|generic_args| {
|
||||
let mut indices = ty::GenericParamCount {
|
||||
lifetimes: 0,
|
||||
types: 0
|
||||
};
|
||||
for param in generics.params.iter() {
|
||||
match param {
|
||||
hir::GenericParam::Lifetime(lt_param) => {
|
||||
if let Some(lt) = provided_params.lifetimes
|
||||
.get(indices.lifetimes).cloned() {
|
||||
match param.kind {
|
||||
hir::GenericParamKind::Lifetime { .. } => {
|
||||
let mut j = 0;
|
||||
let lifetime = generic_args.args.iter().find_map(|arg| {
|
||||
match arg {
|
||||
GenericArg::Lifetime(lt) => {
|
||||
if indices.lifetimes == j {
|
||||
return Some(lt);
|
||||
}
|
||||
j += 1;
|
||||
None
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
});
|
||||
if let Some(lt) = lifetime.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));
|
||||
if let Some(ty) = provided_params.types
|
||||
.get(indices.types).cloned() {
|
||||
Def::TyParam(cx.tcx.hir.local_def_id(param.id));
|
||||
let mut j = 0;
|
||||
let type_ = generic_args.args.iter().find_map(|arg| {
|
||||
match arg {
|
||||
GenericArg::Type(ty) => {
|
||||
if indices.types == j {
|
||||
return Some(ty);
|
||||
}
|
||||
j += 1;
|
||||
None
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
});
|
||||
if let Some(ty) = type_.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));
|
||||
}
|
||||
|
|
@ -2922,18 +2977,14 @@ impl Clean<Type> for hir::Ty {
|
|||
TyTraitObject(ref bounds, ref lifetime) => {
|
||||
match bounds[0].clean(cx).trait_ {
|
||||
ResolvedPath { path, typarams: None, did, is_generic } => {
|
||||
let mut bounds: Vec<_> = bounds[1..].iter().map(|bound| {
|
||||
TraitBound(bound.clean(cx), hir::TraitBoundModifier::None)
|
||||
let mut bounds: Vec<self::GenericBound> = bounds[1..].iter().map(|bound| {
|
||||
self::GenericBound::TraitBound(bound.clean(cx),
|
||||
hir::TraitBoundModifier::None)
|
||||
}).collect();
|
||||
if !lifetime.is_elided() {
|
||||
bounds.push(RegionBound(lifetime.clean(cx)));
|
||||
}
|
||||
ResolvedPath {
|
||||
path,
|
||||
typarams: Some(bounds),
|
||||
did,
|
||||
is_generic,
|
||||
bounds.push(self::GenericBound::Outlives(lifetime.clean(cx)));
|
||||
}
|
||||
ResolvedPath { path, typarams: Some(bounds), did, is_generic, }
|
||||
}
|
||||
_ => Infer // shouldn't happen
|
||||
}
|
||||
|
|
@ -3030,13 +3081,13 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
|
|||
inline::record_extern_fqn(cx, did, TypeKind::Trait);
|
||||
|
||||
let mut typarams = vec![];
|
||||
reg.clean(cx).map(|b| typarams.push(RegionBound(b)));
|
||||
reg.clean(cx).map(|b| typarams.push(GenericBound::Outlives(b)));
|
||||
for did in obj.auto_traits() {
|
||||
let empty = cx.tcx.intern_substs(&[]);
|
||||
let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
|
||||
Some(did), false, vec![], empty);
|
||||
inline::record_extern_fqn(cx, did, TypeKind::Trait);
|
||||
let bound = TraitBound(PolyTrait {
|
||||
let bound = GenericBound::TraitBound(PolyTrait {
|
||||
trait_: ResolvedPath {
|
||||
path,
|
||||
typarams: None,
|
||||
|
|
@ -3087,7 +3138,9 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
|
|||
tr
|
||||
} else if let ty::Predicate::TypeOutlives(pred) = *predicate {
|
||||
// these should turn up at the end
|
||||
pred.skip_binder().1.clean(cx).map(|r| regions.push(RegionBound(r)));
|
||||
pred.skip_binder().1.clean(cx).map(|r| {
|
||||
regions.push(GenericBound::Outlives(r))
|
||||
});
|
||||
return None;
|
||||
} else {
|
||||
return None;
|
||||
|
|
@ -3100,7 +3153,6 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
let bounds = bounds.predicates.iter().filter_map(|pred|
|
||||
if let ty::Predicate::Projection(proj) = *pred {
|
||||
let proj = proj.skip_binder();
|
||||
|
|
@ -3122,7 +3174,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
|
|||
}).collect::<Vec<_>>();
|
||||
bounds.extend(regions);
|
||||
if !has_sized && !bounds.is_empty() {
|
||||
bounds.insert(0, TyParamBound::maybe_sized(cx));
|
||||
bounds.insert(0, GenericBound::maybe_sized(cx));
|
||||
}
|
||||
ImplTrait(bounds)
|
||||
}
|
||||
|
|
@ -3447,7 +3499,7 @@ impl Path {
|
|||
def: Def::Err,
|
||||
segments: vec![PathSegment {
|
||||
name,
|
||||
params: PathParameters::AngleBracketed {
|
||||
args: GenericArgs::AngleBracketed {
|
||||
lifetimes: Vec::new(),
|
||||
types: Vec::new(),
|
||||
bindings: Vec::new(),
|
||||
|
|
@ -3472,7 +3524,7 @@ impl Clean<Path> for hir::Path {
|
|||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum PathParameters {
|
||||
pub enum GenericArgs {
|
||||
AngleBracketed {
|
||||
lifetimes: Vec<Lifetime>,
|
||||
types: Vec<Type>,
|
||||
|
|
@ -3484,22 +3536,33 @@ pub enum PathParameters {
|
|||
}
|
||||
}
|
||||
|
||||
impl Clean<PathParameters> for hir::PathParameters {
|
||||
fn clean(&self, cx: &DocContext) -> PathParameters {
|
||||
impl Clean<GenericArgs> for hir::GenericArgs {
|
||||
fn clean(&self, cx: &DocContext) -> GenericArgs {
|
||||
if self.parenthesized {
|
||||
let output = self.bindings[0].ty.clean(cx);
|
||||
PathParameters::Parenthesized {
|
||||
GenericArgs::Parenthesized {
|
||||
inputs: self.inputs().clean(cx),
|
||||
output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None }
|
||||
}
|
||||
} else {
|
||||
PathParameters::AngleBracketed {
|
||||
lifetimes: if self.lifetimes.iter().all(|lt| lt.is_elided()) {
|
||||
vec![]
|
||||
} else {
|
||||
self.lifetimes.clean(cx)
|
||||
},
|
||||
types: self.types.clean(cx),
|
||||
let (mut lifetimes, mut types) = (vec![], vec![]);
|
||||
let mut elided_lifetimes = true;
|
||||
for arg in &self.args {
|
||||
match arg {
|
||||
GenericArg::Lifetime(lt) => {
|
||||
if !lt.is_elided() {
|
||||
elided_lifetimes = false;
|
||||
}
|
||||
lifetimes.push(lt.clean(cx));
|
||||
}
|
||||
GenericArg::Type(ty) => {
|
||||
types.push(ty.clean(cx));
|
||||
}
|
||||
}
|
||||
}
|
||||
GenericArgs::AngleBracketed {
|
||||
lifetimes: if elided_lifetimes { vec![] } else { lifetimes },
|
||||
types,
|
||||
bindings: self.bindings.clean(cx),
|
||||
}
|
||||
}
|
||||
|
|
@ -3509,14 +3572,14 @@ impl Clean<PathParameters> for hir::PathParameters {
|
|||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct PathSegment {
|
||||
pub name: String,
|
||||
pub params: PathParameters,
|
||||
pub args: GenericArgs,
|
||||
}
|
||||
|
||||
impl Clean<PathSegment> for hir::PathSegment {
|
||||
fn clean(&self, cx: &DocContext) -> PathSegment {
|
||||
PathSegment {
|
||||
name: self.name.clean(cx),
|
||||
params: self.with_parameters(|parameters| parameters.clean(cx))
|
||||
args: self.with_generic_args(|generic_args| generic_args.clean(cx))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3550,7 +3613,7 @@ fn strip_path(path: &Path) -> Path {
|
|||
let segments = path.segments.iter().map(|s| {
|
||||
PathSegment {
|
||||
name: s.name.clone(),
|
||||
params: PathParameters::AngleBracketed {
|
||||
args: GenericArgs::AngleBracketed {
|
||||
lifetimes: Vec::new(),
|
||||
types: Vec::new(),
|
||||
bindings: Vec::new(),
|
||||
|
|
@ -4365,7 +4428,7 @@ where F: Fn(DefId) -> Def {
|
|||
def: def_ctor(def_id),
|
||||
segments: hir::HirVec::from_vec(apb.names.iter().map(|s| hir::PathSegment {
|
||||
name: ast::Name::intern(&s),
|
||||
parameters: None,
|
||||
args: None,
|
||||
infer_types: false,
|
||||
}).collect())
|
||||
}
|
||||
|
|
@ -4388,8 +4451,8 @@ struct RegionDeps<'tcx> {
|
|||
|
||||
#[derive(Eq, PartialEq, Hash, Debug)]
|
||||
enum SimpleBound {
|
||||
RegionBound(Lifetime),
|
||||
TraitBound(Vec<PathSegment>, Vec<SimpleBound>, Vec<GenericParamDef>, hir::TraitBoundModifier)
|
||||
TraitBound(Vec<PathSegment>, Vec<SimpleBound>, Vec<GenericParamDef>, hir::TraitBoundModifier),
|
||||
Outlives(Lifetime),
|
||||
}
|
||||
|
||||
enum AutoTraitResult {
|
||||
|
|
@ -4407,11 +4470,11 @@ impl AutoTraitResult {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<TyParamBound> for SimpleBound {
|
||||
fn from(bound: TyParamBound) -> Self {
|
||||
impl From<GenericBound> for SimpleBound {
|
||||
fn from(bound: GenericBound) -> Self {
|
||||
match bound.clone() {
|
||||
TyParamBound::RegionBound(l) => SimpleBound::RegionBound(l),
|
||||
TyParamBound::TraitBound(t, mod_) => match t.trait_ {
|
||||
GenericBound::Outlives(l) => SimpleBound::Outlives(l),
|
||||
GenericBound::TraitBound(t, mod_) => match t.trait_ {
|
||||
Type::ResolvedPath { path, typarams, .. } => {
|
||||
SimpleBound::TraitBound(path.segments,
|
||||
typarams
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ use std::collections::BTreeMap;
|
|||
use rustc::hir::def_id::DefId;
|
||||
use rustc::ty;
|
||||
|
||||
use clean::PathParameters as PP;
|
||||
use clean::GenericArgs as PP;
|
||||
use clean::WherePredicate as WP;
|
||||
use clean;
|
||||
use core::DocContext;
|
||||
|
|
@ -83,8 +83,8 @@ pub fn where_clauses(cx: &DocContext, clauses: Vec<WP>) -> Vec<WP> {
|
|||
};
|
||||
!bounds.iter_mut().any(|b| {
|
||||
let trait_ref = match *b {
|
||||
clean::TraitBound(ref mut tr, _) => tr,
|
||||
clean::RegionBound(..) => return false,
|
||||
clean::GenericBound::TraitBound(ref mut tr, _) => tr,
|
||||
clean::GenericBound::Outlives(..) => return false,
|
||||
};
|
||||
let (did, path) = match trait_ref.trait_ {
|
||||
clean::ResolvedPath { did, ref mut path, ..} => (did, path),
|
||||
|
|
@ -97,7 +97,7 @@ pub fn where_clauses(cx: &DocContext, clauses: Vec<WP>) -> Vec<WP> {
|
|||
return false
|
||||
}
|
||||
let last = path.segments.last_mut().unwrap();
|
||||
match last.params {
|
||||
match last.args {
|
||||
PP::AngleBracketed { ref mut bindings, .. } => {
|
||||
bindings.push(clean::TypeBinding {
|
||||
name: name.clone(),
|
||||
|
|
@ -135,14 +135,19 @@ pub fn where_clauses(cx: &DocContext, clauses: Vec<WP>) -> Vec<WP> {
|
|||
clauses
|
||||
}
|
||||
|
||||
pub fn ty_params(mut params: Vec<clean::TyParam>) -> Vec<clean::TyParam> {
|
||||
pub fn ty_params(mut params: Vec<clean::GenericParamDef>) -> Vec<clean::GenericParamDef> {
|
||||
for param in &mut params {
|
||||
param.bounds = ty_bounds(mem::replace(&mut param.bounds, Vec::new()));
|
||||
match param.kind {
|
||||
clean::GenericParamDefKind::Type { ref mut bounds, .. } => {
|
||||
*bounds = ty_bounds(mem::replace(bounds, Vec::new()));
|
||||
}
|
||||
_ => panic!("expected only type parameters"),
|
||||
}
|
||||
}
|
||||
params
|
||||
}
|
||||
|
||||
fn ty_bounds(bounds: Vec<clean::TyParamBound>) -> Vec<clean::TyParamBound> {
|
||||
fn ty_bounds(bounds: Vec<clean::GenericBound>) -> Vec<clean::GenericBound> {
|
||||
bounds
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> {
|
|||
/// Table node id of lifetime parameter definition -> substituted lifetime
|
||||
pub lt_substs: RefCell<FxHashMap<DefId, clean::Lifetime>>,
|
||||
/// Table DefId of `impl Trait` in argument position -> bounds
|
||||
pub impl_trait_bounds: RefCell<FxHashMap<DefId, Vec<clean::TyParamBound>>>,
|
||||
pub impl_trait_bounds: RefCell<FxHashMap<DefId, Vec<clean::GenericBound>>>,
|
||||
pub send_trait: Option<DefId>,
|
||||
pub fake_def_ids: RefCell<FxHashMap<CrateNum, DefId>>,
|
||||
pub all_fake_def_ids: RefCell<FxHashSet<DefId>>,
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ pub struct Trait {
|
|||
pub name: Name,
|
||||
pub items: hir::HirVec<hir::TraitItem>,
|
||||
pub generics: hir::Generics,
|
||||
pub bounds: hir::HirVec<hir::TyParamBound>,
|
||||
pub bounds: hir::HirVec<hir::GenericBound>,
|
||||
pub attrs: hir::HirVec<ast::Attribute>,
|
||||
pub id: ast::NodeId,
|
||||
pub whence: Span,
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ pub struct MutableSpace(pub clean::Mutability);
|
|||
#[derive(Copy, Clone)]
|
||||
pub struct RawMutableSpace(pub clean::Mutability);
|
||||
/// Wrapper struct for emitting type parameter bounds.
|
||||
pub struct TyParamBounds<'a>(pub &'a [clean::TyParamBound]);
|
||||
pub struct GenericBounds<'a>(pub &'a [clean::GenericBound]);
|
||||
/// Wrapper struct for emitting a comma-separated list of items
|
||||
pub struct CommaSep<'a, T: 'a>(pub &'a [T]);
|
||||
pub struct AbiSpace(pub Abi);
|
||||
|
|
@ -104,9 +104,9 @@ impl<'a, T: fmt::Display> fmt::Display for CommaSep<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Display for TyParamBounds<'a> {
|
||||
impl<'a> fmt::Display for GenericBounds<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let &TyParamBounds(bounds) = self;
|
||||
let &GenericBounds(bounds) = self;
|
||||
for (i, bound) in bounds.iter().enumerate() {
|
||||
if i > 0 {
|
||||
f.write_str(" + ")?;
|
||||
|
|
@ -119,20 +119,20 @@ impl<'a> fmt::Display for TyParamBounds<'a> {
|
|||
|
||||
impl fmt::Display for clean::GenericParamDef {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
clean::GenericParamDef::Lifetime(ref lp) => write!(f, "{}", lp),
|
||||
clean::GenericParamDef::Type(ref tp) => {
|
||||
f.write_str(&tp.name)?;
|
||||
match self.kind {
|
||||
clean::GenericParamDefKind::Lifetime => write!(f, "{}", self.name),
|
||||
clean::GenericParamDefKind::Type { ref bounds, ref default, .. } => {
|
||||
f.write_str(&self.name)?;
|
||||
|
||||
if !tp.bounds.is_empty() {
|
||||
if !bounds.is_empty() {
|
||||
if f.alternate() {
|
||||
write!(f, ": {:#}", TyParamBounds(&tp.bounds))?;
|
||||
write!(f, ": {:#}", GenericBounds(bounds))?;
|
||||
} else {
|
||||
write!(f, ": {}", TyParamBounds(&tp.bounds))?;
|
||||
write!(f, ": {}", GenericBounds(bounds))?;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref ty) = tp.default {
|
||||
if let Some(ref ty) = default {
|
||||
if f.alternate() {
|
||||
write!(f, " = {:#}", ty)?;
|
||||
} else {
|
||||
|
|
@ -190,9 +190,9 @@ impl<'a> fmt::Display for WhereClause<'a> {
|
|||
&clean::WherePredicate::BoundPredicate { ref ty, ref bounds } => {
|
||||
let bounds = bounds;
|
||||
if f.alternate() {
|
||||
clause.push_str(&format!("{:#}: {:#}", ty, TyParamBounds(bounds)));
|
||||
clause.push_str(&format!("{:#}: {:#}", ty, GenericBounds(bounds)));
|
||||
} else {
|
||||
clause.push_str(&format!("{}: {}", ty, TyParamBounds(bounds)));
|
||||
clause.push_str(&format!("{}: {}", ty, GenericBounds(bounds)));
|
||||
}
|
||||
}
|
||||
&clean::WherePredicate::RegionPredicate { ref lifetime,
|
||||
|
|
@ -267,13 +267,13 @@ impl fmt::Display for clean::PolyTrait {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for clean::TyParamBound {
|
||||
impl fmt::Display for clean::GenericBound {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
clean::RegionBound(ref lt) => {
|
||||
clean::GenericBound::Outlives(ref lt) => {
|
||||
write!(f, "{}", *lt)
|
||||
}
|
||||
clean::TraitBound(ref ty, modifier) => {
|
||||
clean::GenericBound::TraitBound(ref ty, modifier) => {
|
||||
let modifier_str = match modifier {
|
||||
hir::TraitBoundModifier::None => "",
|
||||
hir::TraitBoundModifier::Maybe => "?",
|
||||
|
|
@ -288,10 +288,10 @@ impl fmt::Display for clean::TyParamBound {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for clean::PathParameters {
|
||||
impl fmt::Display for clean::GenericArgs {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
clean::PathParameters::AngleBracketed {
|
||||
clean::GenericArgs::AngleBracketed {
|
||||
ref lifetimes, ref types, ref bindings
|
||||
} => {
|
||||
if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() {
|
||||
|
|
@ -337,7 +337,7 @@ impl fmt::Display for clean::PathParameters {
|
|||
}
|
||||
}
|
||||
}
|
||||
clean::PathParameters::Parenthesized { ref inputs, ref output } => {
|
||||
clean::GenericArgs::Parenthesized { ref inputs, ref output } => {
|
||||
f.write_str("(")?;
|
||||
let mut comma = false;
|
||||
for ty in inputs {
|
||||
|
|
@ -369,9 +369,9 @@ impl fmt::Display for clean::PathSegment {
|
|||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.write_str(&self.name)?;
|
||||
if f.alternate() {
|
||||
write!(f, "{:#}", self.params)
|
||||
write!(f, "{:#}", self.args)
|
||||
} else {
|
||||
write!(f, "{}", self.params)
|
||||
write!(f, "{}", self.args)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -447,7 +447,7 @@ fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path,
|
|||
}
|
||||
}
|
||||
if w.alternate() {
|
||||
write!(w, "{:#}{:#}", HRef::new(did, &last.name), last.params)?;
|
||||
write!(w, "{:#}{:#}", HRef::new(did, &last.name), last.args)?;
|
||||
} else {
|
||||
let path = if use_absolute {
|
||||
match href(did) {
|
||||
|
|
@ -461,7 +461,7 @@ fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path,
|
|||
} else {
|
||||
format!("{}", HRef::new(did, &last.name))
|
||||
};
|
||||
write!(w, "{}{}", path, last.params)?;
|
||||
write!(w, "{}{}", path, last.args)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -512,7 +512,7 @@ fn primitive_link(f: &mut fmt::Formatter,
|
|||
|
||||
/// Helper to render type parameters
|
||||
fn tybounds(w: &mut fmt::Formatter,
|
||||
typarams: &Option<Vec<clean::TyParamBound>>) -> fmt::Result {
|
||||
typarams: &Option<Vec<clean::GenericBound>>) -> fmt::Result {
|
||||
match *typarams {
|
||||
Some(ref params) => {
|
||||
for param in params {
|
||||
|
|
@ -667,7 +667,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt:
|
|||
}
|
||||
}
|
||||
clean::ImplTrait(ref bounds) => {
|
||||
write!(f, "impl {}", TyParamBounds(bounds))
|
||||
write!(f, "impl {}", GenericBounds(bounds))
|
||||
}
|
||||
clean::QPath { ref name, ref self_type, ref trait_ } => {
|
||||
let should_show_cast = match *trait_ {
|
||||
|
|
@ -757,7 +757,7 @@ fn fmt_impl(i: &clean::Impl,
|
|||
clean::ResolvedPath { typarams: None, ref path, is_generic: false, .. } => {
|
||||
let last = path.segments.last().unwrap();
|
||||
fmt::Display::fmt(&last.name, f)?;
|
||||
fmt::Display::fmt(&last.params, f)?;
|
||||
fmt::Display::fmt(&last.args, f)?;
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ use doctree;
|
|||
use fold::DocFolder;
|
||||
use html::escape::Escape;
|
||||
use html::format::{ConstnessSpace};
|
||||
use html::format::{TyParamBounds, WhereClause, href, AbiSpace};
|
||||
use html::format::{GenericBounds, WhereClause, href, AbiSpace};
|
||||
use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace};
|
||||
use html::format::fmt_impl_for_trait_page;
|
||||
use html::item_type::ItemType;
|
||||
|
|
@ -1453,11 +1453,11 @@ impl DocFolder for Cache {
|
|||
impl<'a> Cache {
|
||||
fn generics(&mut self, generics: &clean::Generics) {
|
||||
for param in &generics.params {
|
||||
match *param {
|
||||
clean::GenericParamDef::Type(ref typ) => {
|
||||
self.typarams.insert(typ.did, typ.name.clone());
|
||||
match param.kind {
|
||||
clean::GenericParamDefKind::Lifetime => {}
|
||||
clean::GenericParamDefKind::Type { did, .. } => {
|
||||
self.typarams.insert(did, param.name.clone());
|
||||
}
|
||||
clean::GenericParamDef::Lifetime(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2960,14 +2960,14 @@ fn assoc_const(w: &mut fmt::Formatter,
|
|||
}
|
||||
|
||||
fn assoc_type<W: fmt::Write>(w: &mut W, it: &clean::Item,
|
||||
bounds: &Vec<clean::TyParamBound>,
|
||||
bounds: &Vec<clean::GenericBound>,
|
||||
default: Option<&clean::Type>,
|
||||
link: AssocItemLink) -> fmt::Result {
|
||||
write!(w, "type <a href='{}' class=\"type\">{}</a>",
|
||||
naive_assoc_href(it, link),
|
||||
it.name.as_ref().unwrap())?;
|
||||
if !bounds.is_empty() {
|
||||
write!(w, ": {}", TyParamBounds(bounds))?
|
||||
write!(w, ": {}", GenericBounds(bounds))?
|
||||
}
|
||||
if let Some(default) = default {
|
||||
write!(w, " = {}", default)?;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#![feature(box_patterns)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(fs_read_write)]
|
||||
#![feature(iterator_find_map)]
|
||||
#![feature(set_stdio)]
|
||||
#![feature(slice_sort_by_cached_key)]
|
||||
#![feature(test)]
|
||||
|
|
|
|||
|
|
@ -10,9 +10,8 @@
|
|||
|
||||
// The Rust abstract syntax tree.
|
||||
|
||||
pub use self::TyParamBound::*;
|
||||
pub use self::UnsafeSource::*;
|
||||
pub use self::PathParameters::*;
|
||||
pub use self::GenericArgs::*;
|
||||
pub use symbol::{Ident, Symbol as Name};
|
||||
pub use util::ThinVec;
|
||||
pub use util::parser::ExprPrecedence;
|
||||
|
|
@ -58,14 +57,6 @@ impl fmt::Debug for Lifetime {
|
|||
}
|
||||
}
|
||||
|
||||
/// A lifetime definition, e.g. `'a: 'b+'c+'d`
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub struct LifetimeDef {
|
||||
pub attrs: ThinVec<Attribute>,
|
||||
pub lifetime: Lifetime,
|
||||
pub bounds: Vec<Lifetime>
|
||||
}
|
||||
|
||||
/// A "Path" is essentially Rust's notion of a name.
|
||||
///
|
||||
/// It's represented as a sequence of identifiers,
|
||||
|
|
@ -135,30 +126,30 @@ pub struct PathSegment {
|
|||
/// `Some` means that parameter list is supplied (`Path<X, Y>`)
|
||||
/// but it can be empty (`Path<>`).
|
||||
/// `P` is used as a size optimization for the common case with no parameters.
|
||||
pub parameters: Option<P<PathParameters>>,
|
||||
pub args: Option<P<GenericArgs>>,
|
||||
}
|
||||
|
||||
impl PathSegment {
|
||||
pub fn from_ident(ident: Ident) -> Self {
|
||||
PathSegment { ident, parameters: None }
|
||||
PathSegment { ident, args: None }
|
||||
}
|
||||
pub fn crate_root(span: Span) -> Self {
|
||||
PathSegment::from_ident(Ident::new(keywords::CrateRoot.name(), span))
|
||||
}
|
||||
}
|
||||
|
||||
/// Parameters of a path segment.
|
||||
/// Arguments of a path segment.
|
||||
///
|
||||
/// E.g. `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub enum PathParameters {
|
||||
pub enum GenericArgs {
|
||||
/// The `<'a, A,B,C>` in `foo::bar::baz::<'a, A,B,C>`
|
||||
AngleBracketed(AngleBracketedParameterData),
|
||||
AngleBracketed(AngleBracketedArgs),
|
||||
/// The `(A,B)` and `C` in `Foo(A,B) -> C`
|
||||
Parenthesized(ParenthesizedParameterData),
|
||||
Parenthesized(ParenthesisedArgs),
|
||||
}
|
||||
|
||||
impl PathParameters {
|
||||
impl GenericArgs {
|
||||
pub fn span(&self) -> Span {
|
||||
match *self {
|
||||
AngleBracketed(ref data) => data.span,
|
||||
|
|
@ -167,36 +158,40 @@ impl PathParameters {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub enum GenericArg {
|
||||
Lifetime(Lifetime),
|
||||
Type(P<Ty>),
|
||||
}
|
||||
|
||||
/// A path like `Foo<'a, T>`
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Default)]
|
||||
pub struct AngleBracketedParameterData {
|
||||
pub struct AngleBracketedArgs {
|
||||
/// Overall span
|
||||
pub span: Span,
|
||||
/// The lifetime parameters for this path segment.
|
||||
pub lifetimes: Vec<Lifetime>,
|
||||
/// The type parameters for this path segment, if present.
|
||||
pub types: Vec<P<Ty>>,
|
||||
/// The arguments for this path segment.
|
||||
pub args: Vec<GenericArg>,
|
||||
/// Bindings (equality constraints) on associated types, if present.
|
||||
///
|
||||
/// E.g., `Foo<A=Bar>`.
|
||||
pub bindings: Vec<TypeBinding>,
|
||||
}
|
||||
|
||||
impl Into<Option<P<PathParameters>>> for AngleBracketedParameterData {
|
||||
fn into(self) -> Option<P<PathParameters>> {
|
||||
Some(P(PathParameters::AngleBracketed(self)))
|
||||
impl Into<Option<P<GenericArgs>>> for AngleBracketedArgs {
|
||||
fn into(self) -> Option<P<GenericArgs>> {
|
||||
Some(P(GenericArgs::AngleBracketed(self)))
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Option<P<PathParameters>>> for ParenthesizedParameterData {
|
||||
fn into(self) -> Option<P<PathParameters>> {
|
||||
Some(P(PathParameters::Parenthesized(self)))
|
||||
impl Into<Option<P<GenericArgs>>> for ParenthesisedArgs {
|
||||
fn into(self) -> Option<P<GenericArgs>> {
|
||||
Some(P(GenericArgs::Parenthesized(self)))
|
||||
}
|
||||
}
|
||||
|
||||
/// A path like `Foo(A,B) -> C`
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub struct ParenthesizedParameterData {
|
||||
pub struct ParenthesisedArgs {
|
||||
/// Overall span
|
||||
pub span: Span,
|
||||
|
||||
|
|
@ -273,25 +268,6 @@ pub const CRATE_NODE_ID: NodeId = NodeId(0);
|
|||
/// small, positive ids.
|
||||
pub const DUMMY_NODE_ID: NodeId = NodeId(!0);
|
||||
|
||||
/// The AST represents all type param bounds as types.
|
||||
/// typeck::collect::compute_bounds matches these against
|
||||
/// the "special" built-in traits (see middle::lang_items) and
|
||||
/// detects Copy, Send and Sync.
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub enum TyParamBound {
|
||||
TraitTyParamBound(PolyTraitRef, TraitBoundModifier),
|
||||
RegionTyParamBound(Lifetime)
|
||||
}
|
||||
|
||||
impl TyParamBound {
|
||||
pub fn span(&self) -> Span {
|
||||
match self {
|
||||
&TraitTyParamBound(ref t, ..) => t.span,
|
||||
&RegionTyParamBound(ref l) => l.ident.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A modifier on a bound, currently this is only used for `?Sized`, where the
|
||||
/// modifier is `Maybe`. Negative bounds should also be handled here.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
|
|
@ -300,37 +276,44 @@ pub enum TraitBoundModifier {
|
|||
Maybe,
|
||||
}
|
||||
|
||||
pub type TyParamBounds = Vec<TyParamBound>;
|
||||
/// The AST represents all type param bounds as types.
|
||||
/// typeck::collect::compute_bounds matches these against
|
||||
/// the "special" built-in traits (see middle::lang_items) and
|
||||
/// detects Copy, Send and Sync.
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub enum GenericBound {
|
||||
Trait(PolyTraitRef, TraitBoundModifier),
|
||||
Outlives(Lifetime)
|
||||
}
|
||||
|
||||
impl GenericBound {
|
||||
pub fn span(&self) -> Span {
|
||||
match self {
|
||||
&GenericBound::Trait(ref t, ..) => t.span,
|
||||
&GenericBound::Outlives(ref l) => l.ident.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type GenericBounds = Vec<GenericBound>;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub struct TyParam {
|
||||
pub attrs: ThinVec<Attribute>,
|
||||
pub ident: Ident,
|
||||
pub enum GenericParamKind {
|
||||
/// A lifetime definition, e.g. `'a: 'b+'c+'d`.
|
||||
Lifetime,
|
||||
Type {
|
||||
default: Option<P<Ty>>,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub struct GenericParam {
|
||||
pub id: NodeId,
|
||||
pub bounds: TyParamBounds,
|
||||
pub default: Option<P<Ty>>,
|
||||
}
|
||||
pub ident: Ident,
|
||||
pub attrs: ThinVec<Attribute>,
|
||||
pub bounds: GenericBounds,
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub enum GenericParam {
|
||||
Lifetime(LifetimeDef),
|
||||
Type(TyParam),
|
||||
}
|
||||
|
||||
impl GenericParam {
|
||||
pub fn is_lifetime_param(&self) -> bool {
|
||||
match *self {
|
||||
GenericParam::Lifetime(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_type_param(&self) -> bool {
|
||||
match *self {
|
||||
GenericParam::Type(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
pub kind: GenericParamKind,
|
||||
}
|
||||
|
||||
/// Represents lifetime, type and const parameters attached to a declaration of
|
||||
|
|
@ -342,31 +325,6 @@ pub struct Generics {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
impl Generics {
|
||||
pub fn is_lt_parameterized(&self) -> bool {
|
||||
self.params.iter().any(|param| param.is_lifetime_param())
|
||||
}
|
||||
|
||||
pub fn is_type_parameterized(&self) -> bool {
|
||||
self.params.iter().any(|param| param.is_type_param())
|
||||
}
|
||||
|
||||
pub fn is_parameterized(&self) -> bool {
|
||||
!self.params.is_empty()
|
||||
}
|
||||
|
||||
pub fn span_for_name(&self, name: &str) -> Option<Span> {
|
||||
for param in &self.params {
|
||||
if let GenericParam::Type(ref t) = *param {
|
||||
if t.ident.name == name {
|
||||
return Some(t.ident.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Generics {
|
||||
/// Creates an instance of `Generics`.
|
||||
fn default() -> Generics {
|
||||
|
|
@ -422,7 +380,7 @@ pub struct WhereBoundPredicate {
|
|||
/// The type being bounded
|
||||
pub bounded_ty: P<Ty>,
|
||||
/// Trait and lifetime bounds (`Clone+Send+'static`)
|
||||
pub bounds: TyParamBounds,
|
||||
pub bounds: GenericBounds,
|
||||
}
|
||||
|
||||
/// A lifetime predicate.
|
||||
|
|
@ -432,7 +390,7 @@ pub struct WhereBoundPredicate {
|
|||
pub struct WhereRegionPredicate {
|
||||
pub span: Span,
|
||||
pub lifetime: Lifetime,
|
||||
pub bounds: Vec<Lifetime>,
|
||||
pub bounds: GenericBounds,
|
||||
}
|
||||
|
||||
/// An equality predicate (unsupported).
|
||||
|
|
@ -968,11 +926,11 @@ impl Expr {
|
|||
}
|
||||
}
|
||||
|
||||
fn to_bound(&self) -> Option<TyParamBound> {
|
||||
fn to_bound(&self) -> Option<GenericBound> {
|
||||
match &self.node {
|
||||
ExprKind::Path(None, path) =>
|
||||
Some(TraitTyParamBound(PolyTraitRef::new(Vec::new(), path.clone(), self.span),
|
||||
TraitBoundModifier::None)),
|
||||
Some(GenericBound::Trait(PolyTraitRef::new(Vec::new(), path.clone(), self.span),
|
||||
TraitBoundModifier::None)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -1393,7 +1351,7 @@ pub struct TraitItem {
|
|||
pub enum TraitItemKind {
|
||||
Const(P<Ty>, Option<P<Expr>>),
|
||||
Method(MethodSig, Option<P<Block>>),
|
||||
Type(TyParamBounds, Option<P<Ty>>),
|
||||
Type(GenericBounds, Option<P<Ty>>),
|
||||
Macro(Mac),
|
||||
}
|
||||
|
||||
|
|
@ -1578,10 +1536,10 @@ pub enum TyKind {
|
|||
Path(Option<QSelf>, Path),
|
||||
/// A trait object type `Bound1 + Bound2 + Bound3`
|
||||
/// where `Bound` is a trait or a lifetime.
|
||||
TraitObject(TyParamBounds, TraitObjectSyntax),
|
||||
TraitObject(GenericBounds, TraitObjectSyntax),
|
||||
/// An `impl Bound1 + Bound2 + Bound3` type
|
||||
/// where `Bound` is a trait or a lifetime.
|
||||
ImplTrait(TyParamBounds),
|
||||
ImplTrait(GenericBounds),
|
||||
/// No-op; kept solely so that we can pretty-print faithfully
|
||||
Paren(P<Ty>),
|
||||
/// Unused for now
|
||||
|
|
@ -2102,11 +2060,11 @@ pub enum ItemKind {
|
|||
/// A Trait declaration (`trait` or `pub trait`).
|
||||
///
|
||||
/// E.g. `trait Foo { .. }`, `trait Foo<T> { .. }` or `auto trait Foo {}`
|
||||
Trait(IsAuto, Unsafety, Generics, TyParamBounds, Vec<TraitItem>),
|
||||
Trait(IsAuto, Unsafety, Generics, GenericBounds, Vec<TraitItem>),
|
||||
/// Trait alias
|
||||
///
|
||||
/// E.g. `trait Foo = Bar + Quux;`
|
||||
TraitAlias(Generics, TyParamBounds),
|
||||
TraitAlias(Generics, GenericBounds),
|
||||
/// An implementation.
|
||||
///
|
||||
/// E.g. `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`
|
||||
|
|
|
|||
|
|
@ -1446,17 +1446,12 @@ impl HasAttrs for Stmt {
|
|||
|
||||
impl HasAttrs for GenericParam {
|
||||
fn attrs(&self) -> &[ast::Attribute] {
|
||||
match self {
|
||||
GenericParam::Lifetime(lifetime) => lifetime.attrs(),
|
||||
GenericParam::Type(ty) => ty.attrs(),
|
||||
}
|
||||
&self.attrs
|
||||
}
|
||||
|
||||
fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self {
|
||||
match self {
|
||||
GenericParam::Lifetime(lifetime) => GenericParam::Lifetime(lifetime.map_attrs(f)),
|
||||
GenericParam::Type(ty) => GenericParam::Type(ty.map_attrs(f)),
|
||||
}
|
||||
fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(mut self, f: F) -> Self {
|
||||
self.attrs = self.attrs.map_attrs(f);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1479,5 +1474,5 @@ macro_rules! derive_has_attrs {
|
|||
|
||||
derive_has_attrs! {
|
||||
Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::ImplItem, ast::TraitItem, ast::Arm,
|
||||
ast::Field, ast::FieldPat, ast::Variant_, ast::LifetimeDef, ast::TyParam
|
||||
ast::Field, ast::FieldPat, ast::Variant_
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,10 +30,9 @@ pub trait AstBuilder {
|
|||
fn path_global(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path;
|
||||
fn path_all(&self, sp: Span,
|
||||
global: bool,
|
||||
idents: Vec<ast::Ident> ,
|
||||
lifetimes: Vec<ast::Lifetime>,
|
||||
types: Vec<P<ast::Ty>>,
|
||||
bindings: Vec<ast::TypeBinding> )
|
||||
idents: Vec<ast::Ident>,
|
||||
args: Vec<ast::GenericArg>,
|
||||
bindings: Vec<ast::TypeBinding>)
|
||||
-> ast::Path;
|
||||
|
||||
fn qpath(&self, self_type: P<ast::Ty>,
|
||||
|
|
@ -43,8 +42,7 @@ pub trait AstBuilder {
|
|||
fn qpath_all(&self, self_type: P<ast::Ty>,
|
||||
trait_path: ast::Path,
|
||||
ident: ast::Ident,
|
||||
lifetimes: Vec<ast::Lifetime>,
|
||||
types: Vec<P<ast::Ty>>,
|
||||
args: Vec<ast::GenericArg>,
|
||||
bindings: Vec<ast::TypeBinding>)
|
||||
-> (ast::QSelf, ast::Path);
|
||||
|
||||
|
|
@ -70,19 +68,19 @@ pub trait AstBuilder {
|
|||
span: Span,
|
||||
id: ast::Ident,
|
||||
attrs: Vec<ast::Attribute>,
|
||||
bounds: ast::TyParamBounds,
|
||||
default: Option<P<ast::Ty>>) -> ast::TyParam;
|
||||
bounds: ast::GenericBounds,
|
||||
default: Option<P<ast::Ty>>) -> ast::GenericParam;
|
||||
|
||||
fn trait_ref(&self, path: ast::Path) -> ast::TraitRef;
|
||||
fn poly_trait_ref(&self, span: Span, path: ast::Path) -> ast::PolyTraitRef;
|
||||
fn typarambound(&self, path: ast::Path) -> ast::TyParamBound;
|
||||
fn trait_bound(&self, path: ast::Path) -> ast::GenericBound;
|
||||
fn lifetime(&self, span: Span, ident: ast::Ident) -> ast::Lifetime;
|
||||
fn lifetime_def(&self,
|
||||
span: Span,
|
||||
ident: ast::Ident,
|
||||
attrs: Vec<ast::Attribute>,
|
||||
bounds: Vec<ast::Lifetime>)
|
||||
-> ast::LifetimeDef;
|
||||
bounds: ast::GenericBounds)
|
||||
-> ast::GenericParam;
|
||||
|
||||
// statements
|
||||
fn stmt_expr(&self, expr: P<ast::Expr>) -> ast::Stmt;
|
||||
|
|
@ -304,34 +302,33 @@ pub trait AstBuilder {
|
|||
|
||||
impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||
fn path(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path {
|
||||
self.path_all(span, false, strs, Vec::new(), Vec::new(), Vec::new())
|
||||
self.path_all(span, false, strs, vec![], vec![])
|
||||
}
|
||||
fn path_ident(&self, span: Span, id: ast::Ident) -> ast::Path {
|
||||
self.path(span, vec![id])
|
||||
}
|
||||
fn path_global(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path {
|
||||
self.path_all(span, true, strs, Vec::new(), Vec::new(), Vec::new())
|
||||
self.path_all(span, true, strs, vec![], vec![])
|
||||
}
|
||||
fn path_all(&self,
|
||||
span: Span,
|
||||
global: bool,
|
||||
mut idents: Vec<ast::Ident> ,
|
||||
lifetimes: Vec<ast::Lifetime>,
|
||||
types: Vec<P<ast::Ty>>,
|
||||
args: Vec<ast::GenericArg>,
|
||||
bindings: Vec<ast::TypeBinding> )
|
||||
-> ast::Path {
|
||||
let last_ident = idents.pop().unwrap();
|
||||
let mut segments: Vec<ast::PathSegment> = Vec::new();
|
||||
let mut segments: Vec<ast::PathSegment> = vec![];
|
||||
|
||||
segments.extend(idents.into_iter().map(|ident| {
|
||||
ast::PathSegment::from_ident(ident.with_span_pos(span))
|
||||
}));
|
||||
let parameters = if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() {
|
||||
ast::AngleBracketedParameterData { lifetimes, types, bindings, span }.into()
|
||||
let args = if !args.is_empty() || !bindings.is_empty() {
|
||||
ast::AngleBracketedArgs { args, bindings, span }.into()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
segments.push(ast::PathSegment { ident: last_ident.with_span_pos(span), parameters });
|
||||
segments.push(ast::PathSegment { ident: last_ident.with_span_pos(span), args });
|
||||
let mut path = ast::Path { span, segments };
|
||||
if global {
|
||||
if let Some(seg) = path.make_root() {
|
||||
|
|
@ -349,7 +346,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
|||
trait_path: ast::Path,
|
||||
ident: ast::Ident)
|
||||
-> (ast::QSelf, ast::Path) {
|
||||
self.qpath_all(self_type, trait_path, ident, vec![], vec![], vec![])
|
||||
self.qpath_all(self_type, trait_path, ident, vec![], vec![])
|
||||
}
|
||||
|
||||
/// Constructs a qualified path.
|
||||
|
|
@ -359,17 +356,16 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
|||
self_type: P<ast::Ty>,
|
||||
trait_path: ast::Path,
|
||||
ident: ast::Ident,
|
||||
lifetimes: Vec<ast::Lifetime>,
|
||||
types: Vec<P<ast::Ty>>,
|
||||
args: Vec<ast::GenericArg>,
|
||||
bindings: Vec<ast::TypeBinding>)
|
||||
-> (ast::QSelf, ast::Path) {
|
||||
let mut path = trait_path;
|
||||
let parameters = if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() {
|
||||
ast::AngleBracketedParameterData { lifetimes, types, bindings, span: ident.span }.into()
|
||||
let args = if !args.is_empty() || !bindings.is_empty() {
|
||||
ast::AngleBracketedArgs { args, bindings, span: ident.span }.into()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
path.segments.push(ast::PathSegment { ident, parameters });
|
||||
path.segments.push(ast::PathSegment { ident, args });
|
||||
|
||||
(ast::QSelf {
|
||||
ty: self_type,
|
||||
|
|
@ -428,8 +424,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
|||
self.path_all(DUMMY_SP,
|
||||
true,
|
||||
self.std_path(&["option", "Option"]),
|
||||
Vec::new(),
|
||||
vec![ ty ],
|
||||
vec![ast::GenericArg::Type(ty)],
|
||||
Vec::new()))
|
||||
}
|
||||
|
||||
|
|
@ -441,14 +436,16 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
|||
span: Span,
|
||||
ident: ast::Ident,
|
||||
attrs: Vec<ast::Attribute>,
|
||||
bounds: ast::TyParamBounds,
|
||||
default: Option<P<ast::Ty>>) -> ast::TyParam {
|
||||
ast::TyParam {
|
||||
bounds: ast::GenericBounds,
|
||||
default: Option<P<ast::Ty>>) -> ast::GenericParam {
|
||||
ast::GenericParam {
|
||||
ident: ident.with_span_pos(span),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
attrs: attrs.into(),
|
||||
bounds,
|
||||
default,
|
||||
kind: ast::GenericParamKind::Type {
|
||||
default,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -467,8 +464,9 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn typarambound(&self, path: ast::Path) -> ast::TyParamBound {
|
||||
ast::TraitTyParamBound(self.poly_trait_ref(path.span, path), ast::TraitBoundModifier::None)
|
||||
fn trait_bound(&self, path: ast::Path) -> ast::GenericBound {
|
||||
ast::GenericBound::Trait(self.poly_trait_ref(path.span, path),
|
||||
ast::TraitBoundModifier::None)
|
||||
}
|
||||
|
||||
fn lifetime(&self, span: Span, ident: ast::Ident) -> ast::Lifetime {
|
||||
|
|
@ -479,12 +477,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
|||
span: Span,
|
||||
ident: ast::Ident,
|
||||
attrs: Vec<ast::Attribute>,
|
||||
bounds: Vec<ast::Lifetime>)
|
||||
-> ast::LifetimeDef {
|
||||
ast::LifetimeDef {
|
||||
bounds: ast::GenericBounds)
|
||||
-> ast::GenericParam {
|
||||
let lifetime = self.lifetime(span, ident);
|
||||
ast::GenericParam {
|
||||
ident: lifetime.ident,
|
||||
id: lifetime.id,
|
||||
attrs: attrs.into(),
|
||||
lifetime: self.lifetime(span, ident),
|
||||
bounds,
|
||||
kind: ast::GenericParamKind::Lifetime,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1797,7 +1797,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
gate_feature_post!(&self, associated_type_defaults, ti.span,
|
||||
"associated type defaults are unstable");
|
||||
}
|
||||
if ti.generics.is_parameterized() {
|
||||
if !ti.generics.params.is_empty() {
|
||||
gate_feature_post!(&self, generic_associated_types, ti.span,
|
||||
"generic associated types are unstable");
|
||||
}
|
||||
|
|
@ -1824,7 +1824,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
|
||||
}
|
||||
}
|
||||
ast::ImplItemKind::Type(_) if ii.generics.is_parameterized() => {
|
||||
ast::ImplItemKind::Type(_) if !ii.generics.params.is_empty() => {
|
||||
gate_feature_post!(&self, generic_associated_types, ii.span,
|
||||
"generic associated types are unstable");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,10 +132,21 @@ pub trait Folder : Sized {
|
|||
noop_fold_exprs(es, self)
|
||||
}
|
||||
|
||||
fn fold_generic_arg(&mut self, arg: GenericArg) -> GenericArg {
|
||||
match arg {
|
||||
GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.fold_lifetime(lt)),
|
||||
GenericArg::Type(ty) => GenericArg::Type(self.fold_ty(ty)),
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, t: P<Ty>) -> P<Ty> {
|
||||
noop_fold_ty(t, self)
|
||||
}
|
||||
|
||||
fn fold_lifetime(&mut self, l: Lifetime) -> Lifetime {
|
||||
noop_fold_lifetime(l, self)
|
||||
}
|
||||
|
||||
fn fold_ty_binding(&mut self, t: TypeBinding) -> TypeBinding {
|
||||
noop_fold_ty_binding(t, self)
|
||||
}
|
||||
|
|
@ -172,18 +183,18 @@ pub trait Folder : Sized {
|
|||
noop_fold_qpath(qs, p, self)
|
||||
}
|
||||
|
||||
fn fold_path_parameters(&mut self, p: PathParameters) -> PathParameters {
|
||||
noop_fold_path_parameters(p, self)
|
||||
fn fold_generic_args(&mut self, p: GenericArgs) -> GenericArgs {
|
||||
noop_fold_generic_args(p, self)
|
||||
}
|
||||
|
||||
fn fold_angle_bracketed_parameter_data(&mut self, p: AngleBracketedParameterData)
|
||||
-> AngleBracketedParameterData
|
||||
fn fold_angle_bracketed_parameter_data(&mut self, p: AngleBracketedArgs)
|
||||
-> AngleBracketedArgs
|
||||
{
|
||||
noop_fold_angle_bracketed_parameter_data(p, self)
|
||||
}
|
||||
|
||||
fn fold_parenthesized_parameter_data(&mut self, p: ParenthesizedParameterData)
|
||||
-> ParenthesizedParameterData
|
||||
fn fold_parenthesized_parameter_data(&mut self, p: ParenthesisedArgs)
|
||||
-> ParenthesisedArgs
|
||||
{
|
||||
noop_fold_parenthesized_parameter_data(p, self)
|
||||
}
|
||||
|
|
@ -233,10 +244,6 @@ pub trait Folder : Sized {
|
|||
noop_fold_variant_data(vdata, self)
|
||||
}
|
||||
|
||||
fn fold_ty_param(&mut self, tp: TyParam) -> TyParam {
|
||||
noop_fold_ty_param(tp, self)
|
||||
}
|
||||
|
||||
fn fold_generic_param(&mut self, param: GenericParam) -> GenericParam {
|
||||
noop_fold_generic_param(param, self)
|
||||
}
|
||||
|
|
@ -261,18 +268,16 @@ pub trait Folder : Sized {
|
|||
noop_fold_interpolated(nt, self)
|
||||
}
|
||||
|
||||
fn fold_opt_bounds(&mut self, b: Option<TyParamBounds>)
|
||||
-> Option<TyParamBounds> {
|
||||
fn fold_opt_bounds(&mut self, b: Option<GenericBounds>) -> Option<GenericBounds> {
|
||||
noop_fold_opt_bounds(b, self)
|
||||
}
|
||||
|
||||
fn fold_bounds(&mut self, b: TyParamBounds)
|
||||
-> TyParamBounds {
|
||||
fn fold_bounds(&mut self, b: GenericBounds) -> GenericBounds {
|
||||
noop_fold_bounds(b, self)
|
||||
}
|
||||
|
||||
fn fold_ty_param_bound(&mut self, tpb: TyParamBound) -> TyParamBound {
|
||||
noop_fold_ty_param_bound(tpb, self)
|
||||
fn fold_param_bound(&mut self, tpb: GenericBound) -> GenericBound {
|
||||
noop_fold_param_bound(tpb, self)
|
||||
}
|
||||
|
||||
fn fold_mt(&mut self, mt: MutTy) -> MutTy {
|
||||
|
|
@ -385,10 +390,10 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
|
|||
TyKind::Typeof(fld.fold_anon_const(expr))
|
||||
}
|
||||
TyKind::TraitObject(bounds, syntax) => {
|
||||
TyKind::TraitObject(bounds.move_map(|b| fld.fold_ty_param_bound(b)), syntax)
|
||||
TyKind::TraitObject(bounds.move_map(|b| fld.fold_param_bound(b)), syntax)
|
||||
}
|
||||
TyKind::ImplTrait(bounds) => {
|
||||
TyKind::ImplTrait(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
|
||||
TyKind::ImplTrait(bounds.move_map(|b| fld.fold_param_bound(b)))
|
||||
}
|
||||
TyKind::Mac(mac) => {
|
||||
TyKind::Mac(fld.fold_mac(mac))
|
||||
|
|
@ -433,9 +438,9 @@ pub fn noop_fold_usize<T: Folder>(i: usize, _: &mut T) -> usize {
|
|||
|
||||
pub fn noop_fold_path<T: Folder>(Path { segments, span }: Path, fld: &mut T) -> Path {
|
||||
Path {
|
||||
segments: segments.move_map(|PathSegment {ident, parameters}| PathSegment {
|
||||
segments: segments.move_map(|PathSegment { ident, args }| PathSegment {
|
||||
ident: fld.fold_ident(ident),
|
||||
parameters: parameters.map(|ps| ps.map(|ps| fld.fold_path_parameters(ps))),
|
||||
args: args.map(|args| args.map(|args| fld.fold_generic_args(args))),
|
||||
}),
|
||||
span: fld.new_span(span)
|
||||
}
|
||||
|
|
@ -454,36 +459,40 @@ pub fn noop_fold_qpath<T: Folder>(qself: Option<QSelf>,
|
|||
(qself, fld.fold_path(path))
|
||||
}
|
||||
|
||||
pub fn noop_fold_path_parameters<T: Folder>(path_parameters: PathParameters, fld: &mut T)
|
||||
-> PathParameters
|
||||
pub fn noop_fold_generic_args<T: Folder>(generic_args: GenericArgs, fld: &mut T) -> GenericArgs
|
||||
{
|
||||
match path_parameters {
|
||||
PathParameters::AngleBracketed(data) =>
|
||||
PathParameters::AngleBracketed(fld.fold_angle_bracketed_parameter_data(data)),
|
||||
PathParameters::Parenthesized(data) =>
|
||||
PathParameters::Parenthesized(fld.fold_parenthesized_parameter_data(data)),
|
||||
match generic_args {
|
||||
GenericArgs::AngleBracketed(data) => {
|
||||
GenericArgs::AngleBracketed(fld.fold_angle_bracketed_parameter_data(data))
|
||||
}
|
||||
GenericArgs::Parenthesized(data) => {
|
||||
GenericArgs::Parenthesized(fld.fold_parenthesized_parameter_data(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn noop_fold_angle_bracketed_parameter_data<T: Folder>(data: AngleBracketedParameterData,
|
||||
pub fn noop_fold_angle_bracketed_parameter_data<T: Folder>(data: AngleBracketedArgs,
|
||||
fld: &mut T)
|
||||
-> AngleBracketedParameterData
|
||||
-> AngleBracketedArgs
|
||||
{
|
||||
let AngleBracketedParameterData { lifetimes, types, bindings, span } = data;
|
||||
AngleBracketedParameterData { lifetimes: lifetimes.move_map(|l| noop_fold_lifetime(l, fld)),
|
||||
types: types.move_map(|ty| fld.fold_ty(ty)),
|
||||
bindings: bindings.move_map(|b| fld.fold_ty_binding(b)),
|
||||
span: fld.new_span(span) }
|
||||
let AngleBracketedArgs { args, bindings, span } = data;
|
||||
AngleBracketedArgs {
|
||||
args: args.move_map(|arg| fld.fold_generic_arg(arg)),
|
||||
bindings: bindings.move_map(|b| fld.fold_ty_binding(b)),
|
||||
span: fld.new_span(span)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn noop_fold_parenthesized_parameter_data<T: Folder>(data: ParenthesizedParameterData,
|
||||
pub fn noop_fold_parenthesized_parameter_data<T: Folder>(data: ParenthesisedArgs,
|
||||
fld: &mut T)
|
||||
-> ParenthesizedParameterData
|
||||
-> ParenthesisedArgs
|
||||
{
|
||||
let ParenthesizedParameterData { inputs, output, span } = data;
|
||||
ParenthesizedParameterData { inputs: inputs.move_map(|ty| fld.fold_ty(ty)),
|
||||
output: output.map(|ty| fld.fold_ty(ty)),
|
||||
span: fld.new_span(span) }
|
||||
let ParenthesisedArgs { inputs, output, span } = data;
|
||||
ParenthesisedArgs {
|
||||
inputs: inputs.move_map(|ty| fld.fold_ty(ty)),
|
||||
output: output.map(|ty| fld.fold_ty(ty)),
|
||||
span: fld.new_span(span)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn noop_fold_local<T: Folder>(l: P<Local>, fld: &mut T) -> P<Local> {
|
||||
|
|
@ -667,47 +676,33 @@ pub fn noop_fold_fn_decl<T: Folder>(decl: P<FnDecl>, fld: &mut T) -> P<FnDecl> {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn noop_fold_ty_param_bound<T>(tpb: TyParamBound, fld: &mut T)
|
||||
-> TyParamBound
|
||||
where T: Folder {
|
||||
match tpb {
|
||||
TraitTyParamBound(ty, modifier) => TraitTyParamBound(fld.fold_poly_trait_ref(ty), modifier),
|
||||
RegionTyParamBound(lifetime) => RegionTyParamBound(noop_fold_lifetime(lifetime, fld)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn noop_fold_ty_param<T: Folder>(tp: TyParam, fld: &mut T) -> TyParam {
|
||||
let TyParam {attrs, id, ident, bounds, default} = tp;
|
||||
let attrs: Vec<_> = attrs.into();
|
||||
TyParam {
|
||||
attrs: attrs.into_iter()
|
||||
.flat_map(|x| fld.fold_attribute(x).into_iter())
|
||||
.collect::<Vec<_>>()
|
||||
.into(),
|
||||
id: fld.new_id(id),
|
||||
ident: fld.fold_ident(ident),
|
||||
bounds: fld.fold_bounds(bounds),
|
||||
default: default.map(|x| fld.fold_ty(x)),
|
||||
pub fn noop_fold_param_bound<T>(pb: GenericBound, fld: &mut T) -> GenericBound where T: Folder {
|
||||
match pb {
|
||||
GenericBound::Trait(ty, modifier) => {
|
||||
GenericBound::Trait(fld.fold_poly_trait_ref(ty), modifier)
|
||||
}
|
||||
GenericBound::Outlives(lifetime) => {
|
||||
GenericBound::Outlives(noop_fold_lifetime(lifetime, fld))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn noop_fold_generic_param<T: Folder>(param: GenericParam, fld: &mut T) -> GenericParam {
|
||||
match param {
|
||||
GenericParam::Lifetime(l) => {
|
||||
let attrs: Vec<_> = l.attrs.into();
|
||||
GenericParam::Lifetime(LifetimeDef {
|
||||
attrs: attrs.into_iter()
|
||||
let attrs: Vec<_> = param.attrs.into();
|
||||
GenericParam {
|
||||
ident: fld.fold_ident(param.ident),
|
||||
id: fld.new_id(param.id),
|
||||
attrs: attrs.into_iter()
|
||||
.flat_map(|x| fld.fold_attribute(x).into_iter())
|
||||
.collect::<Vec<_>>()
|
||||
.into(),
|
||||
lifetime: Lifetime {
|
||||
id: fld.new_id(l.lifetime.id),
|
||||
ident: fld.fold_ident(l.lifetime.ident),
|
||||
},
|
||||
bounds: l.bounds.move_map(|l| noop_fold_lifetime(l, fld)),
|
||||
})
|
||||
bounds: param.bounds.move_map(|l| noop_fold_param_bound(l, fld)),
|
||||
kind: match param.kind {
|
||||
GenericParamKind::Lifetime => GenericParamKind::Lifetime,
|
||||
GenericParamKind::Type { default } => GenericParamKind::Type {
|
||||
default: default.map(|ty| fld.fold_ty(ty))
|
||||
}
|
||||
}
|
||||
GenericParam::Type(t) => GenericParam::Type(fld.fold_ty_param(t)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -765,7 +760,7 @@ pub fn noop_fold_where_predicate<T: Folder>(
|
|||
ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
|
||||
bound_generic_params: fld.fold_generic_params(bound_generic_params),
|
||||
bounded_ty: fld.fold_ty(bounded_ty),
|
||||
bounds: bounds.move_map(|x| fld.fold_ty_param_bound(x)),
|
||||
bounds: bounds.move_map(|x| fld.fold_param_bound(x)),
|
||||
span: fld.new_span(span)
|
||||
})
|
||||
}
|
||||
|
|
@ -775,7 +770,7 @@ pub fn noop_fold_where_predicate<T: Folder>(
|
|||
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
|
||||
span: fld.new_span(span),
|
||||
lifetime: noop_fold_lifetime(lifetime, fld),
|
||||
bounds: bounds.move_map(|bound| noop_fold_lifetime(bound, fld))
|
||||
bounds: bounds.move_map(|bound| noop_fold_param_bound(bound, fld))
|
||||
})
|
||||
}
|
||||
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id,
|
||||
|
|
@ -854,14 +849,14 @@ pub fn noop_fold_mt<T: Folder>(MutTy {ty, mutbl}: MutTy, folder: &mut T) -> MutT
|
|||
}
|
||||
}
|
||||
|
||||
pub fn noop_fold_opt_bounds<T: Folder>(b: Option<TyParamBounds>, folder: &mut T)
|
||||
-> Option<TyParamBounds> {
|
||||
pub fn noop_fold_opt_bounds<T: Folder>(b: Option<GenericBounds>, folder: &mut T)
|
||||
-> Option<GenericBounds> {
|
||||
b.map(|bounds| folder.fold_bounds(bounds))
|
||||
}
|
||||
|
||||
fn noop_fold_bounds<T: Folder>(bounds: TyParamBounds, folder: &mut T)
|
||||
-> TyParamBounds {
|
||||
bounds.move_map(|bound| folder.fold_ty_param_bound(bound))
|
||||
fn noop_fold_bounds<T: Folder>(bounds: GenericBounds, folder: &mut T)
|
||||
-> GenericBounds {
|
||||
bounds.move_map(|bound| folder.fold_param_bound(bound))
|
||||
}
|
||||
|
||||
pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> {
|
||||
|
|
@ -1184,8 +1179,8 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
|
|||
ExprKind::MethodCall(
|
||||
PathSegment {
|
||||
ident: folder.fold_ident(seg.ident),
|
||||
parameters: seg.parameters.map(|ps| {
|
||||
ps.map(|ps| folder.fold_path_parameters(ps))
|
||||
args: seg.args.map(|args| {
|
||||
args.map(|args| folder.fold_generic_args(args))
|
||||
}),
|
||||
},
|
||||
folder.fold_exprs(args))
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@
|
|||
// except according to those terms.
|
||||
|
||||
use rustc_target::spec::abi::{self, Abi};
|
||||
use ast::{AngleBracketedParameterData, ParenthesizedParameterData, AttrStyle, BareFnTy};
|
||||
use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
|
||||
use ast::{AngleBracketedArgs, ParenthesisedArgs, AttrStyle, BareFnTy};
|
||||
use ast::{GenericBound, TraitBoundModifier};
|
||||
use ast::Unsafety;
|
||||
use ast::{Mod, AnonConst, Arg, Arm, Attribute, BindingMode, TraitItemKind};
|
||||
use ast::Block;
|
||||
|
|
@ -21,9 +21,10 @@ use ast::EnumDef;
|
|||
use ast::{Expr, ExprKind, RangeLimits};
|
||||
use ast::{Field, FnDecl};
|
||||
use ast::{ForeignItem, ForeignItemKind, FunctionRetTy};
|
||||
use ast::GenericParam;
|
||||
use ast::{GenericParam, GenericParamKind};
|
||||
use ast::GenericArg;
|
||||
use ast::{Ident, ImplItem, IsAuto, Item, ItemKind};
|
||||
use ast::{Label, Lifetime, LifetimeDef, Lit, LitKind};
|
||||
use ast::{Label, Lifetime, Lit, LitKind};
|
||||
use ast::Local;
|
||||
use ast::MacStmtStyle;
|
||||
use ast::{Mac, Mac_, MacDelimiter};
|
||||
|
|
@ -35,7 +36,7 @@ use ast::{VariantData, StructField};
|
|||
use ast::StrStyle;
|
||||
use ast::SelfKind;
|
||||
use ast::{TraitItem, TraitRef, TraitObjectSyntax};
|
||||
use ast::{Ty, TyKind, TypeBinding, TyParam, TyParamBounds};
|
||||
use ast::{Ty, TyKind, TypeBinding, GenericBounds};
|
||||
use ast::{Visibility, VisibilityKind, WhereClause, CrateSugar};
|
||||
use ast::{UseTree, UseTreeKind};
|
||||
use ast::{BinOpKind, UnOp};
|
||||
|
|
@ -1245,8 +1246,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
/// parse a TyKind::BareFn type:
|
||||
fn parse_ty_bare_fn(&mut self, generic_params: Vec<GenericParam>)
|
||||
-> PResult<'a, TyKind> {
|
||||
fn parse_ty_bare_fn(&mut self, generic_params: Vec<GenericParam>) -> PResult<'a, TyKind> {
|
||||
/*
|
||||
|
||||
[unsafe] [extern "ABI"] fn (S) -> T
|
||||
|
|
@ -1311,9 +1311,7 @@ impl<'a> Parser<'a> {
|
|||
let lo = self.span;
|
||||
|
||||
let (name, node, generics) = if self.eat_keyword(keywords::Type) {
|
||||
let (generics, TyParam {ident, bounds, default, ..}) =
|
||||
self.parse_trait_item_assoc_ty(vec![])?;
|
||||
(ident, TraitItemKind::Type(bounds, default), generics)
|
||||
self.parse_trait_item_assoc_ty()?
|
||||
} else if self.is_const_item() {
|
||||
self.expect_keyword(keywords::Const)?;
|
||||
let ident = self.parse_ident()?;
|
||||
|
|
@ -1446,7 +1444,7 @@ impl<'a> Parser<'a> {
|
|||
TyKind::TraitObject(ref bounds, TraitObjectSyntax::None)
|
||||
if maybe_bounds && bounds.len() == 1 && !trailing_plus => {
|
||||
let path = match bounds[0] {
|
||||
TraitTyParamBound(ref pt, ..) => pt.trait_ref.path.clone(),
|
||||
GenericBound::Trait(ref pt, ..) => pt.trait_ref.path.clone(),
|
||||
_ => self.bug("unexpected lifetime bound"),
|
||||
};
|
||||
self.parse_remaining_bounds(Vec::new(), path, lo, true)?
|
||||
|
|
@ -1511,7 +1509,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
} else if self.eat_keyword(keywords::Impl) {
|
||||
// Always parse bounds greedily for better error recovery.
|
||||
let bounds = self.parse_ty_param_bounds()?;
|
||||
let bounds = self.parse_generic_bounds()?;
|
||||
impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus;
|
||||
TyKind::ImplTrait(bounds)
|
||||
} else if self.check_keyword(keywords::Dyn) &&
|
||||
|
|
@ -1519,13 +1517,13 @@ impl<'a> Parser<'a> {
|
|||
!can_continue_type_after_non_fn_ident(t)) {
|
||||
self.bump(); // `dyn`
|
||||
// Always parse bounds greedily for better error recovery.
|
||||
let bounds = self.parse_ty_param_bounds()?;
|
||||
let bounds = self.parse_generic_bounds()?;
|
||||
impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus;
|
||||
TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn)
|
||||
} else if self.check(&token::Question) ||
|
||||
self.check_lifetime() && self.look_ahead(1, |t| t.is_like_plus()) {
|
||||
// Bound list (trait object type)
|
||||
TyKind::TraitObject(self.parse_ty_param_bounds_common(allow_plus)?,
|
||||
TyKind::TraitObject(self.parse_generic_bounds_common(allow_plus)?,
|
||||
TraitObjectSyntax::None)
|
||||
} else if self.eat_lt() {
|
||||
// Qualified path
|
||||
|
|
@ -1568,10 +1566,10 @@ impl<'a> Parser<'a> {
|
|||
fn parse_remaining_bounds(&mut self, generic_params: Vec<GenericParam>, path: ast::Path,
|
||||
lo: Span, parse_plus: bool) -> PResult<'a, TyKind> {
|
||||
let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_span));
|
||||
let mut bounds = vec![TraitTyParamBound(poly_trait_ref, TraitBoundModifier::None)];
|
||||
let mut bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)];
|
||||
if parse_plus {
|
||||
self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded
|
||||
bounds.append(&mut self.parse_ty_param_bounds()?);
|
||||
bounds.append(&mut self.parse_generic_bounds()?);
|
||||
}
|
||||
Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
|
||||
}
|
||||
|
|
@ -1596,7 +1594,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
self.bump(); // `+`
|
||||
let bounds = self.parse_ty_param_bounds()?;
|
||||
let bounds = self.parse_generic_bounds()?;
|
||||
let sum_span = ty.span.to(self.prev_span);
|
||||
|
||||
let mut err = struct_span_err!(self.sess.span_diagnostic, sum_span, E0178,
|
||||
|
|
@ -1612,7 +1610,7 @@ impl<'a> Parser<'a> {
|
|||
s.print_mutability(mut_ty.mutbl)?;
|
||||
s.popen()?;
|
||||
s.print_type(&mut_ty.ty)?;
|
||||
s.print_bounds(" +", &bounds)?;
|
||||
s.print_type_bounds(" +", &bounds)?;
|
||||
s.pclose()
|
||||
});
|
||||
err.span_suggestion_with_applicability(
|
||||
|
|
@ -1894,7 +1892,7 @@ impl<'a> Parser<'a> {
|
|||
-> PResult<'a, ast::Path> {
|
||||
maybe_whole!(self, NtPath, |path| {
|
||||
if style == PathStyle::Mod &&
|
||||
path.segments.iter().any(|segment| segment.parameters.is_some()) {
|
||||
path.segments.iter().any(|segment| segment.args.is_some()) {
|
||||
self.diagnostic().span_err(path.span, "unexpected generic arguments in path");
|
||||
}
|
||||
path
|
||||
|
|
@ -1969,12 +1967,12 @@ impl<'a> Parser<'a> {
|
|||
.span_label(self.prev_span, "try removing `::`").emit();
|
||||
}
|
||||
|
||||
let parameters = if self.eat_lt() {
|
||||
let args = if self.eat_lt() {
|
||||
// `<'a, T, A = U>`
|
||||
let (lifetimes, types, bindings) = self.parse_generic_args()?;
|
||||
let (args, bindings) = self.parse_generic_args()?;
|
||||
self.expect_gt()?;
|
||||
let span = lo.to(self.prev_span);
|
||||
AngleBracketedParameterData { lifetimes, types, bindings, span }.into()
|
||||
AngleBracketedArgs { args, bindings, span }.into()
|
||||
} else {
|
||||
// `(T, U) -> R`
|
||||
self.bump(); // `(`
|
||||
|
|
@ -1990,10 +1988,10 @@ impl<'a> Parser<'a> {
|
|||
None
|
||||
};
|
||||
let span = lo.to(self.prev_span);
|
||||
ParenthesizedParameterData { inputs, output, span }.into()
|
||||
ParenthesisedArgs { inputs, output, span }.into()
|
||||
};
|
||||
|
||||
PathSegment { ident, parameters }
|
||||
PathSegment { ident, args }
|
||||
} else {
|
||||
// Generic arguments are not found.
|
||||
PathSegment::from_ident(ident)
|
||||
|
|
@ -2543,8 +2541,8 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
_ => {
|
||||
// Field access `expr.f`
|
||||
if let Some(parameters) = segment.parameters {
|
||||
self.span_err(parameters.span(),
|
||||
if let Some(args) = segment.args {
|
||||
self.span_err(args.span(),
|
||||
"field expressions may not have generic arguments");
|
||||
}
|
||||
|
||||
|
|
@ -4737,7 +4735,7 @@ impl<'a> Parser<'a> {
|
|||
// LT_BOUND = LIFETIME (e.g. `'a`)
|
||||
// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN)
|
||||
// TY_BOUND_NOPAREN = [?] [for<LT_PARAM_DEFS>] SIMPLE_PATH (e.g. `?for<'a: 'b> m::Trait<'a>`)
|
||||
fn parse_ty_param_bounds_common(&mut self, allow_plus: bool) -> PResult<'a, TyParamBounds> {
|
||||
fn parse_generic_bounds_common(&mut self, allow_plus: bool) -> PResult<'a, GenericBounds> {
|
||||
let mut bounds = Vec::new();
|
||||
loop {
|
||||
// This needs to be syncronized with `Token::can_begin_bound`.
|
||||
|
|
@ -4754,7 +4752,7 @@ impl<'a> Parser<'a> {
|
|||
self.span_err(question_span,
|
||||
"`?` may only modify trait bounds, not lifetime bounds");
|
||||
}
|
||||
bounds.push(RegionTyParamBound(self.expect_lifetime()));
|
||||
bounds.push(GenericBound::Outlives(self.expect_lifetime()));
|
||||
if has_parens {
|
||||
self.expect(&token::CloseDelim(token::Paren))?;
|
||||
self.span_err(self.prev_span,
|
||||
|
|
@ -4772,7 +4770,7 @@ impl<'a> Parser<'a> {
|
|||
} else {
|
||||
TraitBoundModifier::None
|
||||
};
|
||||
bounds.push(TraitTyParamBound(poly_trait, modifier));
|
||||
bounds.push(GenericBound::Trait(poly_trait, modifier));
|
||||
}
|
||||
} else {
|
||||
break
|
||||
|
|
@ -4786,16 +4784,16 @@ impl<'a> Parser<'a> {
|
|||
return Ok(bounds);
|
||||
}
|
||||
|
||||
fn parse_ty_param_bounds(&mut self) -> PResult<'a, TyParamBounds> {
|
||||
self.parse_ty_param_bounds_common(true)
|
||||
fn parse_generic_bounds(&mut self) -> PResult<'a, GenericBounds> {
|
||||
self.parse_generic_bounds_common(true)
|
||||
}
|
||||
|
||||
// Parse bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
|
||||
// BOUND = LT_BOUND (e.g. `'a`)
|
||||
fn parse_lt_param_bounds(&mut self) -> Vec<Lifetime> {
|
||||
fn parse_lt_param_bounds(&mut self) -> GenericBounds {
|
||||
let mut lifetimes = Vec::new();
|
||||
while self.check_lifetime() {
|
||||
lifetimes.push(self.expect_lifetime());
|
||||
lifetimes.push(ast::GenericBound::Outlives(self.expect_lifetime()));
|
||||
|
||||
if !self.eat_plus() {
|
||||
break
|
||||
|
|
@ -4805,12 +4803,14 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
/// Matches typaram = IDENT (`?` unbound)? optbounds ( EQ ty )?
|
||||
fn parse_ty_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a, TyParam> {
|
||||
fn parse_ty_param(&mut self,
|
||||
preceding_attrs: Vec<Attribute>)
|
||||
-> PResult<'a, GenericParam> {
|
||||
let ident = self.parse_ident()?;
|
||||
|
||||
// Parse optional colon and param bounds.
|
||||
let bounds = if self.eat(&token::Colon) {
|
||||
self.parse_ty_param_bounds()?
|
||||
self.parse_generic_bounds()?
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
|
@ -4821,25 +4821,27 @@ impl<'a> Parser<'a> {
|
|||
None
|
||||
};
|
||||
|
||||
Ok(TyParam {
|
||||
attrs: preceding_attrs.into(),
|
||||
Ok(GenericParam {
|
||||
ident,
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
attrs: preceding_attrs.into(),
|
||||
bounds,
|
||||
default,
|
||||
kind: GenericParamKind::Type {
|
||||
default,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Parses the following grammar:
|
||||
/// TraitItemAssocTy = Ident ["<"...">"] [":" [TyParamBounds]] ["where" ...] ["=" Ty]
|
||||
fn parse_trait_item_assoc_ty(&mut self, preceding_attrs: Vec<Attribute>)
|
||||
-> PResult<'a, (ast::Generics, TyParam)> {
|
||||
/// TraitItemAssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty]
|
||||
fn parse_trait_item_assoc_ty(&mut self)
|
||||
-> PResult<'a, (Ident, TraitItemKind, ast::Generics)> {
|
||||
let ident = self.parse_ident()?;
|
||||
let mut generics = self.parse_generics()?;
|
||||
|
||||
// Parse optional colon and param bounds.
|
||||
let bounds = if self.eat(&token::Colon) {
|
||||
self.parse_ty_param_bounds()?
|
||||
self.parse_generic_bounds()?
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
|
@ -4852,13 +4854,7 @@ impl<'a> Parser<'a> {
|
|||
};
|
||||
self.expect(&token::Semi)?;
|
||||
|
||||
Ok((generics, TyParam {
|
||||
attrs: preceding_attrs.into(),
|
||||
ident,
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
bounds,
|
||||
default,
|
||||
}))
|
||||
Ok((ident, TraitItemKind::Type(bounds, default), generics))
|
||||
}
|
||||
|
||||
/// Parses (possibly empty) list of lifetime and type parameters, possibly including
|
||||
|
|
@ -4876,18 +4872,20 @@ impl<'a> Parser<'a> {
|
|||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
params.push(ast::GenericParam::Lifetime(LifetimeDef {
|
||||
params.push(ast::GenericParam {
|
||||
ident: lifetime.ident,
|
||||
id: lifetime.id,
|
||||
attrs: attrs.into(),
|
||||
lifetime,
|
||||
bounds,
|
||||
}));
|
||||
kind: ast::GenericParamKind::Lifetime,
|
||||
});
|
||||
if seen_ty_param {
|
||||
self.span_err(self.prev_span,
|
||||
"lifetime parameters must be declared prior to type parameters");
|
||||
}
|
||||
} else if self.check_ident() {
|
||||
// Parse type parameter.
|
||||
params.push(ast::GenericParam::Type(self.parse_ty_param(attrs)?));
|
||||
params.push(self.parse_ty_param(attrs)?);
|
||||
seen_ty_param = true;
|
||||
} else {
|
||||
// Check for trailing attributes and stop parsing.
|
||||
|
|
@ -4936,16 +4934,16 @@ impl<'a> Parser<'a> {
|
|||
|
||||
/// Parses (possibly empty) list of lifetime and type arguments and associated type bindings,
|
||||
/// possibly including trailing comma.
|
||||
fn parse_generic_args(&mut self) -> PResult<'a, (Vec<Lifetime>, Vec<P<Ty>>, Vec<TypeBinding>)> {
|
||||
let mut lifetimes = Vec::new();
|
||||
let mut types = Vec::new();
|
||||
fn parse_generic_args(&mut self)
|
||||
-> PResult<'a, (Vec<GenericArg>, Vec<TypeBinding>)> {
|
||||
let mut args = Vec::new();
|
||||
let mut bindings = Vec::new();
|
||||
let mut seen_type = false;
|
||||
let mut seen_binding = false;
|
||||
loop {
|
||||
if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
|
||||
// Parse lifetime argument.
|
||||
lifetimes.push(self.expect_lifetime());
|
||||
args.push(GenericArg::Lifetime(self.expect_lifetime()));
|
||||
if seen_type || seen_binding {
|
||||
self.span_err(self.prev_span,
|
||||
"lifetime parameters must be declared prior to type parameters");
|
||||
|
|
@ -4965,11 +4963,12 @@ impl<'a> Parser<'a> {
|
|||
seen_binding = true;
|
||||
} else if self.check_type() {
|
||||
// Parse type argument.
|
||||
types.push(self.parse_ty()?);
|
||||
let ty_param = self.parse_ty()?;
|
||||
if seen_binding {
|
||||
self.span_err(types[types.len() - 1].span,
|
||||
self.span_err(ty_param.span,
|
||||
"type parameters must be declared prior to associated type bindings");
|
||||
}
|
||||
args.push(GenericArg::Type(ty_param));
|
||||
seen_type = true;
|
||||
} else {
|
||||
break
|
||||
|
|
@ -4979,7 +4978,7 @@ impl<'a> Parser<'a> {
|
|||
break
|
||||
}
|
||||
}
|
||||
Ok((lifetimes, types, bindings))
|
||||
Ok((args, bindings))
|
||||
}
|
||||
|
||||
/// Parses an optional `where` clause and places it in `generics`.
|
||||
|
|
@ -5037,7 +5036,7 @@ impl<'a> Parser<'a> {
|
|||
// or with mandatory equality sign and the second type.
|
||||
let ty = self.parse_ty()?;
|
||||
if self.eat(&token::Colon) {
|
||||
let bounds = self.parse_ty_param_bounds()?;
|
||||
let bounds = self.parse_generic_bounds()?;
|
||||
where_clause.predicates.push(ast::WherePredicate::BoundPredicate(
|
||||
ast::WhereBoundPredicate {
|
||||
span: lo.to(self.prev_span),
|
||||
|
|
@ -5537,14 +5536,14 @@ impl<'a> Parser<'a> {
|
|||
|
||||
// Parse optional colon and supertrait bounds.
|
||||
let bounds = if self.eat(&token::Colon) {
|
||||
self.parse_ty_param_bounds()?
|
||||
self.parse_generic_bounds()?
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
if self.eat(&token::Eq) {
|
||||
// it's a trait alias
|
||||
let bounds = self.parse_ty_param_bounds()?;
|
||||
let bounds = self.parse_generic_bounds()?;
|
||||
tps.where_clause = self.parse_where_clause()?;
|
||||
self.expect(&token::Semi)?;
|
||||
if unsafety != Unsafety::Normal {
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ pub use self::AnnNode::*;
|
|||
|
||||
use rustc_target::spec::abi::{self, Abi};
|
||||
use ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
|
||||
use ast::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
|
||||
use ast::{Attribute, MacDelimiter};
|
||||
use ast::{SelfKind, GenericBound, TraitBoundModifier};
|
||||
use ast::{Attribute, MacDelimiter, GenericArg};
|
||||
use util::parser::{self, AssocOp, Fixity};
|
||||
use attr;
|
||||
use codemap::{self, CodeMap};
|
||||
|
|
@ -292,8 +292,8 @@ pub fn ty_to_string(ty: &ast::Ty) -> String {
|
|||
to_string(|s| s.print_type(ty))
|
||||
}
|
||||
|
||||
pub fn bounds_to_string(bounds: &[ast::TyParamBound]) -> String {
|
||||
to_string(|s| s.print_bounds("", bounds))
|
||||
pub fn bounds_to_string(bounds: &[ast::GenericBound]) -> String {
|
||||
to_string(|s| s.print_type_bounds("", bounds))
|
||||
}
|
||||
|
||||
pub fn pat_to_string(pat: &ast::Pat) -> String {
|
||||
|
|
@ -308,8 +308,8 @@ pub fn expr_to_string(e: &ast::Expr) -> String {
|
|||
to_string(|s| s.print_expr(e))
|
||||
}
|
||||
|
||||
pub fn lifetime_to_string(e: &ast::Lifetime) -> String {
|
||||
to_string(|s| s.print_lifetime(e))
|
||||
pub fn lifetime_to_string(lt: &ast::Lifetime) -> String {
|
||||
to_string(|s| s.print_lifetime(*lt))
|
||||
}
|
||||
|
||||
pub fn tt_to_string(tt: tokenstream::TokenTree) -> String {
|
||||
|
|
@ -1008,15 +1008,21 @@ impl<'a> State<'a> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn print_opt_lifetime(&mut self,
|
||||
lifetime: &Option<ast::Lifetime>) -> io::Result<()> {
|
||||
if let Some(l) = *lifetime {
|
||||
self.print_lifetime(&l)?;
|
||||
pub fn print_opt_lifetime(&mut self, lifetime: &Option<ast::Lifetime>) -> io::Result<()> {
|
||||
if let Some(lt) = *lifetime {
|
||||
self.print_lifetime(lt)?;
|
||||
self.nbsp()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn print_generic_arg(&mut self, generic_arg: &GenericArg) -> io::Result<()> {
|
||||
match generic_arg {
|
||||
GenericArg::Lifetime(lt) => self.print_lifetime(*lt),
|
||||
GenericArg::Type(ty) => self.print_type(ty),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> {
|
||||
self.maybe_print_comment(ty.span.lo())?;
|
||||
self.ibox(0)?;
|
||||
|
|
@ -1071,10 +1077,10 @@ impl<'a> State<'a> {
|
|||
}
|
||||
ast::TyKind::TraitObject(ref bounds, syntax) => {
|
||||
let prefix = if syntax == ast::TraitObjectSyntax::Dyn { "dyn" } else { "" };
|
||||
self.print_bounds(prefix, &bounds[..])?;
|
||||
self.print_type_bounds(prefix, &bounds[..])?;
|
||||
}
|
||||
ast::TyKind::ImplTrait(ref bounds) => {
|
||||
self.print_bounds("impl", &bounds[..])?;
|
||||
self.print_type_bounds("impl", &bounds[..])?;
|
||||
}
|
||||
ast::TyKind::Array(ref ty, ref length) => {
|
||||
self.s.word("[")?;
|
||||
|
|
@ -1171,13 +1177,13 @@ impl<'a> State<'a> {
|
|||
|
||||
fn print_associated_type(&mut self,
|
||||
ident: ast::Ident,
|
||||
bounds: Option<&ast::TyParamBounds>,
|
||||
bounds: Option<&ast::GenericBounds>,
|
||||
ty: Option<&ast::Ty>)
|
||||
-> io::Result<()> {
|
||||
self.word_space("type")?;
|
||||
self.print_ident(ident)?;
|
||||
if let Some(bounds) = bounds {
|
||||
self.print_bounds(":", bounds)?;
|
||||
self.print_type_bounds(":", bounds)?;
|
||||
}
|
||||
if let Some(ty) = ty {
|
||||
self.s.space()?;
|
||||
|
|
@ -1322,7 +1328,7 @@ impl<'a> State<'a> {
|
|||
self.print_unsafety(unsafety)?;
|
||||
self.word_nbsp("impl")?;
|
||||
|
||||
if generics.is_parameterized() {
|
||||
if !generics.params.is_empty() {
|
||||
self.print_generic_params(&generics.params)?;
|
||||
self.s.space()?;
|
||||
}
|
||||
|
|
@ -1358,7 +1364,7 @@ impl<'a> State<'a> {
|
|||
self.print_generic_params(&generics.params)?;
|
||||
let mut real_bounds = Vec::with_capacity(bounds.len());
|
||||
for b in bounds.iter() {
|
||||
if let TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = *b {
|
||||
if let GenericBound::Trait(ref ptr, ast::TraitBoundModifier::Maybe) = *b {
|
||||
self.s.space()?;
|
||||
self.word_space("for ?")?;
|
||||
self.print_trait_ref(&ptr.trait_ref)?;
|
||||
|
|
@ -1366,7 +1372,7 @@ impl<'a> State<'a> {
|
|||
real_bounds.push(b.clone());
|
||||
}
|
||||
}
|
||||
self.print_bounds(":", &real_bounds[..])?;
|
||||
self.print_type_bounds(":", &real_bounds[..])?;
|
||||
self.print_where_clause(&generics.where_clause)?;
|
||||
self.s.word(" ")?;
|
||||
self.bopen()?;
|
||||
|
|
@ -1384,7 +1390,7 @@ impl<'a> State<'a> {
|
|||
let mut real_bounds = Vec::with_capacity(bounds.len());
|
||||
// FIXME(durka) this seems to be some quite outdated syntax
|
||||
for b in bounds.iter() {
|
||||
if let TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = *b {
|
||||
if let GenericBound::Trait(ref ptr, ast::TraitBoundModifier::Maybe) = *b {
|
||||
self.s.space()?;
|
||||
self.word_space("for ?")?;
|
||||
self.print_trait_ref(&ptr.trait_ref)?;
|
||||
|
|
@ -1393,7 +1399,7 @@ impl<'a> State<'a> {
|
|||
}
|
||||
}
|
||||
self.nbsp()?;
|
||||
self.print_bounds("=", &real_bounds[..])?;
|
||||
self.print_type_bounds("=", &real_bounds[..])?;
|
||||
self.print_where_clause(&generics.where_clause)?;
|
||||
self.s.word(";")?;
|
||||
}
|
||||
|
|
@ -1984,8 +1990,8 @@ impl<'a> State<'a> {
|
|||
self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX)?;
|
||||
self.s.word(".")?;
|
||||
self.print_ident(segment.ident)?;
|
||||
if let Some(ref parameters) = segment.parameters {
|
||||
self.print_path_parameters(parameters, true)?;
|
||||
if let Some(ref args) = segment.args {
|
||||
self.print_generic_args(args, true)?;
|
||||
}
|
||||
self.print_call_post(base_args)
|
||||
}
|
||||
|
|
@ -2428,8 +2434,8 @@ impl<'a> State<'a> {
|
|||
if segment.ident.name != keywords::CrateRoot.name() &&
|
||||
segment.ident.name != keywords::DollarCrate.name() {
|
||||
self.print_ident(segment.ident)?;
|
||||
if let Some(ref parameters) = segment.parameters {
|
||||
self.print_path_parameters(parameters, colons_before_params)?;
|
||||
if let Some(ref args) = segment.args {
|
||||
self.print_generic_args(args, colons_before_params)?;
|
||||
}
|
||||
} else if segment.ident.name == keywords::DollarCrate.name() {
|
||||
self.print_dollar_crate(segment.ident.span.ctxt())?;
|
||||
|
|
@ -2455,44 +2461,30 @@ impl<'a> State<'a> {
|
|||
self.s.word("::")?;
|
||||
let item_segment = path.segments.last().unwrap();
|
||||
self.print_ident(item_segment.ident)?;
|
||||
match item_segment.parameters {
|
||||
Some(ref parameters) => self.print_path_parameters(parameters, colons_before_params),
|
||||
match item_segment.args {
|
||||
Some(ref args) => self.print_generic_args(args, colons_before_params),
|
||||
None => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
fn print_path_parameters(&mut self,
|
||||
parameters: &ast::PathParameters,
|
||||
colons_before_params: bool)
|
||||
-> io::Result<()>
|
||||
fn print_generic_args(&mut self,
|
||||
args: &ast::GenericArgs,
|
||||
colons_before_params: bool)
|
||||
-> io::Result<()>
|
||||
{
|
||||
if colons_before_params {
|
||||
self.s.word("::")?
|
||||
}
|
||||
|
||||
match *parameters {
|
||||
ast::PathParameters::AngleBracketed(ref data) => {
|
||||
match *args {
|
||||
ast::GenericArgs::AngleBracketed(ref data) => {
|
||||
self.s.word("<")?;
|
||||
|
||||
let mut comma = false;
|
||||
for lifetime in &data.lifetimes {
|
||||
if comma {
|
||||
self.word_space(",")?
|
||||
}
|
||||
self.print_lifetime(lifetime)?;
|
||||
comma = true;
|
||||
}
|
||||
self.commasep(Inconsistent, &data.args, |s, generic_arg| {
|
||||
s.print_generic_arg(generic_arg)
|
||||
})?;
|
||||
|
||||
if !data.types.is_empty() {
|
||||
if comma {
|
||||
self.word_space(",")?
|
||||
}
|
||||
self.commasep(
|
||||
Inconsistent,
|
||||
&data.types,
|
||||
|s, ty| s.print_type(ty))?;
|
||||
comma = true;
|
||||
}
|
||||
let mut comma = data.args.len() != 0;
|
||||
|
||||
for binding in data.bindings.iter() {
|
||||
if comma {
|
||||
|
|
@ -2508,7 +2500,7 @@ impl<'a> State<'a> {
|
|||
self.s.word(">")?
|
||||
}
|
||||
|
||||
ast::PathParameters::Parenthesized(ref data) => {
|
||||
ast::GenericArgs::Parenthesized(ref data) => {
|
||||
self.s.word("(")?;
|
||||
self.commasep(
|
||||
Inconsistent,
|
||||
|
|
@ -2816,9 +2808,9 @@ impl<'a> State<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn print_bounds(&mut self,
|
||||
pub fn print_type_bounds(&mut self,
|
||||
prefix: &str,
|
||||
bounds: &[ast::TyParamBound])
|
||||
bounds: &[ast::GenericBound])
|
||||
-> io::Result<()> {
|
||||
if !bounds.is_empty() {
|
||||
self.s.word(prefix)?;
|
||||
|
|
@ -2834,32 +2826,25 @@ impl<'a> State<'a> {
|
|||
}
|
||||
|
||||
match bound {
|
||||
TraitTyParamBound(tref, modifier) => {
|
||||
GenericBound::Trait(tref, modifier) => {
|
||||
if modifier == &TraitBoundModifier::Maybe {
|
||||
self.s.word("?")?;
|
||||
}
|
||||
self.print_poly_trait_ref(tref)?;
|
||||
}
|
||||
RegionTyParamBound(lt) => {
|
||||
self.print_lifetime(lt)?;
|
||||
}
|
||||
GenericBound::Outlives(lt) => self.print_lifetime(*lt)?,
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn print_lifetime(&mut self,
|
||||
lifetime: &ast::Lifetime)
|
||||
-> io::Result<()>
|
||||
{
|
||||
pub fn print_lifetime(&mut self, lifetime: ast::Lifetime) -> io::Result<()> {
|
||||
self.print_name(lifetime.ident.name)
|
||||
}
|
||||
|
||||
pub fn print_lifetime_bounds(&mut self,
|
||||
lifetime: &ast::Lifetime,
|
||||
bounds: &[ast::Lifetime])
|
||||
-> io::Result<()>
|
||||
pub fn print_lifetime_bounds(&mut self, lifetime: ast::Lifetime, bounds: &ast::GenericBounds)
|
||||
-> io::Result<()>
|
||||
{
|
||||
self.print_lifetime(lifetime)?;
|
||||
if !bounds.is_empty() {
|
||||
|
|
@ -2868,7 +2853,10 @@ impl<'a> State<'a> {
|
|||
if i != 0 {
|
||||
self.s.word(" + ")?;
|
||||
}
|
||||
self.print_lifetime(bound)?;
|
||||
match bound {
|
||||
ast::GenericBound::Outlives(lt) => self.print_lifetime(*lt)?,
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -2885,12 +2873,25 @@ impl<'a> State<'a> {
|
|||
self.s.word("<")?;
|
||||
|
||||
self.commasep(Inconsistent, &generic_params, |s, param| {
|
||||
match *param {
|
||||
ast::GenericParam::Lifetime(ref lifetime_def) => {
|
||||
s.print_outer_attributes_inline(&lifetime_def.attrs)?;
|
||||
s.print_lifetime_bounds(&lifetime_def.lifetime, &lifetime_def.bounds)
|
||||
match param.kind {
|
||||
ast::GenericParamKind::Lifetime => {
|
||||
s.print_outer_attributes_inline(¶m.attrs)?;
|
||||
let lt = ast::Lifetime { id: param.id, ident: param.ident };
|
||||
s.print_lifetime_bounds(lt, ¶m.bounds)
|
||||
},
|
||||
ast::GenericParam::Type(ref ty_param) => s.print_ty_param(ty_param),
|
||||
ast::GenericParamKind::Type { ref default } => {
|
||||
s.print_outer_attributes_inline(¶m.attrs)?;
|
||||
s.print_ident(param.ident)?;
|
||||
s.print_type_bounds(":", ¶m.bounds)?;
|
||||
match default {
|
||||
Some(ref default) => {
|
||||
s.s.space()?;
|
||||
s.word_space("=")?;
|
||||
s.print_type(default)
|
||||
}
|
||||
_ => Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
})?;
|
||||
|
||||
|
|
@ -2898,20 +2899,6 @@ impl<'a> State<'a> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn print_ty_param(&mut self, param: &ast::TyParam) -> io::Result<()> {
|
||||
self.print_outer_attributes_inline(¶m.attrs)?;
|
||||
self.print_ident(param.ident)?;
|
||||
self.print_bounds(":", ¶m.bounds)?;
|
||||
match param.default {
|
||||
Some(ref default) => {
|
||||
self.s.space()?;
|
||||
self.word_space("=")?;
|
||||
self.print_type(default)
|
||||
}
|
||||
_ => Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_where_clause(&mut self, where_clause: &ast::WhereClause)
|
||||
-> io::Result<()> {
|
||||
if where_clause.predicates.is_empty() {
|
||||
|
|
@ -2935,12 +2922,12 @@ impl<'a> State<'a> {
|
|||
}) => {
|
||||
self.print_formal_generic_params(bound_generic_params)?;
|
||||
self.print_type(bounded_ty)?;
|
||||
self.print_bounds(":", bounds)?;
|
||||
self.print_type_bounds(":", bounds)?;
|
||||
}
|
||||
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
|
||||
ref bounds,
|
||||
..}) => {
|
||||
self.print_lifetime_bounds(lifetime, bounds)?;
|
||||
self.print_lifetime_bounds(*lifetime, bounds)?;
|
||||
}
|
||||
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref lhs_ty,
|
||||
ref rhs_ty,
|
||||
|
|
|
|||
|
|
@ -353,7 +353,7 @@ fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
|
|||
|
||||
match (has_output, has_should_panic_attr) {
|
||||
(true, true) => No(BadTestSignature::ShouldPanicOnlyWithNoArgs),
|
||||
(true, false) => if generics.is_parameterized() {
|
||||
(true, false) => if !generics.params.is_empty() {
|
||||
No(BadTestSignature::WrongTypeSignature)
|
||||
} else {
|
||||
Yes
|
||||
|
|
|
|||
|
|
@ -95,9 +95,9 @@ impl<'ast> Visitor<'ast> for NodeCounter {
|
|||
self.count += 1;
|
||||
walk_trait_ref(self, t)
|
||||
}
|
||||
fn visit_ty_param_bound(&mut self, bounds: &TyParamBound) {
|
||||
fn visit_param_bound(&mut self, bounds: &GenericBound) {
|
||||
self.count += 1;
|
||||
walk_ty_param_bound(self, bounds)
|
||||
walk_param_bound(self, bounds)
|
||||
}
|
||||
fn visit_poly_trait_ref(&mut self, t: &PolyTraitRef, m: &TraitBoundModifier) {
|
||||
self.count += 1;
|
||||
|
|
@ -137,9 +137,9 @@ impl<'ast> Visitor<'ast> for NodeCounter {
|
|||
self.count += 1;
|
||||
walk_use_tree(self, use_tree, id)
|
||||
}
|
||||
fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &PathParameters) {
|
||||
fn visit_generic_args(&mut self, path_span: Span, generic_args: &GenericArgs) {
|
||||
self.count += 1;
|
||||
walk_path_parameters(self, path_span, path_parameters)
|
||||
walk_generic_args(self, path_span, generic_args)
|
||||
}
|
||||
fn visit_assoc_type_binding(&mut self, type_binding: &TypeBinding) {
|
||||
self.count += 1;
|
||||
|
|
|
|||
|
|
@ -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 GenericParam) { walk_generic_param(self, param) }
|
||||
fn visit_generic_param(&mut self, param: &'ast GenericParam) {
|
||||
walk_generic_param(self, param)
|
||||
}
|
||||
fn visit_generics(&mut self, g: &'ast Generics) { walk_generics(self, g) }
|
||||
fn visit_where_predicate(&mut self, p: &'ast WherePredicate) {
|
||||
walk_where_predicate(self, p)
|
||||
|
|
@ -84,8 +86,8 @@ pub trait Visitor<'ast>: Sized {
|
|||
fn visit_trait_item(&mut self, ti: &'ast TraitItem) { walk_trait_item(self, ti) }
|
||||
fn visit_impl_item(&mut self, ii: &'ast ImplItem) { walk_impl_item(self, ii) }
|
||||
fn visit_trait_ref(&mut self, t: &'ast TraitRef) { walk_trait_ref(self, t) }
|
||||
fn visit_ty_param_bound(&mut self, bounds: &'ast TyParamBound) {
|
||||
walk_ty_param_bound(self, bounds)
|
||||
fn visit_param_bound(&mut self, bounds: &'ast GenericBound) {
|
||||
walk_param_bound(self, bounds)
|
||||
}
|
||||
fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) {
|
||||
walk_poly_trait_ref(self, t, m)
|
||||
|
|
@ -128,8 +130,14 @@ pub trait Visitor<'ast>: Sized {
|
|||
fn visit_path_segment(&mut self, path_span: Span, path_segment: &'ast PathSegment) {
|
||||
walk_path_segment(self, path_span, path_segment)
|
||||
}
|
||||
fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &'ast PathParameters) {
|
||||
walk_path_parameters(self, path_span, path_parameters)
|
||||
fn visit_generic_args(&mut self, path_span: Span, generic_args: &'ast GenericArgs) {
|
||||
walk_generic_args(self, path_span, generic_args)
|
||||
}
|
||||
fn visit_generic_arg(&mut self, generic_arg: &'ast GenericArg) {
|
||||
match generic_arg {
|
||||
GenericArg::Lifetime(lt) => self.visit_lifetime(lt),
|
||||
GenericArg::Type(ty) => self.visit_ty(ty),
|
||||
}
|
||||
}
|
||||
fn visit_assoc_type_binding(&mut self, type_binding: &'ast TypeBinding) {
|
||||
walk_assoc_type_binding(self, type_binding)
|
||||
|
|
@ -268,12 +276,12 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
|
|||
}
|
||||
ItemKind::Trait(.., ref generics, ref bounds, ref methods) => {
|
||||
visitor.visit_generics(generics);
|
||||
walk_list!(visitor, visit_ty_param_bound, bounds);
|
||||
walk_list!(visitor, visit_param_bound, bounds);
|
||||
walk_list!(visitor, visit_trait_item, methods);
|
||||
}
|
||||
ItemKind::TraitAlias(ref generics, ref bounds) => {
|
||||
visitor.visit_generics(generics);
|
||||
walk_list!(visitor, visit_ty_param_bound, bounds);
|
||||
walk_list!(visitor, visit_param_bound, bounds);
|
||||
}
|
||||
ItemKind::Mac(ref mac) => visitor.visit_mac(mac),
|
||||
ItemKind::MacroDef(ref ts) => visitor.visit_mac_def(ts, item.id),
|
||||
|
|
@ -333,7 +341,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
|
|||
}
|
||||
TyKind::TraitObject(ref bounds, ..) |
|
||||
TyKind::ImplTrait(ref bounds) => {
|
||||
walk_list!(visitor, visit_ty_param_bound, bounds);
|
||||
walk_list!(visitor, visit_param_bound, bounds);
|
||||
}
|
||||
TyKind::Typeof(ref expression) => {
|
||||
visitor.visit_anon_const(expression)
|
||||
|
|
@ -375,23 +383,22 @@ pub fn walk_path_segment<'a, V: Visitor<'a>>(visitor: &mut V,
|
|||
path_span: Span,
|
||||
segment: &'a PathSegment) {
|
||||
visitor.visit_ident(segment.ident);
|
||||
if let Some(ref parameters) = segment.parameters {
|
||||
visitor.visit_path_parameters(path_span, parameters);
|
||||
if let Some(ref args) = segment.args {
|
||||
visitor.visit_generic_args(path_span, args);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_path_parameters<'a, V>(visitor: &mut V,
|
||||
_path_span: Span,
|
||||
path_parameters: &'a PathParameters)
|
||||
pub fn walk_generic_args<'a, V>(visitor: &mut V,
|
||||
_path_span: Span,
|
||||
generic_args: &'a GenericArgs)
|
||||
where V: Visitor<'a>,
|
||||
{
|
||||
match *path_parameters {
|
||||
PathParameters::AngleBracketed(ref data) => {
|
||||
walk_list!(visitor, visit_ty, &data.types);
|
||||
walk_list!(visitor, visit_lifetime, &data.lifetimes);
|
||||
match *generic_args {
|
||||
GenericArgs::AngleBracketed(ref data) => {
|
||||
walk_list!(visitor, visit_generic_arg, &data.args);
|
||||
walk_list!(visitor, visit_assoc_type_binding, &data.bindings);
|
||||
}
|
||||
PathParameters::Parenthesized(ref data) => {
|
||||
GenericArgs::Parenthesized(ref data) => {
|
||||
walk_list!(visitor, visit_ty, &data.inputs);
|
||||
walk_list!(visitor, visit_ty, &data.output);
|
||||
}
|
||||
|
|
@ -472,30 +479,20 @@ pub fn walk_global_asm<'a, V: Visitor<'a>>(_: &mut V, _: &'a GlobalAsm) {
|
|||
// Empty!
|
||||
}
|
||||
|
||||
pub fn walk_ty_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a TyParamBound) {
|
||||
pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericBound) {
|
||||
match *bound {
|
||||
TraitTyParamBound(ref typ, ref modifier) => {
|
||||
visitor.visit_poly_trait_ref(typ, modifier);
|
||||
}
|
||||
RegionTyParamBound(ref lifetime) => {
|
||||
visitor.visit_lifetime(lifetime);
|
||||
}
|
||||
GenericBound::Trait(ref typ, ref modifier) => visitor.visit_poly_trait_ref(typ, modifier),
|
||||
GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a GenericParam) {
|
||||
match *param {
|
||||
GenericParam::Lifetime(ref l) => {
|
||||
visitor.visit_ident(l.lifetime.ident);
|
||||
walk_list!(visitor, visit_lifetime, &l.bounds);
|
||||
walk_list!(visitor, visit_attribute, &*l.attrs);
|
||||
}
|
||||
GenericParam::Type(ref t) => {
|
||||
visitor.visit_ident(t.ident);
|
||||
walk_list!(visitor, visit_ty_param_bound, &t.bounds);
|
||||
walk_list!(visitor, visit_ty, &t.default);
|
||||
walk_list!(visitor, visit_attribute, &*t.attrs);
|
||||
}
|
||||
visitor.visit_ident(param.ident);
|
||||
walk_list!(visitor, visit_attribute, param.attrs.iter());
|
||||
walk_list!(visitor, visit_param_bound, ¶m.bounds);
|
||||
match param.kind {
|
||||
GenericParamKind::Lifetime => {}
|
||||
GenericParamKind::Type { ref default } => walk_list!(visitor, visit_ty, default),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -511,14 +508,14 @@ pub fn walk_where_predicate<'a, V: Visitor<'a>>(visitor: &mut V, predicate: &'a
|
|||
ref bound_generic_params,
|
||||
..}) => {
|
||||
visitor.visit_ty(bounded_ty);
|
||||
walk_list!(visitor, visit_ty_param_bound, bounds);
|
||||
walk_list!(visitor, visit_param_bound, bounds);
|
||||
walk_list!(visitor, visit_generic_param, bound_generic_params);
|
||||
}
|
||||
WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime,
|
||||
ref bounds,
|
||||
..}) => {
|
||||
visitor.visit_lifetime(lifetime);
|
||||
walk_list!(visitor, visit_lifetime, bounds);
|
||||
walk_list!(visitor, visit_param_bound, bounds);
|
||||
}
|
||||
WherePredicate::EqPredicate(WhereEqPredicate{ref lhs_ty,
|
||||
ref rhs_ty,
|
||||
|
|
@ -579,7 +576,7 @@ pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, trait_item: &'a Trai
|
|||
&sig.decl, trait_item.span, trait_item.id);
|
||||
}
|
||||
TraitItemKind::Type(ref bounds, ref default) => {
|
||||
walk_list!(visitor, visit_ty_param_bound, bounds);
|
||||
walk_list!(visitor, visit_param_bound, bounds);
|
||||
walk_list!(visitor, visit_ty, default);
|
||||
}
|
||||
TraitItemKind::Macro(ref mac) => {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ use deriving::generic::*;
|
|||
use deriving::generic::ty::*;
|
||||
|
||||
use syntax::ast::{self, Expr, Generics, ItemKind, MetaItem, VariantData};
|
||||
use syntax::ast::GenericArg;
|
||||
use syntax::attr;
|
||||
use syntax::ext::base::{Annotatable, ExtCtxt};
|
||||
use syntax::ext::build::AstBuilder;
|
||||
|
|
@ -48,7 +49,10 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt,
|
|||
ItemKind::Struct(_, Generics { ref params, .. }) |
|
||||
ItemKind::Enum(_, Generics { ref params, .. }) => {
|
||||
if attr::contains_name(&annitem.attrs, "rustc_copy_clone_marker") &&
|
||||
!params.iter().any(|param| param.is_type_param())
|
||||
!params.iter().any(|param| match param.kind {
|
||||
ast::GenericParamKind::Type { .. } => true,
|
||||
_ => false,
|
||||
})
|
||||
{
|
||||
bounds = vec![];
|
||||
is_shallow = true;
|
||||
|
|
@ -123,7 +127,7 @@ fn cs_clone_shallow(name: &str,
|
|||
let span = span.with_ctxt(cx.backtrace());
|
||||
let assert_path = cx.path_all(span, true,
|
||||
cx.std_path(&["clone", helper_name]),
|
||||
vec![], vec![ty], vec![]);
|
||||
vec![GenericArg::Type(ty)], vec![]);
|
||||
stmts.push(cx.stmt_let_type_only(span, cx.ty_path(assert_path)));
|
||||
}
|
||||
fn process_variant(cx: &mut ExtCtxt, stmts: &mut Vec<ast::Stmt>, variant: &VariantData) {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use deriving::path_std;
|
|||
use deriving::generic::*;
|
||||
use deriving::generic::ty::*;
|
||||
|
||||
use syntax::ast::{self, Expr, MetaItem};
|
||||
use syntax::ast::{self, Expr, MetaItem, GenericArg};
|
||||
use syntax::ext::base::{Annotatable, ExtCtxt};
|
||||
use syntax::ext::build::AstBuilder;
|
||||
use syntax::ptr::P;
|
||||
|
|
@ -62,7 +62,7 @@ fn cs_total_eq_assert(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure)
|
|||
let span = span.with_ctxt(cx.backtrace());
|
||||
let assert_path = cx.path_all(span, true,
|
||||
cx.std_path(&["cmp", helper_name]),
|
||||
vec![], vec![ty], vec![]);
|
||||
vec![GenericArg::Type(ty)], vec![]);
|
||||
stmts.push(cx.stmt_let_type_only(span, cx.ty_path(assert_path)));
|
||||
}
|
||||
fn process_variant(cx: &mut ExtCtxt, stmts: &mut Vec<ast::Stmt>, variant: &ast::VariantData) {
|
||||
|
|
|
|||
|
|
@ -192,10 +192,8 @@ use std::collections::HashSet;
|
|||
use std::vec;
|
||||
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use syntax::ast::{
|
||||
self, BinOpKind, EnumDef, Expr, GenericParam, Generics, Ident, PatKind, VariantData
|
||||
};
|
||||
|
||||
use syntax::ast::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind};
|
||||
use syntax::ast::{VariantData, GenericParamKind, GenericArg};
|
||||
use syntax::attr;
|
||||
use syntax::ext::base::{Annotatable, ExtCtxt};
|
||||
use syntax::ext::build::AstBuilder;
|
||||
|
|
@ -424,7 +422,10 @@ impl<'a> TraitDef<'a> {
|
|||
ast::ItemKind::Struct(_, ref generics) |
|
||||
ast::ItemKind::Enum(_, ref generics) |
|
||||
ast::ItemKind::Union(_, ref generics) => {
|
||||
!generics.params.iter().any(|p| p.is_type_param())
|
||||
!generics.params.iter().any(|param| match param.kind {
|
||||
ast::GenericParamKind::Type { .. } => true,
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
_ => {
|
||||
// Non-ADT derive is an error, but it should have been
|
||||
|
|
@ -548,30 +549,27 @@ impl<'a> TraitDef<'a> {
|
|||
.to_generics(cx, self.span, type_ident, generics);
|
||||
|
||||
// Create the generic parameters
|
||||
params.extend(generics.params.iter().map(|param| {
|
||||
match *param {
|
||||
ref l @ GenericParam::Lifetime(_) => l.clone(),
|
||||
GenericParam::Type(ref ty_param) => {
|
||||
// I don't think this can be moved out of the loop, since
|
||||
// a TyParamBound requires an ast id
|
||||
let mut bounds: Vec<_> =
|
||||
// extra restrictions on the generics parameters to the
|
||||
// type being derived upon
|
||||
self.additional_bounds.iter().map(|p| {
|
||||
cx.typarambound(p.to_path(cx, self.span,
|
||||
type_ident, generics))
|
||||
}).collect();
|
||||
params.extend(generics.params.iter().map(|param| match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => param.clone(),
|
||||
GenericParamKind::Type { .. } => {
|
||||
// I don't think this can be moved out of the loop, since
|
||||
// a GenericBound requires an ast id
|
||||
let mut bounds: Vec<_> =
|
||||
// extra restrictions on the generics parameters to the
|
||||
// type being derived upon
|
||||
self.additional_bounds.iter().map(|p| {
|
||||
cx.trait_bound(p.to_path(cx, self.span, type_ident, generics))
|
||||
}).collect();
|
||||
|
||||
// require the current trait
|
||||
bounds.push(cx.typarambound(trait_path.clone()));
|
||||
// require the current trait
|
||||
bounds.push(cx.trait_bound(trait_path.clone()));
|
||||
|
||||
// also add in any bounds from the declaration
|
||||
for declared_bound in ty_param.bounds.iter() {
|
||||
bounds.push((*declared_bound).clone());
|
||||
}
|
||||
|
||||
GenericParam::Type(cx.typaram(self.span, ty_param.ident, vec![], bounds, None))
|
||||
// also add in any bounds from the declaration
|
||||
for declared_bound in ¶m.bounds {
|
||||
bounds.push((*declared_bound).clone());
|
||||
}
|
||||
|
||||
cx.typaram(self.span, param.ident, vec![], bounds, None)
|
||||
}
|
||||
}));
|
||||
|
||||
|
|
@ -608,8 +606,8 @@ impl<'a> TraitDef<'a> {
|
|||
// Extra scope required here so ty_params goes out of scope before params is moved
|
||||
|
||||
let mut ty_params = params.iter()
|
||||
.filter_map(|param| match *param {
|
||||
ast::GenericParam::Type(ref t) => Some(t),
|
||||
.filter_map(|param| match param.kind {
|
||||
ast::GenericParamKind::Type { .. } => Some(param),
|
||||
_ => None,
|
||||
})
|
||||
.peekable();
|
||||
|
|
@ -636,12 +634,12 @@ impl<'a> TraitDef<'a> {
|
|||
let mut bounds: Vec<_> = self.additional_bounds
|
||||
.iter()
|
||||
.map(|p| {
|
||||
cx.typarambound(p.to_path(cx, self.span, type_ident, generics))
|
||||
cx.trait_bound(p.to_path(cx, self.span, type_ident, generics))
|
||||
})
|
||||
.collect();
|
||||
|
||||
// require the current trait
|
||||
bounds.push(cx.typarambound(trait_path.clone()));
|
||||
bounds.push(cx.trait_bound(trait_path.clone()));
|
||||
|
||||
let predicate = ast::WhereBoundPredicate {
|
||||
span: self.span,
|
||||
|
|
@ -666,31 +664,18 @@ impl<'a> TraitDef<'a> {
|
|||
// Create the reference to the trait.
|
||||
let trait_ref = cx.trait_ref(trait_path);
|
||||
|
||||
// Create the type parameters on the `self` path.
|
||||
let self_ty_params = generics.params
|
||||
.iter()
|
||||
.filter_map(|param| match *param {
|
||||
GenericParam::Type(ref ty_param)
|
||||
=> Some(cx.ty_ident(self.span, ty_param.ident)),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
|
||||
let self_lifetimes: Vec<ast::Lifetime> = generics.params
|
||||
.iter()
|
||||
.filter_map(|param| match *param {
|
||||
GenericParam::Lifetime(ref ld) => Some(ld.lifetime),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
let self_params: Vec<_> = generics.params.iter().map(|param| match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => {
|
||||
GenericArg::Lifetime(cx.lifetime(self.span, param.ident))
|
||||
}
|
||||
GenericParamKind::Type { .. } => {
|
||||
GenericArg::Type(cx.ty_ident(self.span, param.ident))
|
||||
}
|
||||
}).collect();
|
||||
|
||||
// Create the type of `self`.
|
||||
let self_type = cx.ty_path(cx.path_all(self.span,
|
||||
false,
|
||||
vec![type_ident],
|
||||
self_lifetimes,
|
||||
self_ty_params,
|
||||
Vec::new()));
|
||||
let path = cx.path_all(self.span, false, vec![type_ident], self_params, vec![]);
|
||||
let self_type = cx.ty_path(path);
|
||||
|
||||
let attr = cx.attribute(self.span,
|
||||
cx.meta_word(self.span,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ pub use self::PtrTy::*;
|
|||
pub use self::Ty::*;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::ast::{Expr, GenericParam, Generics, Ident, SelfKind};
|
||||
use syntax::ast::{Expr, GenericParamKind, Generics, Ident, SelfKind, GenericArg};
|
||||
use syntax::ext::base::ExtCtxt;
|
||||
use syntax::ext::build::AstBuilder;
|
||||
use syntax::codemap::{respan, DUMMY_SP};
|
||||
|
|
@ -86,15 +86,20 @@ impl<'a> Path<'a> {
|
|||
-> ast::Path {
|
||||
let mut idents = self.path.iter().map(|s| cx.ident_of(*s)).collect();
|
||||
let lt = mk_lifetimes(cx, span, &self.lifetime);
|
||||
let tys = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect();
|
||||
let tys: Vec<P<ast::Ty>> =
|
||||
self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect();
|
||||
let params = lt.into_iter()
|
||||
.map(|lt| GenericArg::Lifetime(lt))
|
||||
.chain(tys.into_iter().map(|ty| GenericArg::Type(ty)))
|
||||
.collect();
|
||||
|
||||
match self.kind {
|
||||
PathKind::Global => cx.path_all(span, true, idents, lt, tys, Vec::new()),
|
||||
PathKind::Local => cx.path_all(span, false, idents, lt, tys, Vec::new()),
|
||||
PathKind::Global => cx.path_all(span, true, idents, params, Vec::new()),
|
||||
PathKind::Local => cx.path_all(span, false, idents, params, Vec::new()),
|
||||
PathKind::Std => {
|
||||
let def_site = DUMMY_SP.apply_mark(cx.current_expansion.mark);
|
||||
idents.insert(0, Ident::new(keywords::DollarCrate.name(), def_site));
|
||||
cx.path_all(span, false, idents, lt, tys, Vec::new())
|
||||
cx.path_all(span, false, idents, params, Vec::new())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -180,34 +185,22 @@ impl<'a> Ty<'a> {
|
|||
cx: &ExtCtxt,
|
||||
span: Span,
|
||||
self_ty: Ident,
|
||||
self_generics: &Generics)
|
||||
generics: &Generics)
|
||||
-> ast::Path {
|
||||
match *self {
|
||||
Self_ => {
|
||||
let self_params = self_generics.params
|
||||
.iter()
|
||||
.filter_map(|param| match *param {
|
||||
GenericParam::Type(ref ty_param) => Some(cx.ty_ident(span, ty_param.ident)),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
let params: Vec<_> = generics.params.iter().map(|param| match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => {
|
||||
GenericArg::Lifetime(ast::Lifetime { id: param.id, ident: param.ident })
|
||||
}
|
||||
GenericParamKind::Type { .. } => {
|
||||
GenericArg::Type(cx.ty_ident(span, param.ident))
|
||||
}
|
||||
}).collect();
|
||||
|
||||
let lifetimes: Vec<ast::Lifetime> = self_generics.params
|
||||
.iter()
|
||||
.filter_map(|param| match *param {
|
||||
GenericParam::Lifetime(ref ld) => Some(ld.lifetime),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
|
||||
cx.path_all(span,
|
||||
false,
|
||||
vec![self_ty],
|
||||
lifetimes,
|
||||
self_params,
|
||||
Vec::new())
|
||||
cx.path_all(span, false, vec![self_ty], params, vec![])
|
||||
}
|
||||
Literal(ref p) => p.to_path(cx, span, self_ty, self_generics),
|
||||
Literal(ref p) => p.to_path(cx, span, self_ty, generics),
|
||||
Ptr(..) => cx.span_bug(span, "pointer in a path in generic `derive`"),
|
||||
Tuple(..) => cx.span_bug(span, "tuple in a path in generic `derive`"),
|
||||
}
|
||||
|
|
@ -222,17 +215,17 @@ fn mk_ty_param(cx: &ExtCtxt,
|
|||
bounds: &[Path],
|
||||
self_ident: Ident,
|
||||
self_generics: &Generics)
|
||||
-> ast::TyParam {
|
||||
-> ast::GenericParam {
|
||||
let bounds = bounds.iter()
|
||||
.map(|b| {
|
||||
let path = b.to_path(cx, span, self_ident, self_generics);
|
||||
cx.typarambound(path)
|
||||
cx.trait_bound(path)
|
||||
})
|
||||
.collect();
|
||||
cx.typaram(span, cx.ident_of(name), attrs.to_owned(), bounds, None)
|
||||
}
|
||||
|
||||
fn mk_generics(params: Vec<GenericParam>, span: Span) -> Generics {
|
||||
fn mk_generics(params: Vec<ast::GenericParam>, span: Span) -> Generics {
|
||||
Generics {
|
||||
params,
|
||||
where_clause: ast::WhereClause {
|
||||
|
|
@ -268,17 +261,14 @@ impl<'a> LifetimeBounds<'a> {
|
|||
.iter()
|
||||
.map(|&(lt, ref bounds)| {
|
||||
let bounds = bounds.iter()
|
||||
.map(|b| cx.lifetime(span, Ident::from_str(b)))
|
||||
.collect();
|
||||
GenericParam::Lifetime(cx.lifetime_def(span, Ident::from_str(lt), vec![], bounds))
|
||||
.map(|b| ast::GenericBound::Outlives(cx.lifetime(span, Ident::from_str(b))));
|
||||
cx.lifetime_def(span, Ident::from_str(lt), vec![], bounds.collect())
|
||||
})
|
||||
.chain(self.bounds
|
||||
.iter()
|
||||
.map(|t| {
|
||||
let (name, ref bounds) = *t;
|
||||
GenericParam::Type(mk_ty_param(
|
||||
cx, span, name, &[], &bounds, self_ty, self_generics
|
||||
))
|
||||
mk_ty_param(cx, span, name, &[], &bounds, self_ty, self_generics)
|
||||
})
|
||||
)
|
||||
.collect();
|
||||
|
|
|
|||
|
|
@ -134,9 +134,12 @@ fn hygienic_type_parameter(item: &Annotatable, base: &str) -> String {
|
|||
match item.node {
|
||||
ast::ItemKind::Struct(_, ast::Generics { ref params, .. }) |
|
||||
ast::ItemKind::Enum(_, ast::Generics { ref params, .. }) => {
|
||||
for param in params.iter() {
|
||||
if let ast::GenericParam::Type(ref ty) = *param{
|
||||
typaram.push_str(&ty.ident.as_str());
|
||||
for param in params {
|
||||
match param.kind {
|
||||
ast::GenericParamKind::Type { .. } => {
|
||||
typaram.push_str(¶m.ident.as_str());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
// interface.
|
||||
//
|
||||
|
||||
use syntax::ast::{self, Ident};
|
||||
use syntax::ast::{self, Ident, GenericArg};
|
||||
use syntax::ext::base::*;
|
||||
use syntax::ext::base;
|
||||
use syntax::ext::build::AstBuilder;
|
||||
|
|
@ -39,12 +39,11 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt,
|
|||
cx.expr_path(cx.path_all(sp,
|
||||
true,
|
||||
cx.std_path(&["option", "Option", "None"]),
|
||||
Vec::new(),
|
||||
vec![cx.ty_rptr(sp,
|
||||
vec![GenericArg::Type(cx.ty_rptr(sp,
|
||||
cx.ty_ident(sp, Ident::from_str("str")),
|
||||
Some(lt),
|
||||
ast::Mutability::Immutable)],
|
||||
Vec::new()))
|
||||
ast::Mutability::Immutable))],
|
||||
vec![]))
|
||||
}
|
||||
Ok(s) => {
|
||||
cx.expr_call_global(sp,
|
||||
|
|
|
|||
|
|
@ -8,5 +8,5 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// error-pattern: `main` function is not allowed to have type parameters
|
||||
// error-pattern: `main` function is not allowed to have generic parameters
|
||||
fn main<T>() { }
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ struct S04_TyParamBound(S05_PolyTraitRef);
|
|||
struct S05_PolyTraitRef(S06_TraitRef);
|
||||
struct S06_TraitRef(S07_Path);
|
||||
struct S07_Path(Vec<S08_PathSegment>);
|
||||
struct S08_PathSegment(S09_PathParameters);
|
||||
struct S09_PathParameters(P<S10_ParenthesizedParameterData>);
|
||||
struct S08_PathSegment(S09_GenericArgs);
|
||||
struct S09_GenericArgs(P<S10_ParenthesizedParameterData>);
|
||||
struct S10_ParenthesizedParameterData(Option<P<S11_Ty>>);
|
||||
struct S11_Ty(P<S12_Expr>);
|
||||
struct S12_Expr(P<S13_Block>);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ error[E0110]: lifetime parameters are not allowed on this type
|
|||
--> $DIR/E0110.rs:11:14
|
||||
|
|
||||
LL | type X = u32<'static>; //~ ERROR E0110
|
||||
| ^^^^^^^ lifetime parameter not allowed on this type
|
||||
| ^^^^^^^ lifetime parameter not allowed
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
error[E0131]: `main` function is not allowed to have type parameters
|
||||
error[E0131]: `main` function is not allowed to have generic parameters
|
||||
--> $DIR/E0131.rs:11:8
|
||||
|
|
||||
LL | fn main<T>() {
|
||||
| ^^^ `main` cannot have type parameters
|
||||
| ^^^ `main` cannot have generic parameters
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -9,4 +9,4 @@
|
|||
// except according to those terms.
|
||||
|
||||
fn main<'a>() { }
|
||||
//~^ ERROR `main` function is not allowed to have lifetime parameters [E0131]
|
||||
//~^ ERROR `main` function is not allowed to have generic parameters [E0131]
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
error[E0131]: `main` function is not allowed to have lifetime parameters
|
||||
error[E0131]: `main` function is not allowed to have generic parameters
|
||||
--> $DIR/issue-51022.rs:11:8
|
||||
|
|
||||
LL | fn main<'a>() { }
|
||||
| ^^^^ `main` cannot have lifetime parameters
|
||||
| ^^^^ `main` cannot have generic parameters
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -20,13 +20,13 @@ error[E0110]: lifetime parameters are not allowed on this type
|
|||
--> $DIR/collections.rs:33:50
|
||||
|
|
||||
LL | fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>;
|
||||
| ^^^^^ lifetime parameter not allowed on this type
|
||||
| ^^^^^ lifetime parameter not allowed
|
||||
|
||||
error[E0110]: lifetime parameters are not allowed on this type
|
||||
--> $DIR/collections.rs:59:50
|
||||
|
|
||||
LL | fn iterate<'iter>(&'iter self) -> Self::Iter<'iter> {
|
||||
| ^^^^^ lifetime parameter not allowed on this type
|
||||
| ^^^^^ lifetime parameter not allowed
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -2,19 +2,19 @@ error[E0110]: lifetime parameters are not allowed on this type
|
|||
--> $DIR/construct_with_other_type.rs:26:46
|
||||
|
|
||||
LL | type Baa<'a>: Deref<Target = <Self::Quux<'a> as Foo>::Bar<'a, 'static>>;
|
||||
| ^^ lifetime parameter not allowed on this type
|
||||
| ^^ lifetime parameter not allowed
|
||||
|
||||
error[E0110]: lifetime parameters are not allowed on this type
|
||||
--> $DIR/construct_with_other_type.rs:26:63
|
||||
|
|
||||
LL | type Baa<'a>: Deref<Target = <Self::Quux<'a> as Foo>::Bar<'a, 'static>>;
|
||||
| ^^ lifetime parameter not allowed on this type
|
||||
| ^^ lifetime parameter not allowed
|
||||
|
||||
error[E0110]: lifetime parameters are not allowed on this type
|
||||
--> $DIR/construct_with_other_type.rs:34:40
|
||||
|
|
||||
LL | type Baa<'a> = &'a <T as Foo>::Bar<'a, 'static>;
|
||||
| ^^ lifetime parameter not allowed on this type
|
||||
| ^^ lifetime parameter not allowed
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -14,19 +14,19 @@ error[E0110]: lifetime parameters are not allowed on this type
|
|||
--> $DIR/generic_associated_type_undeclared_lifetimes.rs:20:47
|
||||
|
|
||||
LL | type Iter<'a>: Iterator<Item = Self::Item<'a>>
|
||||
| ^^ lifetime parameter not allowed on this type
|
||||
| ^^ lifetime parameter not allowed
|
||||
|
||||
error[E0110]: lifetime parameters are not allowed on this type
|
||||
--> $DIR/generic_associated_type_undeclared_lifetimes.rs:22:37
|
||||
|
|
||||
LL | + Deref<Target = Self::Item<'b>>;
|
||||
| ^^ lifetime parameter not allowed on this type
|
||||
| ^^ lifetime parameter not allowed
|
||||
|
||||
error[E0110]: lifetime parameters are not allowed on this type
|
||||
--> $DIR/generic_associated_type_undeclared_lifetimes.rs:26:41
|
||||
|
|
||||
LL | fn iter<'a>(&'a self) -> Self::Iter<'undeclared>;
|
||||
| ^^^^^^^^^^^ lifetime parameter not allowed on this type
|
||||
| ^^^^^^^^^^^ lifetime parameter not allowed
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -2,37 +2,37 @@ error[E0110]: lifetime parameters are not allowed on this type
|
|||
--> $DIR/iterable.rs:20:47
|
||||
|
|
||||
LL | type Iter<'a>: Iterator<Item = Self::Item<'a>>;
|
||||
| ^^ lifetime parameter not allowed on this type
|
||||
| ^^ lifetime parameter not allowed
|
||||
|
||||
error[E0110]: lifetime parameters are not allowed on this type
|
||||
--> $DIR/iterable.rs:49:53
|
||||
|
|
||||
LL | fn make_iter<'a, I: Iterable>(it: &'a I) -> I::Iter<'a> {
|
||||
| ^^ lifetime parameter not allowed on this type
|
||||
| ^^ lifetime parameter not allowed
|
||||
|
||||
error[E0110]: lifetime parameters are not allowed on this type
|
||||
--> $DIR/iterable.rs:54:60
|
||||
|
|
||||
LL | fn get_first<'a, I: Iterable>(it: &'a I) -> Option<I::Item<'a>> {
|
||||
| ^^ lifetime parameter not allowed on this type
|
||||
| ^^ lifetime parameter not allowed
|
||||
|
||||
error[E0110]: lifetime parameters are not allowed on this type
|
||||
--> $DIR/iterable.rs:23:41
|
||||
|
|
||||
LL | fn iter<'a>(&'a self) -> Self::Iter<'a>;
|
||||
| ^^ lifetime parameter not allowed on this type
|
||||
| ^^ lifetime parameter not allowed
|
||||
|
||||
error[E0110]: lifetime parameters are not allowed on this type
|
||||
--> $DIR/iterable.rs:32:41
|
||||
|
|
||||
LL | fn iter<'a>(&'a self) -> Self::Iter<'a> {
|
||||
| ^^ lifetime parameter not allowed on this type
|
||||
| ^^ lifetime parameter not allowed
|
||||
|
||||
error[E0110]: lifetime parameters are not allowed on this type
|
||||
--> $DIR/iterable.rs:43:41
|
||||
|
|
||||
LL | fn iter<'a>(&'a self) -> Self::Iter<'a> {
|
||||
| ^^ lifetime parameter not allowed on this type
|
||||
| ^^ lifetime parameter not allowed
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,26 @@
|
|||
error[E0110]: lifetime parameters are not allowed on this type
|
||||
--> $DIR/parameter_number_and_kind.rs:26:27
|
||||
|
|
||||
LL | type FOk<T> = Self::E<'static, T>;
|
||||
| ^^^^^^^ lifetime parameter not allowed
|
||||
|
||||
error[E0109]: type parameters are not allowed on this type
|
||||
--> $DIR/parameter_number_and_kind.rs:26:36
|
||||
|
|
||||
LL | type FOk<T> = Self::E<'static, T>;
|
||||
| ^ type parameter not allowed
|
||||
|
||||
error[E0110]: lifetime parameters are not allowed on this type
|
||||
--> $DIR/parameter_number_and_kind.rs:26:27
|
||||
|
|
||||
LL | type FOk<T> = Self::E<'static, T>;
|
||||
| ^^^^^^^ lifetime parameter not allowed on this type
|
||||
|
||||
error[E0110]: lifetime parameters are not allowed on this type
|
||||
--> $DIR/parameter_number_and_kind.rs:29:26
|
||||
|
|
||||
LL | type FErr1 = Self::E<'static, 'static>; // Error
|
||||
| ^^^^^^^ lifetime parameter not allowed on this type
|
||||
| ^^^^^^^ lifetime parameter not allowed
|
||||
|
||||
error[E0110]: lifetime parameters are not allowed on this type
|
||||
--> $DIR/parameter_number_and_kind.rs:31:29
|
||||
|
|
||||
LL | type FErr2<T> = Self::E<'static, T, u32>; // Error
|
||||
| ^^^^^^^ lifetime parameter not allowed
|
||||
|
||||
error[E0109]: type parameters are not allowed on this type
|
||||
--> $DIR/parameter_number_and_kind.rs:31:38
|
||||
|
|
@ -22,12 +28,6 @@ error[E0109]: type parameters are not allowed on this type
|
|||
LL | type FErr2<T> = Self::E<'static, T, u32>; // Error
|
||||
| ^ type parameter not allowed
|
||||
|
||||
error[E0110]: lifetime parameters are not allowed on this type
|
||||
--> $DIR/parameter_number_and_kind.rs:31:29
|
||||
|
|
||||
LL | type FErr2<T> = Self::E<'static, T, u32>; // Error
|
||||
| ^^^^^^^ lifetime parameter not allowed on this type
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors occurred: E0109, E0110.
|
||||
|
|
|
|||
|
|
@ -2,31 +2,31 @@ error[E0110]: lifetime parameters are not allowed on this type
|
|||
--> $DIR/streaming_iterator.rs:27:41
|
||||
|
|
||||
LL | bar: <T as StreamingIterator>::Item<'static>,
|
||||
| ^^^^^^^ lifetime parameter not allowed on this type
|
||||
| ^^^^^^^ lifetime parameter not allowed
|
||||
|
||||
error[E0110]: lifetime parameters are not allowed on this type
|
||||
--> $DIR/streaming_iterator.rs:35:64
|
||||
|
|
||||
LL | fn foo<T>(iter: T) where T: StreamingIterator, for<'a> T::Item<'a>: Display { /* ... */ }
|
||||
| ^^ lifetime parameter not allowed on this type
|
||||
| ^^ lifetime parameter not allowed
|
||||
|
||||
error[E0110]: lifetime parameters are not allowed on this type
|
||||
--> $DIR/streaming_iterator.rs:21:48
|
||||
|
|
||||
LL | fn next<'a>(&'a self) -> Option<Self::Item<'a>>;
|
||||
| ^^ lifetime parameter not allowed on this type
|
||||
| ^^ lifetime parameter not allowed
|
||||
|
||||
error[E0110]: lifetime parameters are not allowed on this type
|
||||
--> $DIR/streaming_iterator.rs:47:37
|
||||
|
|
||||
LL | type Item<'a> = (usize, I::Item<'a>);
|
||||
| ^^ lifetime parameter not allowed on this type
|
||||
| ^^ lifetime parameter not allowed
|
||||
|
||||
error[E0110]: lifetime parameters are not allowed on this type
|
||||
--> $DIR/streaming_iterator.rs:49:48
|
||||
|
|
||||
LL | fn next<'a>(&'a self) -> Option<Self::Item<'a>> {
|
||||
| ^^ lifetime parameter not allowed on this type
|
||||
| ^^ lifetime parameter not allowed
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue