segment: &PathSegment,
param_mode: ParamMode)
-> hir::PathSegment {
- let parameters = match segment.parameters {
- PathParameters::AngleBracketed(ref data) => {
- let data = self.lower_angle_bracketed_parameter_data(data, param_mode);
- hir::AngleBracketedParameters(data)
+ let parameters = if let Some(ref parameters) = segment.parameters {
+ match **parameters {
+ PathParameters::AngleBracketed(ref data) => {
+ let data = self.lower_angle_bracketed_parameter_data(data, param_mode);
+ hir::AngleBracketedParameters(data)
+ }
+ PathParameters::Parenthesized(ref data) => {
+ hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data))
+ }
}
- PathParameters::Parenthesized(ref data) =>
- hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data)),
+ } else {
+ let data = self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode);
+ hir::AngleBracketedParameters(data)
};
hir::PathSegment {
match item.node {
ItemKind::Use(ref view_path) => {
let path = view_path.node.path();
- if !path.segments.iter().all(|segment| segment.parameters.is_empty()) {
+ if path.segments.iter().any(|segment| segment.parameters.is_some()) {
self.err_handler()
.span_err(path.span, "type or lifetime parameters in import path");
}
fn visit_vis(&mut self, vis: &'a Visibility) {
match *vis {
Visibility::Restricted { ref path, .. } => {
- if !path.segments.iter().all(|segment| segment.parameters.is_empty()) {
+ if !path.segments.iter().all(|segment| segment.parameters.is_none()) {
self.err_handler()
.span_err(path.span, "type or lifetime parameters in visibility path");
}
use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, Generics};
use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
use syntax::ast::{Local, Mutability, Pat, PatKind, Path};
-use syntax::ast::{PathSegment, PathParameters, QSelf, TraitItemKind, TraitRef, Ty, TyKind};
+use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
use syntax_pos::{Span, DUMMY_SP};
use errors::DiagnosticBuilder;
if ident.name == lookup_name && ns == namespace {
if filter_fn(name_binding.def()) {
// create the path
- let params = PathParameters::none();
- let segment = PathSegment {
- identifier: ident,
- parameters: params,
- };
let span = name_binding.span;
let mut segms = path_segments.clone();
- segms.push(segment);
+ segms.push(ident.into());
let path = Path {
span: span,
global: false,
if let Some(module) = name_binding.module() {
// form the path
let mut path_segments = path_segments.clone();
- path_segments.push(PathSegment {
- identifier: ident,
- parameters: PathParameters::none(),
- });
+ path_segments.push(ident.into());
if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
// add the module to the lookup
fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
-> Result<Rc<SyntaxExtension>, Determinacy> {
let ast::Path { ref segments, global, span } = *path;
- if segments.iter().any(|segment| !segment.parameters.is_empty()) {
+ if segments.iter().any(|segment| segment.parameters.is_some()) {
let kind =
- if segments.last().unwrap().parameters.is_empty() { "module" } else { "macro" };
+ if segments.last().unwrap().parameters.is_some() { "macro" } else { "module" };
let msg = format!("type parameters are not allowed on {}s", kind);
self.session.span_err(path.span, &msg);
return Err(Determinacy::Determined);
Path {
span: s,
global: false,
- segments: vec![
- PathSegment {
- identifier: identifier,
- parameters: PathParameters::none()
- }
- ],
+ segments: vec![identifier.into()],
}
}
}
/// this is more than just simple syntactic sugar; the use of
/// parens affects the region binding rules, so we preserve the
/// distinction.
- pub parameters: PathParameters,
+ /// The `Option<P<..>>` wrapper is purely a size optimization;
+ /// `None` is used to represent both `Path` and `Path<>`.
+ pub parameters: Option<P<PathParameters>>,
+}
+
+impl From<Ident> for PathSegment {
+ fn from(id: Ident) -> Self {
+ PathSegment { identifier: id, parameters: None }
+ }
}
/// Parameters of a path segment.
Parenthesized(ParenthesizedParameterData),
}
-impl PathParameters {
- pub fn none() -> PathParameters {
- PathParameters::AngleBracketed(AngleBracketedParameterData {
- lifetimes: Vec::new(),
- types: P::new(),
- bindings: P::new(),
- })
- }
-
- pub fn is_empty(&self) -> bool {
- match *self {
- PathParameters::AngleBracketed(ref data) => data.is_empty(),
-
- // Even if the user supplied no types, something like
- // `X()` is equivalent to `X<(),()>`.
- PathParameters::Parenthesized(..) => false,
- }
- }
-
- pub fn has_lifetimes(&self) -> bool {
- match *self {
- PathParameters::AngleBracketed(ref data) => !data.lifetimes.is_empty(),
- PathParameters::Parenthesized(_) => false,
- }
- }
-
- pub fn has_types(&self) -> bool {
- match *self {
- PathParameters::AngleBracketed(ref data) => !data.types.is_empty(),
- PathParameters::Parenthesized(..) => true,
- }
- }
-
- /// Returns the types that the user wrote. Note that these do not necessarily map to the type
- /// parameters in the parenthesized case.
- pub fn types(&self) -> Vec<&P<Ty>> {
- match *self {
- PathParameters::AngleBracketed(ref data) => {
- data.types.iter().collect()
- }
- PathParameters::Parenthesized(ref data) => {
- data.inputs.iter()
- .chain(data.output.iter())
- .collect()
- }
- }
- }
-
- pub fn lifetimes(&self) -> Vec<&Lifetime> {
- match *self {
- PathParameters::AngleBracketed(ref data) => {
- data.lifetimes.iter().collect()
- }
- PathParameters::Parenthesized(_) => {
- Vec::new()
- }
- }
- }
-
- pub fn bindings(&self) -> Vec<&TypeBinding> {
- match *self {
- PathParameters::AngleBracketed(ref data) => {
- data.bindings.iter().collect()
- }
- PathParameters::Parenthesized(_) => {
- Vec::new()
- }
- }
- }
-}
-
/// A path like `Foo<'a, T>`
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Default)]
pub struct AngleBracketedParameterData {
/// The lifetime parameters for this path segment.
pub lifetimes: Vec<Lifetime>,
pub bindings: P<[TypeBinding]>,
}
-impl AngleBracketedParameterData {
- fn is_empty(&self) -> bool {
- self.lifetimes.is_empty() && self.types.is_empty() && self.bindings.is_empty()
+impl Into<Option<P<PathParameters>>> for AngleBracketedParameterData {
+ fn into(self) -> Option<P<PathParameters>> {
+ let empty = self.lifetimes.is_empty() && self.types.is_empty() && self.bindings.is_empty();
+ if empty { None } else { Some(P(PathParameters::AngleBracketed(self))) }
}
}
bindings: Vec<ast::TypeBinding> )
-> ast::Path {
let last_identifier = idents.pop().unwrap();
- let mut segments: Vec<ast::PathSegment> = idents.into_iter()
- .map(|ident| {
- ast::PathSegment {
- identifier: ident,
- parameters: ast::PathParameters::none(),
- }
- }).collect();
- segments.push(ast::PathSegment {
- identifier: last_identifier,
- parameters: ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
+ let mut segments: Vec<ast::PathSegment> = idents.into_iter().map(Into::into).collect();
+ let parameters = if lifetimes.is_empty() && types.is_empty() && bindings.is_empty() {
+ None
+ } else {
+ Some(P(ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
lifetimes: lifetimes,
types: P::from_vec(types),
bindings: P::from_vec(bindings),
- })
- });
+ })))
+ };
+ segments.push(ast::PathSegment { identifier: last_identifier, parameters: parameters });
ast::Path {
span: sp,
global: global,
bindings: Vec<ast::TypeBinding>)
-> (ast::QSelf, ast::Path) {
let mut path = trait_path;
+ let parameters = ast::AngleBracketedParameterData {
+ lifetimes: lifetimes,
+ types: P::from_vec(types),
+ bindings: P::from_vec(bindings),
+ };
path.segments.push(ast::PathSegment {
identifier: ident,
- parameters: ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
- lifetimes: lifetimes,
- types: P::from_vec(types),
- bindings: P::from_vec(bindings),
- })
+ parameters: Some(P(ast::PathParameters::AngleBracketed(parameters))),
});
(ast::QSelf {
global: global,
segments: segments.move_map(|PathSegment {identifier, parameters}| PathSegment {
identifier: fld.fold_ident(identifier),
- parameters: fld.fold_path_parameters(parameters),
+ parameters: parameters.map(|ps| ps.map(|ps| fld.fold_path_parameters(ps))),
}),
span: fld.new_span(span)
}
node: ast::ExprKind::Path(None, ast::Path {
span: sp(0, 1),
global: false,
- segments: vec![
- ast::PathSegment {
- identifier: Ident::from_str("a"),
- parameters: ast::PathParameters::none(),
- }
- ],
+ segments: vec![Ident::from_str("a").into()],
}),
span: sp(0, 1),
attrs: ThinVec::new(),
P(ast::Expr {
id: ast::DUMMY_NODE_ID,
node: ast::ExprKind::Path(None, ast::Path {
- span: sp(0, 6),
- global: true,
- segments: vec![
- ast::PathSegment {
- identifier: Ident::from_str("a"),
- parameters: ast::PathParameters::none(),
- },
- ast::PathSegment {
- identifier: Ident::from_str("b"),
- parameters: ast::PathParameters::none(),
- }
- ]
- }),
+ span: sp(0, 6),
+ global: true,
+ segments: vec![Ident::from_str("a").into(), Ident::from_str("b").into()],
+ }),
span: sp(0, 6),
attrs: ThinVec::new(),
}))
node:ast::ExprKind::Path(None, ast::Path{
span: sp(7, 8),
global: false,
- segments: vec![
- ast::PathSegment {
- identifier: Ident::from_str("d"),
- parameters: ast::PathParameters::none(),
- }
- ],
+ segments: vec![Ident::from_str("d").into()],
}),
span:sp(7,8),
attrs: ThinVec::new(),
node: ast::ExprKind::Path(None, ast::Path {
span:sp(0,1),
global:false,
- segments: vec![
- ast::PathSegment {
- identifier: Ident::from_str("b"),
- parameters: ast::PathParameters::none(),
- }
- ],
+ segments: vec![Ident::from_str("b").into()],
}),
span: sp(0,1),
attrs: ThinVec::new()})),
node: ast::TyKind::Path(None, ast::Path{
span:sp(10,13),
global:false,
- segments: vec![
- ast::PathSegment {
- identifier: Ident::from_str("i32"),
- parameters: ast::PathParameters::none(),
- }
- ],
+ segments: vec![Ident::from_str("i32").into()],
}),
span:sp(10,13)
}),
ast::Path{
span:sp(17,18),
global:false,
- segments: vec![
- ast::PathSegment {
- identifier: Ident::from_str("b"),
- parameters:
- ast::PathParameters::none(),
- }
- ],
+ segments: vec![Ident::from_str("b").into()],
}),
span: sp(17,18),
attrs: ThinVec::new()})),
// Parse types, optionally.
let parameters = if self.eat_lt() {
let (lifetimes, types, bindings) = self.parse_generic_values_after_lt()?;
-
- ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
+ ast::AngleBracketedParameterData {
lifetimes: lifetimes,
types: P::from_vec(types),
bindings: P::from_vec(bindings),
- })
+ }.into()
} else if self.eat(&token::OpenDelim(token::Paren)) {
let lo = self.prev_span.lo;
let hi = self.prev_span.hi;
- ast::PathParameters::Parenthesized(ast::ParenthesizedParameterData {
+ Some(P(ast::PathParameters::Parenthesized(ast::ParenthesizedParameterData {
span: mk_sp(lo, hi),
inputs: inputs,
output: output_ty,
- })
+ })))
} else {
- ast::PathParameters::none()
+ None
};
// Assemble and push the result.
- segments.push(ast::PathSegment { identifier: identifier,
- parameters: parameters });
+ segments.push(ast::PathSegment { identifier: identifier, parameters: parameters });
// Continue only if we see a `::`
if !self.eat(&token::ModSep) {
// If we do not see a `::`, stop.
if !self.eat(&token::ModSep) {
- segments.push(ast::PathSegment {
- identifier: identifier,
- parameters: ast::PathParameters::none()
- });
+ segments.push(identifier.into());
return Ok(segments);
}
if self.eat_lt() {
// Consumed `a::b::<`, go look for types
let (lifetimes, types, bindings) = self.parse_generic_values_after_lt()?;
- let parameters = ast::AngleBracketedParameterData {
- lifetimes: lifetimes,
- types: P::from_vec(types),
- bindings: P::from_vec(bindings),
- };
segments.push(ast::PathSegment {
identifier: identifier,
- parameters: ast::PathParameters::AngleBracketed(parameters),
+ parameters: ast::AngleBracketedParameterData {
+ lifetimes: lifetimes,
+ types: P::from_vec(types),
+ bindings: P::from_vec(bindings),
+ }.into(),
});
// Consumed `a::b::<T,U>`, check for `::` before proceeding
}
} else {
// Consumed `a::`, go look for `b`
- segments.push(ast::PathSegment {
- identifier: identifier,
- parameters: ast::PathParameters::none(),
- });
+ segments.push(identifier.into());
}
}
}
let identifier = self.parse_path_segment_ident()?;
// Assemble and push the result.
- segments.push(ast::PathSegment {
- identifier: identifier,
- parameters: ast::PathParameters::none()
- });
+ segments.push(identifier.into());
// If we do not see a `::` or see `::{`/`::*`, stop.
if !self.check(&token::ModSep) || self.is_import_coupler() {
try!(self.print_ident(segment.identifier));
- try!(self.print_path_parameters(&segment.parameters, colons_before_params));
+ if let Some(ref parameters) = segment.parameters {
+ try!(self.print_path_parameters(parameters, colons_before_params))
+ }
}
Ok(())
try!(word(&mut self.s, "::"));
let item_segment = path.segments.last().unwrap();
try!(self.print_ident(item_segment.identifier));
- self.print_path_parameters(&item_segment.parameters, colons_before_params)
+ match item_segment.parameters {
+ Some(ref parameters) => self.print_path_parameters(parameters, colons_before_params),
+ None => Ok(()),
+ }
}
fn print_path_parameters(&mut self,
colons_before_params: bool)
-> io::Result<()>
{
- if parameters.is_empty() {
- return Ok(());
- }
-
if colons_before_params {
try!(word(&mut self.s, "::"))
}
vis: ast::Visibility::Inherited,
node: ast::ItemKind::Use(P(codemap::dummy_spanned(ast::ViewPathGlob(ast::Path {
global: false,
- segments: vec![name, "prelude", "v1"].into_iter().map(|name| ast::PathSegment {
- identifier: ast::Ident::from_str(name),
- parameters: ast::PathParameters::none(),
+ segments: vec![name, "prelude", "v1"].into_iter().map(|name| {
+ ast::Ident::from_str(name).into()
}).collect(),
span: span,
})))),
ast::Path {
span: DUMMY_SP,
global: false,
- segments: ids.into_iter().map(|identifier| ast::PathSegment {
- identifier: identifier,
- parameters: ast::PathParameters::none(),
- }).collect()
+ segments: ids.into_iter().map(Into::into).collect(),
}
}
path_span: Span,
segment: &'a PathSegment) {
visitor.visit_ident(path_span, segment.identifier);
- visitor.visit_path_parameters(path_span, &segment.parameters);
+ if let Some(ref parameters) = segment.parameters {
+ visitor.visit_path_parameters(path_span, parameters);
+ }
}
pub fn walk_path_parameters<'a, V>(visitor: &mut V,
impl Result {
fn path(&self) -> ast::Path {
- let segment = ast::PathSegment {
- identifier: self.ident,
- parameters: ast::PathParameters::none(),
- };
ast::Path {
span: self.span,
global: false,
- segments: vec![segment],
+ segments: vec![self.ident.into()],
}
}
}