Skip to content

Commit 8e61ff2

Browse files
committed
Optimize ast::PathSegment.
1 parent dcae8bf commit 8e61ff2

File tree

14 files changed

+86
-210
lines changed

14 files changed

+86
-210
lines changed

src/librustc/hir/lowering.rs

+12-6
Original file line numberDiff line numberDiff line change
@@ -433,13 +433,19 @@ impl<'a> LoweringContext<'a> {
433433
segment: &PathSegment,
434434
param_mode: ParamMode)
435435
-> hir::PathSegment {
436-
let parameters = match segment.parameters {
437-
PathParameters::AngleBracketed(ref data) => {
438-
let data = self.lower_angle_bracketed_parameter_data(data, param_mode);
439-
hir::AngleBracketedParameters(data)
436+
let parameters = if let Some(ref parameters) = segment.parameters {
437+
match **parameters {
438+
PathParameters::AngleBracketed(ref data) => {
439+
let data = self.lower_angle_bracketed_parameter_data(data, param_mode);
440+
hir::AngleBracketedParameters(data)
441+
}
442+
PathParameters::Parenthesized(ref data) => {
443+
hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data))
444+
}
440445
}
441-
PathParameters::Parenthesized(ref data) =>
442-
hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data)),
446+
} else {
447+
let data = self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode);
448+
hir::AngleBracketedParameters(data)
443449
};
444450

445451
hir::PathSegment {

src/librustc_passes/ast_validation.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
171171
match item.node {
172172
ItemKind::Use(ref view_path) => {
173173
let path = view_path.node.path();
174-
if !path.segments.iter().all(|segment| segment.parameters.is_empty()) {
174+
if path.segments.iter().any(|segment| segment.parameters.is_some()) {
175175
self.err_handler()
176176
.span_err(path.span, "type or lifetime parameters in import path");
177177
}
@@ -275,7 +275,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
275275
fn visit_vis(&mut self, vis: &'a Visibility) {
276276
match *vis {
277277
Visibility::Restricted { ref path, .. } => {
278-
if !path.segments.iter().all(|segment| segment.parameters.is_empty()) {
278+
if !path.segments.iter().all(|segment| segment.parameters.is_none()) {
279279
self.err_handler()
280280
.span_err(path.span, "type or lifetime parameters in visibility path");
281281
}

src/librustc_resolve/lib.rs

+3-11
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ use syntax::ast::{Arm, BindingMode, Block, Crate, Expr, ExprKind};
6262
use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, Generics};
6363
use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
6464
use syntax::ast::{Local, Mutability, Pat, PatKind, Path};
65-
use syntax::ast::{PathSegment, PathParameters, QSelf, TraitItemKind, TraitRef, Ty, TyKind};
65+
use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
6666

6767
use syntax_pos::{Span, DUMMY_SP};
6868
use errors::DiagnosticBuilder;
@@ -2960,14 +2960,9 @@ impl<'a> Resolver<'a> {
29602960
if ident.name == lookup_name && ns == namespace {
29612961
if filter_fn(name_binding.def()) {
29622962
// create the path
2963-
let params = PathParameters::none();
2964-
let segment = PathSegment {
2965-
identifier: ident,
2966-
parameters: params,
2967-
};
29682963
let span = name_binding.span;
29692964
let mut segms = path_segments.clone();
2970-
segms.push(segment);
2965+
segms.push(ident.into());
29712966
let path = Path {
29722967
span: span,
29732968
global: false,
@@ -2990,10 +2985,7 @@ impl<'a> Resolver<'a> {
29902985
if let Some(module) = name_binding.module() {
29912986
// form the path
29922987
let mut path_segments = path_segments.clone();
2993-
path_segments.push(PathSegment {
2994-
identifier: ident,
2995-
parameters: PathParameters::none(),
2996-
});
2988+
path_segments.push(ident.into());
29972989

29982990
if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
29992991
// add the module to the lookup

src/librustc_resolve/macros.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,9 @@ impl<'a> base::Resolver for Resolver<'a> {
183183
fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
184184
-> Result<Rc<SyntaxExtension>, Determinacy> {
185185
let ast::Path { ref segments, global, span } = *path;
186-
if segments.iter().any(|segment| !segment.parameters.is_empty()) {
186+
if segments.iter().any(|segment| segment.parameters.is_some()) {
187187
let kind =
188-
if segments.last().unwrap().parameters.is_empty() { "module" } else { "macro" };
188+
if segments.last().unwrap().parameters.is_some() { "macro" } else { "module" };
189189
let msg = format!("type parameters are not allowed on {}s", kind);
190190
self.session.span_err(path.span, &msg);
191191
return Err(Determinacy::Determined);

src/libsyntax/ast.rs

+15-82
Original file line numberDiff line numberDiff line change
@@ -137,12 +137,7 @@ impl Path {
137137
Path {
138138
span: s,
139139
global: false,
140-
segments: vec![
141-
PathSegment {
142-
identifier: identifier,
143-
parameters: PathParameters::none()
144-
}
145-
],
140+
segments: vec![identifier.into()],
146141
}
147142
}
148143
}
@@ -160,7 +155,15 @@ pub struct PathSegment {
160155
/// this is more than just simple syntactic sugar; the use of
161156
/// parens affects the region binding rules, so we preserve the
162157
/// distinction.
163-
pub parameters: PathParameters,
158+
/// The `Option<P<..>>` wrapper is purely a size optimization;
159+
/// `None` is used to represent both `Path` and `Path<>`.
160+
pub parameters: Option<P<PathParameters>>,
161+
}
162+
163+
impl From<Ident> for PathSegment {
164+
fn from(id: Ident) -> Self {
165+
PathSegment { identifier: id, parameters: None }
166+
}
164167
}
165168

166169
/// Parameters of a path segment.
@@ -174,79 +177,8 @@ pub enum PathParameters {
174177
Parenthesized(ParenthesizedParameterData),
175178
}
176179

177-
impl PathParameters {
178-
pub fn none() -> PathParameters {
179-
PathParameters::AngleBracketed(AngleBracketedParameterData {
180-
lifetimes: Vec::new(),
181-
types: P::new(),
182-
bindings: P::new(),
183-
})
184-
}
185-
186-
pub fn is_empty(&self) -> bool {
187-
match *self {
188-
PathParameters::AngleBracketed(ref data) => data.is_empty(),
189-
190-
// Even if the user supplied no types, something like
191-
// `X()` is equivalent to `X<(),()>`.
192-
PathParameters::Parenthesized(..) => false,
193-
}
194-
}
195-
196-
pub fn has_lifetimes(&self) -> bool {
197-
match *self {
198-
PathParameters::AngleBracketed(ref data) => !data.lifetimes.is_empty(),
199-
PathParameters::Parenthesized(_) => false,
200-
}
201-
}
202-
203-
pub fn has_types(&self) -> bool {
204-
match *self {
205-
PathParameters::AngleBracketed(ref data) => !data.types.is_empty(),
206-
PathParameters::Parenthesized(..) => true,
207-
}
208-
}
209-
210-
/// Returns the types that the user wrote. Note that these do not necessarily map to the type
211-
/// parameters in the parenthesized case.
212-
pub fn types(&self) -> Vec<&P<Ty>> {
213-
match *self {
214-
PathParameters::AngleBracketed(ref data) => {
215-
data.types.iter().collect()
216-
}
217-
PathParameters::Parenthesized(ref data) => {
218-
data.inputs.iter()
219-
.chain(data.output.iter())
220-
.collect()
221-
}
222-
}
223-
}
224-
225-
pub fn lifetimes(&self) -> Vec<&Lifetime> {
226-
match *self {
227-
PathParameters::AngleBracketed(ref data) => {
228-
data.lifetimes.iter().collect()
229-
}
230-
PathParameters::Parenthesized(_) => {
231-
Vec::new()
232-
}
233-
}
234-
}
235-
236-
pub fn bindings(&self) -> Vec<&TypeBinding> {
237-
match *self {
238-
PathParameters::AngleBracketed(ref data) => {
239-
data.bindings.iter().collect()
240-
}
241-
PathParameters::Parenthesized(_) => {
242-
Vec::new()
243-
}
244-
}
245-
}
246-
}
247-
248180
/// A path like `Foo<'a, T>`
249-
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
181+
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Default)]
250182
pub struct AngleBracketedParameterData {
251183
/// The lifetime parameters for this path segment.
252184
pub lifetimes: Vec<Lifetime>,
@@ -258,9 +190,10 @@ pub struct AngleBracketedParameterData {
258190
pub bindings: P<[TypeBinding]>,
259191
}
260192

261-
impl AngleBracketedParameterData {
262-
fn is_empty(&self) -> bool {
263-
self.lifetimes.is_empty() && self.types.is_empty() && self.bindings.is_empty()
193+
impl Into<Option<P<PathParameters>>> for AngleBracketedParameterData {
194+
fn into(self) -> Option<P<PathParameters>> {
195+
let empty = self.lifetimes.is_empty() && self.types.is_empty() && self.bindings.is_empty();
196+
if empty { None } else { Some(P(PathParameters::AngleBracketed(self))) }
264197
}
265198
}
266199

src/libsyntax/ext/build.rs

+14-17
Original file line numberDiff line numberDiff line change
@@ -322,21 +322,17 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
322322
bindings: Vec<ast::TypeBinding> )
323323
-> ast::Path {
324324
let last_identifier = idents.pop().unwrap();
325-
let mut segments: Vec<ast::PathSegment> = idents.into_iter()
326-
.map(|ident| {
327-
ast::PathSegment {
328-
identifier: ident,
329-
parameters: ast::PathParameters::none(),
330-
}
331-
}).collect();
332-
segments.push(ast::PathSegment {
333-
identifier: last_identifier,
334-
parameters: ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
325+
let mut segments: Vec<ast::PathSegment> = idents.into_iter().map(Into::into).collect();
326+
let parameters = if lifetimes.is_empty() && types.is_empty() && bindings.is_empty() {
327+
None
328+
} else {
329+
Some(P(ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
335330
lifetimes: lifetimes,
336331
types: P::from_vec(types),
337332
bindings: P::from_vec(bindings),
338-
})
339-
});
333+
})))
334+
};
335+
segments.push(ast::PathSegment { identifier: last_identifier, parameters: parameters });
340336
ast::Path {
341337
span: sp,
342338
global: global,
@@ -367,13 +363,14 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
367363
bindings: Vec<ast::TypeBinding>)
368364
-> (ast::QSelf, ast::Path) {
369365
let mut path = trait_path;
366+
let parameters = ast::AngleBracketedParameterData {
367+
lifetimes: lifetimes,
368+
types: P::from_vec(types),
369+
bindings: P::from_vec(bindings),
370+
};
370371
path.segments.push(ast::PathSegment {
371372
identifier: ident,
372-
parameters: ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
373-
lifetimes: lifetimes,
374-
types: P::from_vec(types),
375-
bindings: P::from_vec(bindings),
376-
})
373+
parameters: Some(P(ast::PathParameters::AngleBracketed(parameters))),
377374
});
378375

379376
(ast::QSelf {

src/libsyntax/fold.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ pub fn noop_fold_path<T: Folder>(Path {global, segments, span}: Path, fld: &mut
438438
global: global,
439439
segments: segments.move_map(|PathSegment {identifier, parameters}| PathSegment {
440440
identifier: fld.fold_ident(identifier),
441-
parameters: fld.fold_path_parameters(parameters),
441+
parameters: parameters.map(|ps| ps.map(|ps| fld.fold_path_parameters(ps))),
442442
}),
443443
span: fld.new_span(span)
444444
}

src/libsyntax/parse/mod.rs

+9-44
Original file line numberDiff line numberDiff line change
@@ -634,12 +634,7 @@ mod tests {
634634
node: ast::ExprKind::Path(None, ast::Path {
635635
span: sp(0, 1),
636636
global: false,
637-
segments: vec![
638-
ast::PathSegment {
639-
identifier: Ident::from_str("a"),
640-
parameters: ast::PathParameters::none(),
641-
}
642-
],
637+
segments: vec![Ident::from_str("a").into()],
643638
}),
644639
span: sp(0, 1),
645640
attrs: ThinVec::new(),
@@ -651,19 +646,10 @@ mod tests {
651646
P(ast::Expr {
652647
id: ast::DUMMY_NODE_ID,
653648
node: ast::ExprKind::Path(None, ast::Path {
654-
span: sp(0, 6),
655-
global: true,
656-
segments: vec![
657-
ast::PathSegment {
658-
identifier: Ident::from_str("a"),
659-
parameters: ast::PathParameters::none(),
660-
},
661-
ast::PathSegment {
662-
identifier: Ident::from_str("b"),
663-
parameters: ast::PathParameters::none(),
664-
}
665-
]
666-
}),
649+
span: sp(0, 6),
650+
global: true,
651+
segments: vec![Ident::from_str("a").into(), Ident::from_str("b").into()],
652+
}),
667653
span: sp(0, 6),
668654
attrs: ThinVec::new(),
669655
}))
@@ -772,12 +758,7 @@ mod tests {
772758
node:ast::ExprKind::Path(None, ast::Path{
773759
span: sp(7, 8),
774760
global: false,
775-
segments: vec![
776-
ast::PathSegment {
777-
identifier: Ident::from_str("d"),
778-
parameters: ast::PathParameters::none(),
779-
}
780-
],
761+
segments: vec![Ident::from_str("d").into()],
781762
}),
782763
span:sp(7,8),
783764
attrs: ThinVec::new(),
@@ -795,12 +776,7 @@ mod tests {
795776
node: ast::ExprKind::Path(None, ast::Path {
796777
span:sp(0,1),
797778
global:false,
798-
segments: vec![
799-
ast::PathSegment {
800-
identifier: Ident::from_str("b"),
801-
parameters: ast::PathParameters::none(),
802-
}
803-
],
779+
segments: vec![Ident::from_str("b").into()],
804780
}),
805781
span: sp(0,1),
806782
attrs: ThinVec::new()})),
@@ -842,12 +818,7 @@ mod tests {
842818
node: ast::TyKind::Path(None, ast::Path{
843819
span:sp(10,13),
844820
global:false,
845-
segments: vec![
846-
ast::PathSegment {
847-
identifier: Ident::from_str("i32"),
848-
parameters: ast::PathParameters::none(),
849-
}
850-
],
821+
segments: vec![Ident::from_str("i32").into()],
851822
}),
852823
span:sp(10,13)
853824
}),
@@ -890,13 +861,7 @@ mod tests {
890861
ast::Path{
891862
span:sp(17,18),
892863
global:false,
893-
segments: vec![
894-
ast::PathSegment {
895-
identifier: Ident::from_str("b"),
896-
parameters:
897-
ast::PathParameters::none(),
898-
}
899-
],
864+
segments: vec![Ident::from_str("b").into()],
900865
}),
901866
span: sp(17,18),
902867
attrs: ThinVec::new()})),

0 commit comments

Comments
 (0)