about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libsyntax/parse/parser.rs73
-rw-r--r--src/libsyntax/print/pprust.rs16
-rw-r--r--src/test/compile-fail/kindck-owned-trait-contains.rs4
-rw-r--r--src/test/run-pass/alignment-gep-tup-like-1.rs4
-rw-r--r--src/test/run-pass/close-over-big-then-small-data.rs4
-rw-r--r--src/test/run-pass/kindck-owned-trait-contains-1.rs4
-rw-r--r--src/test/run-pass/parameterized-trait-with-bounds.rs27
7 files changed, 59 insertions, 73 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 9b12987361e..d6ccea7331d 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -111,13 +111,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,
@@ -1514,24 +1507,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
             }
@@ -1548,13 +1531,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
@@ -1567,42 +1547,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 e1d6f821ba9..6309f83abdd 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1526,7 +1526,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 {
@@ -1535,14 +1535,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, "::"))
@@ -1571,7 +1563,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,
diff --git a/src/test/compile-fail/kindck-owned-trait-contains.rs b/src/test/compile-fail/kindck-owned-trait-contains.rs
index ed1725f3240..e2005cbae91 100644
--- a/src/test/compile-fail/kindck-owned-trait-contains.rs
+++ b/src/test/compile-fail/kindck-owned-trait-contains.rs
@@ -14,8 +14,8 @@ impl<A:Clone> Repeat<A> for A {
     fn get(&self) -> A { self.clone() }
 }
 
-fn repeater<A:Clone>(v: A) -> ~Repeat:<A> {
-    ~v as ~Repeat:<A> // No
+fn repeater<A:Clone>(v: A) -> ~Repeat<A>: {
+    ~v as ~Repeat<A>: // No
 }
 
 fn main() {
diff --git a/src/test/run-pass/alignment-gep-tup-like-1.rs b/src/test/run-pass/alignment-gep-tup-like-1.rs
index a0233360a7c..2c71d791cd4 100644
--- a/src/test/run-pass/alignment-gep-tup-like-1.rs
+++ b/src/test/run-pass/alignment-gep-tup-like-1.rs
@@ -27,11 +27,11 @@ impl<A:Clone> Invokable<A> for Invoker<A> {
     }
 }
 
-fn f<A:Clone + 'static>(a: A, b: u16) -> ~Invokable:<A> {
+fn f<A:Clone + 'static>(a: A, b: u16) -> ~Invokable<A>: {
     ~Invoker {
         a: a,
         b: b,
-    } as ~Invokable:<A>
+    } as ~Invokable<A>:
 }
 
 pub fn main() {
diff --git a/src/test/run-pass/close-over-big-then-small-data.rs b/src/test/run-pass/close-over-big-then-small-data.rs
index ea75ae2fc5c..c57b6fdf384 100644
--- a/src/test/run-pass/close-over-big-then-small-data.rs
+++ b/src/test/run-pass/close-over-big-then-small-data.rs
@@ -31,11 +31,11 @@ impl<A:Clone> Invokable<A> for Invoker<A> {
     }
 }
 
-fn f<A:Clone + 'static>(a: A, b: u16) -> ~Invokable:<A> {
+fn f<A:Clone + 'static>(a: A, b: u16) -> ~Invokable<A>: {
     ~Invoker {
         a: a,
         b: b,
-    } as ~Invokable:<A>
+    } as ~Invokable<A>:
 }
 
 pub fn main() {
diff --git a/src/test/run-pass/kindck-owned-trait-contains-1.rs b/src/test/run-pass/kindck-owned-trait-contains-1.rs
index 0a7e164ca5b..e4a7e7af14f 100644
--- a/src/test/run-pass/kindck-owned-trait-contains-1.rs
+++ b/src/test/run-pass/kindck-owned-trait-contains-1.rs
@@ -16,9 +16,9 @@ impl<A:Clone + 'static> repeat<A> for ~A {
     }
 }
 
-fn repeater<A:Clone + 'static>(v: ~A) -> ~repeat:<A> {
+fn repeater<A:Clone + 'static>(v: ~A) -> ~repeat<A>: {
     // Note: owned kind is not necessary as A appears in the trait type
-    ~v as ~repeat:<A> // No
+    ~v as ~repeat<A>: // No
 }
 
 pub fn main() {
diff --git a/src/test/run-pass/parameterized-trait-with-bounds.rs b/src/test/run-pass/parameterized-trait-with-bounds.rs
new file mode 100644
index 00000000000..6200d04c802
--- /dev/null
+++ b/src/test/run-pass/parameterized-trait-with-bounds.rs
@@ -0,0 +1,27 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[allow(dead_code)];
+
+trait A<T> {}
+trait B<T, U> {}
+trait C<'a, U> {}
+
+mod foo {
+    pub trait D<'a, T> {}
+}
+
+fn foo1<T>(_: &A<T>: Send) {}
+fn foo2<T>(_: ~A<T>: Send + Share) {}
+fn foo3<T>(_: ~B<int, uint>: 'static) {}
+fn foo4<'a, T>(_: ~C<'a, T>: 'static + Send) {}
+fn foo5<'a, T>(_: ~foo::D<'a, T>: 'static + Send) {}
+
+pub fn main() {}