提交 8e61ff25 编写于 作者: J Jeffrey Seyfried

Optimize `ast::PathSegment`.

上级 dcae8bfb
......@@ -433,13 +433,19 @@ fn lower_path_segment(&mut self,
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 {
......
......@@ -171,7 +171,7 @@ fn visit_item(&mut self, item: &'a Item) {
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");
}
......@@ -275,7 +275,7 @@ fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
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");
}
......
......@@ -62,7 +62,7 @@
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;
......@@ -2960,14 +2960,9 @@ fn lookup_candidates<FilterFn>(&mut self,
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,
......@@ -2990,10 +2985,7 @@ fn lookup_candidates<FilterFn>(&mut self,
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
......
......@@ -183,9 +183,9 @@ fn find_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>) -> Option<ast::At
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);
......
......@@ -137,12 +137,7 @@ pub fn from_ident(s: Span, identifier: Ident) -> Path {
Path {
span: s,
global: false,
segments: vec![
PathSegment {
identifier: identifier,
parameters: PathParameters::none()
}
],
segments: vec![identifier.into()],
}
}
}
......@@ -160,7 +155,15 @@ 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: 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.
......@@ -174,79 +177,8 @@ pub enum PathParameters {
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>,
......@@ -258,9 +190,10 @@ pub struct AngleBracketedParameterData {
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))) }
}
}
......
......@@ -322,21 +322,17 @@ fn path_all(&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,
......@@ -367,13 +363,14 @@ fn qpath_all(&self,
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 {
......
......@@ -438,7 +438,7 @@ pub fn noop_fold_path<T: Folder>(Path {global, segments, span}: Path, fld: &mut
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)
}
......
......@@ -634,12 +634,7 @@ fn sp(a: u32, b: u32) -> 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(),
......@@ -651,19 +646,10 @@ fn sp(a: u32, b: u32) -> Span {
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(),
}))
......@@ -772,12 +758,7 @@ fn string_to_tts_1() {
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(),
......@@ -795,12 +776,7 @@ fn string_to_tts_1() {
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()})),
......@@ -842,12 +818,7 @@ fn parser_done(p: Parser){
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)
}),
......@@ -890,13 +861,7 @@ fn parser_done(p: Parser){
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()})),
......
......@@ -1705,12 +1705,11 @@ pub fn parse_path_segments_without_colons(&mut self) -> PResult<'a, Vec<ast::Pat
// 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;
......@@ -1727,18 +1726,17 @@ pub fn parse_path_segments_without_colons(&mut self) -> PResult<'a, Vec<ast::Pat
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) {
......@@ -1757,10 +1755,7 @@ pub fn parse_path_segments_with_colons(&mut self) -> PResult<'a, Vec<ast::PathSe
// 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);
}
......@@ -1768,14 +1763,13 @@ pub fn parse_path_segments_with_colons(&mut self) -> PResult<'a, Vec<ast::PathSe
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
......@@ -1784,10 +1778,7 @@ pub fn parse_path_segments_with_colons(&mut self) -> PResult<'a, Vec<ast::PathSe
}
} else {
// Consumed `a::`, go look for `b`
segments.push(ast::PathSegment {
identifier: identifier,
parameters: ast::PathParameters::none(),
});
segments.push(identifier.into());
}
}
}
......@@ -1802,10 +1793,7 @@ pub fn parse_path_segments_without_types(&mut self)
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() {
......
......@@ -2349,7 +2349,9 @@ fn print_path(&mut self,
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(())
......@@ -2373,7 +2375,10 @@ fn print_qpath(&mut self,
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,
......@@ -2381,10 +2386,6 @@ 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, "::"))
}
......
......@@ -81,9 +81,8 @@ pub fn maybe_inject_crates_ref(sess: &ParseSess,
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,
})))),
......
......@@ -580,10 +580,7 @@ fn path_node(ids: Vec<Ident>) -> ast::Path {
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(),
}
}
......
......@@ -383,7 +383,9 @@ pub fn walk_path_segment<'a, V: Visitor<'a>>(visitor: &mut V,
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,
......
......@@ -59,14 +59,10 @@ struct Result {
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()],
}
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册