提交 494859e8 编写于 作者: V varkor

Consolidate PathParameters and AngleBracketedParameterData

上级 cca43a7f
......@@ -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);
}
......
......@@ -46,6 +46,7 @@
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 @@ fn lower_ty_binding(&mut self, b: &TypeBinding, itctx: ImplTraitContext) -> hir:
}
}
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 @@ fn lower_qpath(
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 @@ fn lower_path_segment(
) -> 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 @@ fn lower_path_segment(
};
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 @@ fn lower_angle_bracketed_parameter_data(
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 @@ fn lower_parenthesized_parameter_data(
(
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 @@ fn lower_lifetime_def(&mut self, l: &LifetimeDef) -> hir::LifetimeDef {
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 @@ fn lower_lifetime_def(&mut self, l: &LifetimeDef) -> hir::LifetimeDef {
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>,
......
......@@ -372,12 +372,16 @@ pub fn with_parameters<F, R>(&self, f: F) -> R
}
}
#[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 @@ pub fn inputs(&self) -> &[P<Ty>] {
}
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.
......
......@@ -25,6 +25,7 @@
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 @@ fn print_expr_method_call(&mut self,
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 @@ pub fn print_qpath(&mut self,
}
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 @@ fn print_path_parameters(&mut self,
}
};
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;
}
}
}
if !parameters.types.is_empty() {
start_or_comma(self)?;
self.commasep(Inconsistent, &parameters.types, |s, ty| s.print_type(&ty))?;
}
true
});
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 @@ fn print_path_parameters(&mut self,
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()?;
......
......@@ -180,9 +180,13 @@ fn hash_stable<W: StableHasherResult>(&self,
parameters
});
impl_stable_hash_for!(enum hir::GenericPathParam {
Lifetime(lt),
Type(ty)
});
impl_stable_hash_for!(struct hir::PathParameters {
lifetimes,
types,
parameters,
bindings,
parenthesized
});
......
......@@ -155,7 +155,7 @@ fn shifted_out_to_binder(self, binder: ty::DebruijnIndex) -> 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 @@ fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
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 @@ fn visit_segment_parameters(
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 @@ fn visit_segment_parameters(
} 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 @@ fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) {
}
}
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;
}
......
......@@ -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 @@ pub fn requires_monomorphization(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
}
}
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>)
......
......@@ -680,7 +680,7 @@ fn involves_impl_trait(ty: &ast::Ty) -> bool {
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()) ||
......
......@@ -822,7 +822,7 @@ fn process_path(&mut self, id: NodeId, path: &'l ast::Path) {
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 @@ fn process_method_call(
// 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);
}
}
......
......@@ -214,8 +214,8 @@ fn create_substs_for_ast_path(&self,
// 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 @@ fn create_substs_for_ast_path(&self,
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 @@ fn create_substs_for_ast_path(&self,
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 @@ fn qpath_to_ty(&self,
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();
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();
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 binding in &parameters.bindings {
for binding in &params.bindings {
self.prohibit_projection(binding.span);
break;
}
......
......@@ -331,7 +331,7 @@ fn instantiate_method_substs(
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 @@ fn instantiate_method_substs(
}
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 @@ fn instantiate_method_substs(
}
self.var_for_def(self.span, param)
}
self.type_var_for_def(self.span, def, cur_substs)
})
}
......
......@@ -4833,8 +4833,8 @@ pub fn instantiate_value_path(&self,
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 @@ pub fn instantiate_value_path(&self,
}
}
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 @@ fn check_path_parameter_count(&self,
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;
......
......@@ -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,
......
......@@ -167,21 +167,47 @@ pub fn span(&self) -> Span {
}
}
#[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)))
......
......@@ -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 @@ fn qpath(&self, self_type: P<ast::Ty>,
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 @@ fn item_use_glob(&self, sp: Span,
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 @@ fn path_all(&self,
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 @@ fn qpath(&self,
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 @@ 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) {
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 @@ fn ty_option(&self, ty: P<ast::Ty>) -> P<ast::Ty> {
self.path_all(DUMMY_SP,
true,
self.std_path(&["option", "Option"]),
Vec::new(),
vec![ ty ],
vec![ ast::GenericAngleBracketedParam::Type(ty) ],
Vec::new()))
}
......
......@@ -132,6 +132,10 @@ fn fold_exprs(&mut self, es: Vec<P<Expr>>) -> Vec<P<Expr>> {
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) }
}
......
......@@ -22,6 +22,7 @@
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 @@ fn parse_path_segment(&mut self, style: PathStyle, enable_warning: bool)
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 @@ fn parse_generics(&mut self) -> PResult<'a, ast::Generics> {
/// 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 @@ fn parse_generic_args(&mut self) -> PResult<'a, (Vec<Lifetime>, Vec<P<Ty>>, Vec<
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 @@ fn parse_generic_args(&mut self) -> PResult<'a, (Vec<Lifetime>, Vec<P<Ty>>, Vec<
break
}
}
Ok((lifetimes, types, bindings))
Ok((parameters, bindings))
}
/// Parses an optional `where` clause and places it in `generics`.
......
......@@ -13,7 +13,7 @@
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 @@ pub fn print_opt_lifetime(&mut self,
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 @@ fn print_path_parameters(&mut self,
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 {
......
......@@ -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) => {
......
......@@ -13,6 +13,7 @@
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 assert_ty_bounds(cx: &mut ExtCtxt, stmts: &mut Vec<ast::Stmt>,
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) {
......
......@@ -12,7 +12,7 @@
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 assert_ty_bounds(cx: &mut ExtCtxt, stmts: &mut Vec<ast::Stmt>,
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) {
......
......@@ -192,10 +192,8 @@
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 @@ fn create_derived_impl(&self,
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 @@ fn create_derived_impl(&self,
})
.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,
......
......@@ -15,7 +15,7 @@
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 @@ pub fn to_path(&self,
-> 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 @@ pub fn to_path(&self,
-> 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 @@ pub fn to_path(&self,
})
.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),
......
......@@ -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)],
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册