]> git.lizzy.rs Git - rust.git/commitdiff
Issue warnings for unnecessary path disambiguators
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Thu, 10 Aug 2017 23:30:08 +0000 (02:30 +0300)
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Thu, 10 Aug 2017 23:47:22 +0000 (02:47 +0300)
src/libsyntax/ext/tt/macro_parser.rs
src/libsyntax/parse/parser.rs
src/test/compile-fail/issue-36116.rs

index 146bd5d985699fead5fc4050eadc3f426752b4ca..16a6a0717e0bec432d5e6c67d6fdff917fbcde9f 100644 (file)
@@ -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
index 9e36adf3d35963effcf01bc83b041fe7b0411645..fbf7c4adf371a38e8e981d3e76022e8f4e344d24 100644 (file)
@@ -1755,7 +1755,7 @@ fn parse_qpath(&mut self, style: PathStyle) -> PResult<'a, (QSelf, ast::Path)> {
         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 @@ fn parse_qpath(&mut self, style: PathStyle) -> PResult<'a, (QSelf, ast::Path)> {
     /// `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 @@ pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, ast::Path>
         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 @@ pub fn parse_path_allowing_meta(&mut self, style: PathStyle) -> PResult<'a, ast:
         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 @@ fn parse_path_segments(&mut self, segments: &mut Vec<PathSegment>, style: PathSt
         }
     }
 
-    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,7 +1840,10 @@ fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, PathSegment> {
                                       && self.look_ahead(1, |t| is_args_start(t)) {
             // Generic arguments are found - `<`, `(`, `::<` or `::(`.
             let lo = self.span;
-            self.eat(&token::ModSep);
+            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() {
                 // `<'a, T, A = U>`
@@ -2371,7 +2379,7 @@ pub fn parse_dot_or_call_expr_with(&mut self,
 
     // 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()`
index 18a6e430b84ded2c8b237f352d72cb88c988c28b..3afbfa61984b566456317591534df18c0a5571ef 100644 (file)
 #![feature(rustc_attrs)]
 #![allow(unused)]
 
+macro_rules! m {
+    ($p: path) => {
+        let _ = $p(0);
+        let _: $p;
+    }
+}
+
 struct Foo<T> {
     _a: T,
 }
 
+struct S<T>(T);
+
 fn f() {
-    let f = Some(Foo { _a: 42 }).map(|a| a as Foo::<i32>);
-    let g: Foo::<i32> = Foo { _a: 42 };
+    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
+
+    m!(S::<u8>); // OK, no warning
 }
 
 #[rustc_error]