about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2014-03-22 09:20:22 -0700
committerAlex Crichton <alex@alexcrichton.com>2014-03-26 14:51:41 -0700
commit8118406ecf1fedf2949e8e6fa014086ac7b557e8 (patch)
tree9424dc0d698a79d5b3c8d99b5972f731e789fabc /src/libsyntax
parente233a43f5a0e14ceb322b955b16c8967adb2f4a8 (diff)
syntax: Tweak parsing bounds on generics paths
The previous syntax was `Foo:Bound<trait-parameters>`, but this is a little
ambiguous because it was being parsed as `Foo: (Bound<trait-parameters)` rather
than `Foo: (Bound) <trait-parameters>`

This commit changes the syntax to `Foo<trait-parameters>: Bound` in order to be
clear where the trait parameters are going.

Closes #9265
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/parse/parser.rs73
-rw-r--r--src/libsyntax/print/pprust.rs16
2 files changed, 24 insertions, 65 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index c8492cc4113..57b2c21e03b 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -112,13 +112,6 @@ pub enum PathParsingMode {
     LifetimeAndTypesAndBounds,
 }
 
-/// A pair of a path segment and group of type parameter bounds. (See `ast.rs`
-/// for the definition of a path segment.)
-struct PathSegmentAndBoundSet {
-    segment: ast::PathSegment,
-    bound_set: Option<OwnedSlice<TyParamBound>>,
-}
-
 /// A path paired with optional type bounds.
 pub struct PathAndBounds {
     path: ast::Path,
@@ -1515,24 +1508,14 @@ impl<'a> Parser<'a> {
             // First, parse an identifier.
             let identifier = self.parse_ident();
 
-            // Next, parse a colon and bounded type parameters, if applicable.
-            let bound_set = if mode == LifetimeAndTypesAndBounds {
-                self.parse_optional_ty_param_bounds()
-            } else {
-                None
-            };
-
             // Parse the '::' before type parameters if it's required. If
             // it is required and wasn't present, then we're done.
             if mode == LifetimeAndTypesWithColons &&
                     !self.eat(&token::MOD_SEP) {
-                segments.push(PathSegmentAndBoundSet {
-                    segment: ast::PathSegment {
-                        identifier: identifier,
-                        lifetimes: Vec::new(),
-                        types: OwnedSlice::empty(),
-                    },
-                    bound_set: bound_set
+                segments.push(ast::PathSegment {
+                    identifier: identifier,
+                    lifetimes: Vec::new(),
+                    types: OwnedSlice::empty(),
                 });
                 break
             }
@@ -1549,13 +1532,10 @@ impl<'a> Parser<'a> {
             };
 
             // Assemble and push the result.
-            segments.push(PathSegmentAndBoundSet {
-                segment: ast::PathSegment {
-                    identifier: identifier,
-                    lifetimes: lifetimes,
-                    types: types,
-                },
-                bound_set: bound_set
+            segments.push(ast::PathSegment {
+                identifier: identifier,
+                lifetimes: lifetimes,
+                types: types,
             });
 
             // We're done if we don't see a '::', unless the mode required
@@ -1568,42 +1548,25 @@ impl<'a> Parser<'a> {
             }
         }
 
+        // Next, parse a colon and bounded type parameters, if applicable.
+        let bounds = if mode == LifetimeAndTypesAndBounds {
+            self.parse_optional_ty_param_bounds()
+        } else {
+            None
+        };
+
         // Assemble the span.
         let span = mk_sp(lo, self.last_span.hi);
 
-        // Assemble the path segments.
-        let mut path_segments = Vec::new();
-        let mut bounds = None;
-        let last_segment_index = segments.len() - 1;
-        for (i, segment_and_bounds) in segments.move_iter().enumerate() {
-            let PathSegmentAndBoundSet {
-                segment: segment,
-                bound_set: bound_set
-            } = segment_and_bounds;
-            path_segments.push(segment);
-
-            if bound_set.is_some() {
-                if i != last_segment_index {
-                    self.span_err(span,
-                                  "type parameter bounds are allowed only \
-                                   before the last segment in a path")
-                }
-
-                bounds = bound_set
-            }
-        }
-
         // Assemble the result.
-        let path_and_bounds = PathAndBounds {
+        PathAndBounds {
             path: ast::Path {
                 span: span,
                 global: is_global,
-                segments: path_segments,
+                segments: segments,
             },
             bounds: bounds,
-        };
-
-        path_and_bounds
+        }
     }
 
     /// parses 0 or 1 lifetime
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 9cecd5f6c2b..655cde3cbed 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1525,7 +1525,7 @@ impl<'a> State<'a> {
         }
 
         let mut first = true;
-        for (i, segment) in path.segments.iter().enumerate() {
+        for segment in path.segments.iter() {
             if first {
                 first = false
             } else {
@@ -1534,14 +1534,6 @@ impl<'a> State<'a> {
 
             try!(self.print_ident(segment.identifier));
 
-            // If this is the last segment, print the bounds.
-            if i == path.segments.len() - 1 {
-                match *opt_bounds {
-                    None => {}
-                    Some(ref bounds) => try!(self.print_bounds(bounds, true)),
-                }
-            }
-
             if !segment.lifetimes.is_empty() || !segment.types.is_empty() {
                 if colons_before_params {
                     try!(word(&mut self.s, "::"))
@@ -1570,7 +1562,11 @@ impl<'a> State<'a> {
                 try!(word(&mut self.s, ">"))
             }
         }
-        Ok(())
+
+        match *opt_bounds {
+            None => Ok(()),
+            Some(ref bounds) => self.print_bounds(bounds, true),
+        }
     }
 
     fn print_path(&mut self, path: &ast::Path,