about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libsyntax/ext/tt/macro_parser.rs4
-rw-r--r--src/libsyntax/parse/parser.rs39
-rw-r--r--src/test/compile-fail/issue-32995.rs8
-rw-r--r--src/test/compile-fail/issue-36116.rs28
-rw-r--r--src/test/compile-fail/unboxed-closure-sugar-used-on-struct-3.rs (renamed from src/test/parse-fail/unboxed-closure-sugar-used-on-struct-3.rs)12
-rw-r--r--src/test/parse-fail/type-parameters-in-field-exprs.rs2
6 files changed, 49 insertions, 44 deletions
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index aea48632d5d..405d06dafbf 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -599,9 +599,7 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
                 panic!(FatalError)
             }
         },
-        "path" => {
-            token::NtPath(panictry!(p.parse_path(PathStyle::Type)))
-        },
+        "path" => token::NtPath(panictry!(p.parse_path_common(PathStyle::Type, false))),
         "meta" => token::NtMeta(panictry!(p.parse_meta_item())),
         "vis" => token::NtVis(panictry!(p.parse_visibility(true))),
         // this is not supposed to happen, since it has been checked
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index e251d136f23..84e3d8ddf70 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -84,7 +84,7 @@ pub enum PathStyle {
     Expr,
     /// In other contexts, notably in types, no ambiguity exists and paths can be written
     /// without the disambiguator, e.g. `x<y>` - unambiguously a path.
-    /// Paths with disambiguators are rejected for now, but may be allowed in the future.
+    /// Paths with disambiguators are still accepted, `x::<Y>` - unambiguously a path too.
     Type,
     /// A path with generic arguments disallowed, e.g. `foo::bar::Baz`, used in imports,
     /// visibilities or attributes.
@@ -1755,7 +1755,7 @@ impl<'a> Parser<'a> {
         self.expect(&token::ModSep)?;
 
         let qself = QSelf { ty, position: path.segments.len() };
-        self.parse_path_segments(&mut path.segments, style)?;
+        self.parse_path_segments(&mut path.segments, style, true)?;
 
         Ok((qself, ast::Path { segments: path.segments, span: lo.to(self.prev_span) }))
     }
@@ -1770,8 +1770,12 @@ impl<'a> Parser<'a> {
     /// `a::b::C::<D>` (with disambiguator)
     /// `Fn(Args)` (without disambiguator)
     /// `Fn::(Args)` (with disambiguator)
-    pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, ast::Path>
-    {
+    pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, ast::Path> {
+        self.parse_path_common(style, true)
+    }
+
+    pub fn parse_path_common(&mut self, style: PathStyle, enable_warning: bool)
+                             -> PResult<'a, ast::Path> {
         maybe_whole!(self, NtPath, |x| x);
 
         let lo = self.meta_var_span.unwrap_or(self.span);
@@ -1779,7 +1783,7 @@ impl<'a> Parser<'a> {
         if self.eat(&token::ModSep) {
             segments.push(PathSegment::crate_root(lo));
         }
-        self.parse_path_segments(&mut segments, style)?;
+        self.parse_path_segments(&mut segments, style, enable_warning)?;
 
         Ok(ast::Path { segments, span: lo.to(self.prev_span) })
     }
@@ -1804,10 +1808,10 @@ impl<'a> Parser<'a> {
         self.parse_path(style)
     }
 
-    fn parse_path_segments(&mut self, segments: &mut Vec<PathSegment>, style: PathStyle)
-                           -> PResult<'a, ()> {
+    fn parse_path_segments(&mut self, segments: &mut Vec<PathSegment>, style: PathStyle,
+                           enable_warning: bool) -> PResult<'a, ()> {
         loop {
-            segments.push(self.parse_path_segment(style)?);
+            segments.push(self.parse_path_segment(style, enable_warning)?);
 
             if self.is_import_coupler() || !self.eat(&token::ModSep) {
                 return Ok(());
@@ -1815,7 +1819,8 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, PathSegment> {
+    fn parse_path_segment(&mut self, style: PathStyle, enable_warning: bool)
+                          -> PResult<'a, PathSegment> {
         let ident_span = self.span;
         let ident = self.parse_path_segment_ident()?;
 
@@ -1835,17 +1840,9 @@ impl<'a> Parser<'a> {
                                       && self.look_ahead(1, |t| is_args_start(t)) {
             // Generic arguments are found - `<`, `(`, `::<` or `::(`.
             let lo = self.span;
-            if self.eat(&token::ModSep) {
-                // These errors are not strictly necessary and may be removed in the future.
-                if style == PathStyle::Type {
-                    let mut err = self.diagnostic().struct_span_err(self.prev_span,
-                        "unnecessary path disambiguator");
-                    err.span_label(self.prev_span, "try removing `::`");
-                    err.emit();
-                } else if self.token == token::OpenDelim(token::Paren) {
-                    self.diagnostic().span_err(self.prev_span,
-                        "`::` is not supported before parenthesized generic arguments")
-                }
+            if self.eat(&token::ModSep) && style == PathStyle::Type && enable_warning {
+                self.diagnostic().struct_span_warn(self.prev_span, "unnecessary path disambiguator")
+                                 .span_label(self.prev_span, "try removing `::`").emit();
             }
 
             let parameters = if self.eat_lt() {
@@ -2382,7 +2379,7 @@ impl<'a> Parser<'a> {
 
     // Assuming we have just parsed `.`, continue parsing into an expression.
     fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
-        let segment = self.parse_path_segment(PathStyle::Expr)?;
+        let segment = self.parse_path_segment(PathStyle::Expr, true)?;
         Ok(match self.token {
             token::OpenDelim(token::Paren) => {
                 // Method call `expr.f()`
diff --git a/src/test/compile-fail/issue-32995.rs b/src/test/compile-fail/issue-32995.rs
index 4b7f82943ba..ffbd0c0c22a 100644
--- a/src/test/compile-fail/issue-32995.rs
+++ b/src/test/compile-fail/issue-32995.rs
@@ -19,15 +19,11 @@ fn main() {
     //~^ ERROR parenthesized parameters may only be used with a trait
     //~| WARN previously accepted
 
-    macro_rules! pathexpr {
-        ($p:path) => { $p }
-    }
-
-    let p = pathexpr!(::std::str()::from_utf8)(b"foo").unwrap();
+    let p = ::std::str::()::from_utf8(b"foo").unwrap();
     //~^ ERROR parenthesized parameters may only be used with a trait
     //~| WARN previously accepted
 
-    let p = pathexpr!(::std::str::from_utf8())(b"foo").unwrap();
+    let p = ::std::str::from_utf8::()(b"foo").unwrap();
     //~^ ERROR parenthesized parameters may only be used with a trait
     //~| WARN previously accepted
 
diff --git a/src/test/compile-fail/issue-36116.rs b/src/test/compile-fail/issue-36116.rs
index 737955b2ff3..3afbfa61984 100644
--- a/src/test/compile-fail/issue-36116.rs
+++ b/src/test/compile-fail/issue-36116.rs
@@ -8,16 +8,30 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// Unnecessary path disambiguator is ok
+
+#![feature(rustc_attrs)]
+#![allow(unused)]
+
+macro_rules! m {
+    ($p: path) => {
+        let _ = $p(0);
+        let _: $p;
+    }
+}
+
 struct Foo<T> {
     _a: T,
 }
 
-fn main() {
-    let f = Some(Foo { _a: 42 }).map(|a| a as Foo::<i32>);
-    //~^ ERROR unnecessary path disambiguator
-    //~| NOTE try removing `::`
+struct S<T>(T);
+
+fn f() {
+    let f = Some(Foo { _a: 42 }).map(|a| a as Foo::<i32>); //~ WARN unnecessary path disambiguator
+    let g: Foo::<i32> = Foo { _a: 42 }; //~ WARN unnecessary path disambiguator
 
-    let g: Foo::<i32> = Foo { _a: 42 };
-    //~^ ERROR unnecessary path disambiguator
-    //~| NOTE try removing `::`
+    m!(S::<u8>); // OK, no warning
 }
+
+#[rustc_error]
+fn main() {} //~ ERROR compilation successful
diff --git a/src/test/parse-fail/unboxed-closure-sugar-used-on-struct-3.rs b/src/test/compile-fail/unboxed-closure-sugar-used-on-struct-3.rs
index 548a5078a74..42fffe546c2 100644
--- a/src/test/parse-fail/unboxed-closure-sugar-used-on-struct-3.rs
+++ b/src/test/compile-fail/unboxed-closure-sugar-used-on-struct-3.rs
@@ -8,9 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z parse-only
-
-// Test that parentheses form doesn't work in expression paths.
+// Test that parentheses form parses in expression paths.
 
 struct Bar<A,R> {
     f: A, r: R
@@ -21,10 +19,10 @@ impl<A,B> Bar<A,B> {
 }
 
 fn bar() {
-    let b = Box::Bar::<isize,usize>::new(); // OK
+    let b = Bar::<isize, usize>::new(); // OK
 
-    let b = Box::Bar::()::new();
-    //~^ ERROR `::` is not supported before parenthesized generic arguments
+    let b = Bar::(isize, usize)::new(); // OK too (for the parser)
+    //~^ ERROR parenthesized parameters may only be used with a trait
 }
 
-fn main() { }
+fn main() {}
diff --git a/src/test/parse-fail/type-parameters-in-field-exprs.rs b/src/test/parse-fail/type-parameters-in-field-exprs.rs
index 95c307c5670..cb018ff1bfa 100644
--- a/src/test/parse-fail/type-parameters-in-field-exprs.rs
+++ b/src/test/parse-fail/type-parameters-in-field-exprs.rs
@@ -24,4 +24,6 @@ fn main() {
     //~^ ERROR field expressions may not have generic arguments
     f.x::<>;
     //~^ ERROR field expressions may not have generic arguments
+    f.x::();
+    //~^ ERROR field expressions may not have generic arguments
 }