]> git.lizzy.rs Git - rust.git/commitdiff
Optimize `ast::PathSegment`.
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>
Sat, 10 Dec 2016 06:45:58 +0000 (06:45 +0000)
committerJeffrey Seyfried <jeffrey.seyfried@gmail.com>
Mon, 19 Dec 2016 20:57:00 +0000 (20:57 +0000)
14 files changed:
src/librustc/hir/lowering.rs
src/librustc_passes/ast_validation.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/libsyntax/ast.rs
src/libsyntax/ext/build.rs
src/libsyntax/fold.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/std_inject.rs
src/libsyntax/test.rs
src/libsyntax/visit.rs
src/libsyntax_ext/concat_idents.rs

index f5773d351780477c255d70f52d69b308d81775a3..e8c3492705a3f95da1e4886b661479e9748a27c6 100644 (file)
@@ -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 {
index 2d0f0864752ab5739f064b3bc237301369c80cd0..bc150b847786f2c08531e847d08061b2f9600d3d 100644 (file)
@@ -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");
                 }
index d87e04f7b97f9e7b6c694a35ac1ab5cab82794df..821820df8388be92bfa224949e5b95dffc87b57e 100644 (file)
@@ -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
index ce92a4446f92055208f84af7351d872e4716255e..6399a266fcf38fe449931531d1a7de0e40cf0489 100644 (file)
@@ -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);
index 39d78cd87761e4cd124d6f60fa86bda270bfc713..fdd82225b974747990adb31c6a9d8067499011d2 100644 (file)
@@ -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))) }
     }
 }
 
index a208b934d79e1da09b7ca1b31ba069b7aca824dd..c0dfb90024006971679ed8fde5dd7ab90a988d8d 100644 (file)
@@ -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 {
index 6af8efb2a195c6c3408a568b2fa0b8a8f7c04568..b3753e3e977e331cf424d382694f2bcd28ff0c34 100644 (file)
@@ -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)
     }
index c982205f0ecef8e8f135731803971224388d37f4..b9e6605639ead2c8ff0f8ee61cd0814c5df31738 100644 (file)
@@ -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()})),
index a1d4ad9d629c9f973cfaafc84187c63deac0eff2..72462b74e686ca60b1f002f220738dd7e55b162f 100644 (file)
@@ -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() {
index c28b9d00501b70fd6a989f27af86ad170873d3df..22e8391de93ed4910d9fbf988db6e3093392c844 100644 (file)
@@ -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, "::"))
         }
index 6a291ad9c408a372ed1dbd9b7af1b8c59f9a0335..4ad760a3cafe4194ca60be1ec28fb9e5c5c12168 100644 (file)
@@ -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,
         })))),
index fca89e265e4edcfa710694532e46cc8f3d162c48..7709d3bd1cf1ce27e5bcd1492ac54a34a7ad08b8 100644 (file)
@@ -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(),
     }
 }
 
index c1391d0b1c2f18f50bf3094a335e1850c3e32205..ad29cb50a84c80221e308b2b381ed08bed08406e 100644 (file)
@@ -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,
index b26e33eb384dc0017fc942a16ec9e62e0bf9e6c7..1381490efa194b3bd7a1e7850aa35c394bae9a30 100644 (file)
@@ -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()],
             }
         }
     }