Consolidate PathParameters and AngleBracketedParameterData

This commit is contained in:
varkor 2018-02-08 08:58:13 +00:00
parent cca43a7f97
commit 494859e8dd
24 changed files with 363 additions and 174 deletions

View File

@ -650,8 +650,8 @@ pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
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_lifetime, path_parameters.lifetimes());
walk_list!(visitor, visit_ty, path_parameters.types());
walk_list!(visitor, visit_assoc_type_binding, &path_parameters.bindings);
}

View File

@ -46,6 +46,7 @@ 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::GenericPathParam;
use lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES};
use middle::cstore::CrateStore;
use rustc_data_structures::indexed_vec::IndexVec;
@ -1037,6 +1038,20 @@ impl<'a> LoweringContext<'a> {
}
}
fn lower_param(&mut self,
p: &GenericAngleBracketedParam,
itctx: ImplTraitContext)
-> GenericPathParam {
match p {
GenericAngleBracketedParam::Lifetime(lt) => {
GenericPathParam::Lifetime(self.lower_lifetime(&lt))
}
GenericAngleBracketedParam::Type(ty) => {
GenericPathParam::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,
@ -1552,7 +1567,7 @@ impl<'a> LoweringContext<'a> {
assert!(!def_id.is_local());
let item_generics =
self.cstore.item_generics_cloned_untracked(def_id, self.sess);
let n = item_generics.own_counts().lifetimes;
let n = item_generics.own_counts().lifetimes();
self.type_def_lifetime_params.insert(def_id, n);
n
});
@ -1671,7 +1686,7 @@ impl<'a> LoweringContext<'a> {
) -> hir::PathSegment {
let (mut parameters, infer_types) = if let Some(ref parameters) = segment.parameters {
let msg = "parenthesized parameters may only be used with a trait";
match **parameters {
match **path_params {
PathParameters::AngleBracketed(ref data) => {
self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
}
@ -1699,12 +1714,14 @@ impl<'a> LoweringContext<'a> {
};
if !parameters.parenthesized && parameters.lifetimes.is_empty() {
parameters.lifetimes = self.elided_path_lifetimes(path_span, expected_lifetimes);
path_params.parameters = (0..expected_lifetimes).map(|_| {
GenericPathParam::Lifetime(self.elided_lifetime(path_span))
}).chain(path_params.parameters.into_iter()).collect();
}
hir::PathSegment::new(
self.lower_ident(segment.ident),
parameters,
path_params,
infer_types,
)
}
@ -1715,24 +1732,13 @@ impl<'a> LoweringContext<'a> {
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,
)
let &AngleBracketedParameterData { ref parameters, ref bindings, .. } = data;
(hir::PathParameters {
parameters: parameters.iter().map(|p| self.lower_param(p, itctx)).collect(),
bindings: bindings.iter().map(|b| self.lower_ty_binding(b, itctx)).collect(),
parenthesized: false,
},
types.is_empty() && param_mode == ParamMode::Optional)
}
fn lower_parenthesized_parameter_data(
@ -1769,8 +1775,7 @@ impl<'a> LoweringContext<'a> {
(
hir::PathParameters {
lifetimes: hir::HirVec::new(),
types: hir_vec![mk_tup(this, inputs, span)],
parameters: hir_vec![GenericPathParam::Type(mk_tup(this, inputs, span))],
bindings: hir_vec![
hir::TypeBinding {
id: this.next_id().node_id,
@ -1971,7 +1976,7 @@ impl<'a> LoweringContext<'a> {
let def = hir::LifetimeDef {
lifetime: self.lower_lifetime(&l.lifetime),
bounds: self.lower_lifetimes(&l.bounds),
bounds: l.bounds.iter().map(|l| self.lower_lifetime(l)).collect(),
pure_wrt_drop: attr::contains_name(&l.attrs, "may_dangle"),
in_band: false,
};
@ -1981,10 +1986,6 @@ impl<'a> LoweringContext<'a> {
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>,

View File

@ -372,12 +372,16 @@ impl PathSegment {
}
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum GenericPathParam {
Lifetime(Lifetime),
Type(P<Ty>),
}
#[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>>,
/// The generic parameters for this path segment.
pub parameters: HirVec<GenericPathParam>,
/// Bindings (equality constraints) on associated types, if present.
/// E.g., `Foo<A=Bar>`.
pub bindings: HirVec<TypeBinding>,
@ -390,21 +394,19 @@ pub struct PathParameters {
impl PathParameters {
pub fn none() -> Self {
Self {
lifetimes: HirVec::new(),
types: HirVec::new(),
parameters: 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.parameters.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 Some(ref ty) = self.types().get(0) {
if let TyTup(ref tys) = ty.node {
return tys;
}
@ -412,6 +414,26 @@ impl PathParameters {
}
bug!("PathParameters::inputs: not a `Fn(T) -> U`");
}
pub fn lifetimes(&self) -> Vec<&Lifetime> {
self.parameters.iter().filter_map(|p| {
if let GenericPathParam::Lifetime(lt) = p {
Some(lt)
} else {
None
}
}).collect()
}
pub fn types(&self) -> Vec<&P<Ty>> {
self.parameters.iter().filter_map(|p| {
if let GenericPathParam::Type(ty) = p {
Some(ty)
} else {
None
}
}).collect()
}
}
/// The AST represents all type param bounds as types.

View File

@ -25,6 +25,7 @@ use syntax_pos::{self, BytePos, FileName};
use hir;
use hir::{PatKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier, RangeEnd};
use hir::GenericPathParam;
use std::cell::Cell;
use std::io::{self, Write, Read};
@ -1269,8 +1270,7 @@ impl<'a> State<'a> {
self.print_name(segment.name)?;
segment.with_parameters(|parameters| {
if !parameters.lifetimes.is_empty() ||
!parameters.types.is_empty() ||
if !parameters.parameters.is_empty() ||
!parameters.bindings.is_empty()
{
self.print_path_parameters(&parameters, segment.infer_types, true)
@ -1707,18 +1707,18 @@ impl<'a> State<'a> {
}
fn print_path_parameters(&mut self,
parameters: &hir::PathParameters,
path_params: &hir::PathParameters,
infer_types: bool,
colons_before_params: bool)
-> io::Result<()> {
if parameters.parenthesized {
if path_params.parenthesized {
self.s.word("(")?;
self.commasep(Inconsistent, parameters.inputs(), |s, ty| s.print_type(&ty))?;
self.commasep(Inconsistent, path_params.inputs(), |s, ty| s.print_type(&ty))?;
self.s.word(")")?;
self.space_if_not_bol()?;
self.word_space("->")?;
self.print_type(&parameters.bindings[0].ty)?;
self.print_type(&path_params.bindings[0].ty)?;
} else {
let start = if colons_before_params { "::<" } else { "<" };
let empty = Cell::new(true);
@ -1731,17 +1731,27 @@ impl<'a> State<'a> {
}
};
if !parameters.lifetimes.iter().all(|lt| lt.is_elided()) {
for lifetime in &parameters.lifetimes {
start_or_comma(self)?;
self.print_lifetime(lifetime)?;
let elide_lifetimes = path_params.parameters.iter().all(|p| {
if let GenericPathParam::Lifetime(lt) = p {
if !lt.is_elided() {
return false;
}
}
}
true
});
if !parameters.types.is_empty() {
start_or_comma(self)?;
self.commasep(Inconsistent, &parameters.types, |s, ty| s.print_type(&ty))?;
}
self.commasep(Inconsistent, &path_params.parameters, |s, p| {
match p {
GenericPathParam::Lifetime(lt) => {
if !elide_lifetimes {
s.print_lifetime(lt)
} else {
Ok(())
}
}
GenericPathParam::Type(ty) => s.print_type(ty),
}
})?;
// FIXME(eddyb) This would leak into error messages, e.g.:
// "non-exhaustive patterns: `Some::<..>(_)` not covered".
@ -1750,7 +1760,7 @@ impl<'a> State<'a> {
self.s.word("..")?;
}
for binding in parameters.bindings.iter() {
for binding in path_params.bindings.iter() {
start_or_comma(self)?;
self.print_name(binding.name)?;
self.s.space()?;

View File

@ -180,9 +180,13 @@ impl_stable_hash_for!(struct hir::PathSegment {
parameters
});
impl_stable_hash_for!(enum hir::GenericPathParam {
Lifetime(lt),
Type(ty)
});
impl_stable_hash_for!(struct hir::PathParameters {
lifetimes,
types,
parameters,
bindings,
parenthesized
});

View File

@ -155,7 +155,7 @@ impl Region {
}
}
fn subst(self, params: &[hir::Lifetime], map: &NamedRegionMap) -> Option<Region> {
fn subst(self, params: Vec<&hir::Lifetime>, map: &NamedRegionMap) -> Option<Region> {
if let Region::EarlyBound(index, _, _) = self {
params
.get(index as usize)
@ -820,7 +820,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
if lifetime_ref.is_elided() {
self.resolve_elided_lifetimes(slice::from_ref(lifetime_ref), false);
self.resolve_elided_lifetimes(vec![lifetime_ref], false);
return;
}
if lifetime_ref.is_static() {
@ -1613,10 +1613,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
return;
}
if params.lifetimes.iter().all(|l| l.is_elided()) {
self.resolve_elided_lifetimes(&params.lifetimes, true);
if params.lifetimes().iter().all(|l| l.is_elided()) {
self.resolve_elided_lifetimes(params.lifetimes(), true);
} else {
for l in &params.lifetimes {
for l in &params.lifetimes() {
self.visit_lifetime(l);
}
}
@ -1688,13 +1688,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
} else {
Some(Region::Static)
},
Set1::One(r) => r.subst(&params.lifetimes, map),
Set1::One(r) => r.subst(params.lifetimes(), map),
Set1::Many => None,
})
.collect()
});
for (i, ty) in params.types.iter().enumerate() {
for (i, ty) in params.types().iter().enumerate() {
if let Some(&lt) = object_lifetime_defaults.get(i) {
let scope = Scope::ObjectLifetimeDefault {
lifetime: lt,
@ -1981,7 +1981,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
}
}
fn resolve_elided_lifetimes(&mut self, lifetime_refs: &'tcx [hir::Lifetime], deprecated: bool) {
fn resolve_elided_lifetimes(&mut self,
lifetime_refs: Vec<&'tcx hir::Lifetime>,
deprecated: bool) {
if lifetime_refs.is_empty() {
return;
}

View File

@ -885,6 +885,73 @@ pub struct GenericParamCount {
pub types: usize,
}
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum GenericParameterDef {
Lifetime(RegionParameterDef),
Type(TypeParameterDef),
}
impl GenericParameterDef {
pub fn index(&self) -> u32 {
match self {
GenericParameterDef::Lifetime(lt) => lt.index,
GenericParameterDef::Type(ty) => ty.index,
}
}
}
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum KindIndex {
Lifetime,
Type,
}
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct KindIndexed<L, T> {
pub lt: L,
pub ty: T,
}
impl<T> KindIndexed<T, T> {
pub fn get(&self, idx: KindIndex) -> &T {
match idx {
KindIndex::Lifetime => &self.lt,
KindIndex::Type => &self.ty,
}
}
pub fn iter(&self) -> KindIndexIterator<T> {
KindIndexIterator {
index: self,
next: Some(KindIndex::Lifetime),
}
}
}
#[derive(Clone, Debug)]
pub struct KindIndexIterator<'a, T: 'a> {
pub index: &'a KindIndexed<T, T>,
pub next: Option<KindIndex>,
}
impl<'a, T> Iterator for KindIndexIterator<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
match self.next {
Some(KindIndex::Lifetime) => {
self.next = Some(KindIndex::Type);
Some(&self.index.lt)
}
Some(KindIndex::Type) => {
self.next = None;
Some(&self.index.ty)
},
None => None,
}
}
}
/// Information about the formal type/lifetime parameters associated
/// with an item or method. Analogous to hir::Generics.
///
@ -942,6 +1009,34 @@ impl<'a, 'gcx, 'tcx> Generics {
}
}
pub fn lifetimes(&self) -> Vec<&RegionParameterDef> {
self.parameters.iter().filter_map(|p| {
if let GenericParameterDef::Lifetime(lt) = p {
Some(lt)
} else {
None
}
}).collect()
}
pub fn types(&self) -> Vec<&TypeParameterDef> {
self.parameters.iter().filter_map(|p| {
if let GenericParameterDef::Type(ty) = p {
Some(ty)
} else {
None
}
}).collect()
}
pub fn parent_lifetimes(&self) -> u32 {
*self.parent_parameters.get(KindIndex::Lifetime)
}
pub fn parent_types(&self) -> u32 {
*self.parent_parameters.get(KindIndex::Type)
}
pub fn region_param(&'tcx self,
param: &EarlyBoundRegion,
tcx: TyCtxt<'a, 'gcx, 'tcx>)

View File

@ -680,7 +680,7 @@ impl<'a> ReplaceBodyWithLoop<'a> {
match seg.parameters.as_ref().map(|p| &**p) {
None => false,
Some(&ast::PathParameters::AngleBracketed(ref data)) =>
any_involves_impl_trait(data.types.iter()) ||
any_involves_impl_trait(data.types().into_iter()) ||
any_involves_impl_trait(data.bindings.iter().map(|b| &b.ty)),
Some(&ast::PathParameters::Parenthesized(ref data)) =>
any_involves_impl_trait(data.inputs.iter()) ||

View File

@ -822,7 +822,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
for seg in &path.segments {
if let Some(ref params) = seg.parameters {
match **params {
ast::PathParameters::AngleBracketed(ref data) => for t in &data.types {
ast::PathParameters::AngleBracketed(ref data) => for t in data.types() {
self.visit_ty(t);
},
ast::PathParameters::Parenthesized(ref data) => {
@ -907,7 +907,7 @@ 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 {
for t in data.types() {
self.visit_ty(t);
}
}

View File

@ -214,8 +214,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
// 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();
let ty_provided = parameters.types().len();
let lt_provided = parameters.lifetimes().len();
let mut lt_accepted = 0;
let mut ty_params = ParamRange { required: 0, accepted: 0 };
@ -269,7 +269,7 @@ 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) {
if let Some(lifetime) = parameters.lifetimes().get(i) {
self.ast_region_to_region(lifetime, Some(param)).into()
} else {
tcx.types.re_static.into()
@ -286,7 +286,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(&parameters.types[i]).into()
self.ast_ty_to_ty(&parameters.types()[i]).into()
} else if infer_types {
// No type parameters were provided, we can infer all.
if !default_needs_object_self(param) {
@ -970,23 +970,27 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) {
for segment in segments {
segment.with_parameters(|parameters| {
for typ in &parameters.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();
segment.with_parameters(|params| {
for p in &params.parameters {
let (mut span_err, span, kind) = match p {
hir::GenericPathParam::Lifetime(lt) => {
(struct_span_err!(self.tcx().sess, lt.span, E0110,
"lifetime parameters are not allowed on this type"),
lt.span,
"lifetime")
}
hir::GenericPathParam::Type(ty) => {
(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();
break;
}
for lifetime in &parameters.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 &parameters.bindings {
for binding in &params.bindings {
self.prohibit_projection(binding.span);
break;
}

View File

@ -331,7 +331,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
match param.kind {
GenericParamDefKind::Lifetime => {
if let Some(lifetime) = provided.as_ref().and_then(|p| {
p.lifetimes.get(i - parent_substs.len())
p.lifetimes().get(i - parent_substs.len())
}) {
return AstConv::ast_region_to_region(
self.fcx, lifetime, Some(param)).into();
@ -339,7 +339,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
}
GenericParamDefKind::Type {..} => {
if let Some(ast_ty) = provided.as_ref().and_then(|p| {
p.types.get(i - parent_substs.len() - own_counts.lifetimes)
p.types().get(i - parent_substs.len() - own_counts.lifetimes)
}) {
return self.to_ty(ast_ty).into();
}
@ -347,6 +347,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
}
self.var_for_def(self.span, param)
}
self.type_var_for_def(self.span, def, cur_substs)
})
}

View File

@ -4833,8 +4833,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
match param.kind {
GenericParamDefKind::Lifetime => {
let lifetimes = segment.map_or(&[][..], |(s, _)| {
s.parameters.as_ref().map_or(&[][..], |p| &p.lifetimes[..])
let lifetimes = segment.map_or(vec![], |(s, _)| {
s.parameters.as_ref().map_or(vec![], |p| p.lifetimes())
});
if let Some(lifetime) = lifetimes.get(i) {
@ -4844,8 +4844,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
}
GenericParamDefKind::Type {..} => {
let (types, infer_types) = segment.map_or((&[][..], true), |(s, _)| {
(s.parameters.as_ref().map_or(&[][..], |p| &p.types[..]), s.infer_types)
let (types, infer_types) = segment.map_or((vec![], true), |(s, _)| {
(s.parameters.as_ref().map_or(vec![], |p| |p| p.types()), s.infer_types)
});
// Skip over the lifetimes in the same segment.
@ -4961,10 +4961,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
is_method_call: bool,
supress_mismatch_error: bool) {
let (lifetimes, types, infer_types, bindings) = segment.map_or(
(&[][..], &[][..], true, &[][..]),
(vec![], vec![], true, &[][..]),
|(s, _)| s.parameters.as_ref().map_or(
(&[][..], &[][..], s.infer_types, &[][..]),
|p| (&p.lifetimes[..], &p.types[..],
(vec![], vec![], s.infer_types, &[][..]),
|p| (p.lifetimes(), p.types(),
s.infer_types, &p.bindings[..])));
let infer_lifetimes = lifetimes.len() == 0;

View File

@ -973,6 +973,13 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
.map(|param| (param.def_id, param.index))
.collect();
let parent_parameters = ty::KindIndexed { lt: parent_regions, ty: parent_types };
let lifetimes: Vec<ty::GenericParameterDef> =
regions.into_iter().map(|lt| ty::GenericParameterDef::Lifetime(lt)).collect();
let types: Vec<ty::GenericParameterDef> =
types.into_iter().map(|ty| ty::GenericParameterDef::Type(ty)).collect();
let parameters = lifetimes.into_iter().chain(types.into_iter()).collect();
tcx.alloc_generics(ty::Generics {
parent: parent_def_id,
parent_count,

View File

@ -167,21 +167,47 @@ impl PathParameters {
}
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum GenericAngleBracketedParam {
Lifetime(Lifetime),
Type(P<Ty>),
}
/// A path like `Foo<'a, T>`
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Default)]
pub struct AngleBracketedParameterData {
/// 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 parameters for this path segment.
pub parameters: Vec<GenericAngleBracketedParam>,
/// Bindings (equality constraints) on associated types, if present.
///
/// E.g., `Foo<A=Bar>`.
pub bindings: Vec<TypeBinding>,
}
impl AngleBracketedParameterData {
pub fn lifetimes(&self) -> Vec<&Lifetime> {
self.parameters.iter().filter_map(|p| {
if let GenericAngleBracketedParam::Lifetime(lt) = p {
Some(lt)
} else {
None
}
}).collect()
}
pub fn types(&self) -> Vec<&P<Ty>> {
self.parameters.iter().filter_map(|p| {
if let GenericAngleBracketedParam::Type(ty) = p {
Some(ty)
} else {
None
}
}).collect()
}
}
impl Into<Option<P<PathParameters>>> for AngleBracketedParameterData {
fn into(self) -> Option<P<PathParameters>> {
Some(P(PathParameters::AngleBracketed(self)))

View File

@ -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>,
parameters: Vec<ast::GenericAngleBracketedParam>,
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>>,
parameters: Vec<ast::GenericAngleBracketedParam>,
bindings: Vec<ast::TypeBinding>)
-> (ast::QSelf, ast::Path);
@ -304,20 +302,19 @@ 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::new(), Vec::new())
}
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::new(), Vec::new())
}
fn path_all(&self,
span: Span,
global: bool,
mut idents: Vec<ast::Ident> ,
lifetimes: Vec<ast::Lifetime>,
types: Vec<P<ast::Ty>>,
parameters: Vec<ast::GenericAngleBracketedParam>,
bindings: Vec<ast::TypeBinding> )
-> ast::Path {
let last_ident = idents.pop().unwrap();
@ -326,8 +323,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
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 parameters = if !parameters.is_empty() !bindings.is_empty() {
ast::AngleBracketedParameterData { parameters, bindings, span }.into()
} else {
None
};
@ -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,13 +356,12 @@ 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>>,
parameters: Vec<ast::GenericAngleBracketedParam>,
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 parameters = if !parameters.is_empty() || !bindings.is_empty() {
ast::AngleBracketedParameterData { parameters, bindings, span: ident.span }.into()
} else {
None
};
@ -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::GenericAngleBracketedParam::Type(ty) ],
Vec::new()))
}

View File

@ -132,6 +132,10 @@ pub trait Folder : Sized {
noop_fold_exprs(es, self)
}
fn fold_param(&mut self, p: GenericAngleBracketedParam) -> GenericAngleBracketedParam {
noop_fold_param(p, self)
}
fn fold_ty(&mut self, t: P<Ty>) -> P<Ty> {
noop_fold_ty(t, self)
}
@ -353,6 +357,19 @@ pub fn noop_fold_ty_binding<T: Folder>(b: TypeBinding, fld: &mut T) -> TypeBindi
}
}
pub fn noop_fold_param<T: Folder>(p: GenericAngleBracketedParam,
fld: &mut T)
-> GenericAngleBracketedParam {
match p {
GenericAngleBracketedParam::Lifetime(lt) => {
GenericAngleBracketedParam::Lifetime(noop_fold_lifetime(lt, fld))
}
GenericAngleBracketedParam::Type(ty) => {
GenericAngleBracketedParam::Type(noop_fold_ty(ty, fld))
}
}
}
pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
t.map(|Ty {id, node, span}| Ty {
id: fld.new_id(id),
@ -469,9 +486,8 @@ pub fn noop_fold_angle_bracketed_parameter_data<T: Folder>(data: AngleBracketedP
fld: &mut T)
-> AngleBracketedParameterData
{
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)),
let AngleBracketedParameterData { parameters, bindings, span } = data;
AngleBracketedParameterData { parameters: parameters.move_map(|p| fld.fold_param(p)),
bindings: bindings.move_map(|b| fld.fold_ty_binding(b)),
span: fld.new_span(span) }
}

View File

@ -22,6 +22,7 @@ use ast::{Expr, ExprKind, RangeLimits};
use ast::{Field, FnDecl};
use ast::{ForeignItem, ForeignItemKind, FunctionRetTy};
use ast::GenericParam;
use ast::GenericAngleBracketedParam;
use ast::{Ident, ImplItem, IsAuto, Item, ItemKind};
use ast::{Label, Lifetime, LifetimeDef, Lit, LitKind};
use ast::Local;
@ -1971,10 +1972,10 @@ impl<'a> Parser<'a> {
let parameters = if self.eat_lt() {
// `<'a, T, A = U>`
let (lifetimes, types, bindings) = self.parse_generic_args()?;
let (parameters, bindings) = self.parse_generic_args()?;
self.expect_gt()?;
let span = lo.to(self.prev_span);
AngleBracketedParameterData { lifetimes, types, bindings, span }.into()
AngleBracketedParameterData { parameters, bindings, span }.into()
} else {
// `(T, U) -> R`
self.bump(); // `(`
@ -4936,16 +4937,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<GenericAngleBracketedParam>, Vec<TypeBinding>)> {
let mut parameters = 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());
parameters.push(GenericAngleBracketedParam::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 +4966,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");
}
parameters.push(GenericAngleBracketedParam::Type(ty_param));
seen_type = true;
} else {
break
@ -4979,7 +4981,7 @@ impl<'a> Parser<'a> {
break
}
}
Ok((lifetimes, types, bindings))
Ok((parameters, bindings))
}
/// Parses an optional `where` clause and places it in `generics`.

View File

@ -13,7 +13,7 @@ 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::{Attribute, MacDelimiter, GenericAngleBracketedParam};
use util::parser::{self, AssocOp, Fixity};
use attr;
use codemap::{self, CodeMap};
@ -1017,6 +1017,13 @@ impl<'a> State<'a> {
Ok(())
}
pub fn print_param(&mut self, param: &GenericAngleBracketedParam) -> io::Result<()> {
match param {
GenericAngleBracketedParam::Lifetime(lt) => self.print_lifetime(lt),
GenericAngleBracketedParam::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)?;
@ -2474,25 +2481,9 @@ impl<'a> State<'a> {
ast::PathParameters::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.parameters, |s, p| s.print_param(p))?;
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.parameters.len() != 0;
for binding in data.bindings.iter() {
if comma {

View File

@ -387,8 +387,8 @@ pub fn walk_path_parameters<'a, V>(visitor: &mut V,
{
match *path_parameters {
PathParameters::AngleBracketed(ref data) => {
walk_list!(visitor, visit_ty, &data.types);
walk_list!(visitor, visit_lifetime, &data.lifetimes);
walk_list!(visitor, visit_lifetime, data.lifetimes());
walk_list!(visitor, visit_ty, data.types());
walk_list!(visitor, visit_assoc_type_binding, &data.bindings);
}
PathParameters::Parenthesized(ref data) => {

View File

@ -13,6 +13,7 @@ use deriving::generic::*;
use deriving::generic::ty::*;
use syntax::ast::{self, Expr, Generics, ItemKind, MetaItem, VariantData};
use syntax::ast::GenericAngleBracketedParam;
use syntax::attr;
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ext::build::AstBuilder;
@ -123,7 +124,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![GenericAngleBracketedParam::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) {

View File

@ -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, GenericAngleBracketedParam};
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![GenericAngleBracketedParam::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) {

View File

@ -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, GenericParam, Generics, Ident, PatKind};
use syntax::ast::{VariantData, GenericAngleBracketedParam};
use syntax::attr;
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ext::build::AstBuilder;
@ -667,7 +665,7 @@ impl<'a> TraitDef<'a> {
let trait_ref = cx.trait_ref(trait_path);
// Create the type parameters on the `self` path.
let self_ty_params = generics.params
let self_ty_params: Vec<P<ast::Ty>> = generics.params
.iter()
.filter_map(|param| match *param {
GenericParam::Type(ref ty_param)
@ -684,12 +682,17 @@ impl<'a> TraitDef<'a> {
})
.collect();
let self_params = self_lifetimes.into_iter()
.map(|lt| GenericAngleBracketedParam::Lifetime(lt))
.chain(self_ty_params.into_iter().map(|ty|
GenericAngleBracketedParam::Type(ty)))
.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,
self_params,
Vec::new()));
let attr = cx.attribute(self.span,

View File

@ -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, GenericParam, Generics, Ident, SelfKind, GenericAngleBracketedParam};
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| GenericAngleBracketedParam::Lifetime(lt))
.chain(tys.into_iter().map(|ty| GenericAngleBracketedParam::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())
}
}
@ -184,7 +189,7 @@ impl<'a> Ty<'a> {
-> ast::Path {
match *self {
Self_ => {
let self_params = self_generics.params
let ty_params: Vec<P<ast::Ty>> = self_generics.params
.iter()
.filter_map(|param| match *param {
GenericParam::Type(ref ty_param) => Some(cx.ty_ident(span, ty_param.ident)),
@ -200,11 +205,16 @@ impl<'a> Ty<'a> {
})
.collect();
let params = lifetimes.into_iter()
.map(|lt| GenericAngleBracketedParam::Lifetime(lt))
.chain(ty_params.into_iter().map(|ty|
GenericAngleBracketedParam::Type(ty)))
.collect();
cx.path_all(span,
false,
vec![self_ty],
lifetimes,
self_params,
params,
Vec::new())
}
Literal(ref p) => p.to_path(cx, span, self_ty, self_generics),

View File

@ -13,7 +13,7 @@
// interface.
//
use syntax::ast::{self, Ident};
use syntax::ast::{self, Ident, GenericAngleBracketedParam};
use syntax::ext::base::*;
use syntax::ext::base;
use syntax::ext::build::AstBuilder;
@ -39,8 +39,7 @@ 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![GenericAngleBracketedParam::Type(cx.ty_rptr(sp,
cx.ty_ident(sp, Ident::from_str("str")),
Some(lt),
ast::Mutability::Immutable)],