about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2017-07-23 19:32:36 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2017-07-27 22:59:35 +0300
commitce3beb609f75fb690d6980c9e6a62c6efa6f3d97 (patch)
tree393b1ae3dd4e554835638bb3cc5c451caa2aad24 /src
parentda77a1a0acf54fddba97052d55187a441224d022 (diff)
downloadrust-ce3beb609f75fb690d6980c9e6a62c6efa6f3d97.tar.gz
rust-ce3beb609f75fb690d6980c9e6a62c6efa6f3d97.zip
Discern between `Path` and `Path<>` in AST
Diffstat (limited to 'src')
-rw-r--r--src/librustc_passes/ast_validation.rs6
-rw-r--r--src/librustc_resolve/macros.rs6
-rw-r--r--src/libsyntax/ast.rs14
-rw-r--r--src/libsyntax/ext/build.rs20
-rw-r--r--src/test/compile-fail/import-ty-params.rs7
-rw-r--r--src/test/compile-fail/macro-with-seps-err-msg.rs23
-rw-r--r--src/test/compile-fail/privacy/restricted/ty-params.rs6
7 files changed, 50 insertions, 32 deletions
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 99a49dbd7d7..e8331cc5397 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -197,7 +197,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 let path = view_path.node.path();
                 if path.segments.iter().any(|segment| segment.parameters.is_some()) {
                     self.err_handler()
-                        .span_err(path.span, "type or lifetime parameters in import path");
+                        .span_err(path.span, "generic arguments in import path");
                 }
             }
             ItemKind::Impl(.., Some(..), _, ref impl_items) => {
@@ -297,9 +297,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
     fn visit_vis(&mut self, vis: &'a Visibility) {
         match *vis {
             Visibility::Restricted { ref path, .. } => {
-                if !path.segments.iter().all(|segment| segment.parameters.is_none()) {
+                if path.segments.iter().any(|segment| segment.parameters.is_some()) {
                     self.err_handler()
-                        .span_err(path.span, "type or lifetime parameters in visibility path");
+                        .span_err(path.span, "generic arguments in visibility path");
                 }
             }
             _ => {}
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 18ec2b3cc1b..c256b42f1bd 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -387,11 +387,7 @@ impl<'a> Resolver<'a> {
                             -> Result<Def, Determinacy> {
         let ast::Path { ref segments, span } = *path;
         if segments.iter().any(|segment| segment.parameters.is_some()) {
-            let kind =
-                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);
+            self.session.span_err(span, "generic arguments in macro path");
         }
 
         let path: Vec<_> = segments.iter().map(|seg| respan(seg.span, seg.identifier)).collect();
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index b8e371a4e76..544afc5d6f6 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -120,12 +120,11 @@ pub struct PathSegment {
     pub span: Span,
 
     /// Type/lifetime parameters attached to this path. They come in
-    /// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`. Note that
-    /// this is more than just simple syntactic sugar; the use of
-    /// parens affects the region binding rules, so we preserve the
-    /// distinction.
-    /// The `Option<P<..>>` wrapper is purely a size optimization;
-    /// `None` is used to represent both `Path` and `Path<>`.
+    /// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`.
+    /// `None` means that no parameter list is supplied (`Path`),
+    /// `Some` means that parameter list is supplied (`Path<X, Y>`)
+    /// but it can be empty (`Path<>`).
+    /// `P` is used as a size optimization for the common case with no parameters.
     pub parameters: Option<P<PathParameters>>,
 }
 
@@ -181,8 +180,7 @@ pub struct AngleBracketedParameterData {
 
 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))) }
+        Some(P(PathParameters::AngleBracketed(self)))
     }
 }
 
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index d8140417214..af9143eadbc 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -326,14 +326,10 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         }
 
         segments.extend(idents.into_iter().map(|i| ast::PathSegment::from_ident(i, sp)));
-        let parameters = if lifetimes.is_empty() && types.is_empty() && bindings.is_empty() {
-            None
+        let parameters = if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() {
+            ast::AngleBracketedParameterData { lifetimes, types, bindings }.into()
         } else {
-            Some(P(ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
-                lifetimes: lifetimes,
-                types: types,
-                bindings: bindings,
-            })))
+            None
         };
         segments.push(ast::PathSegment {
             identifier: last_identifier,
@@ -369,15 +365,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
                  bindings: Vec<ast::TypeBinding>)
                  -> (ast::QSelf, ast::Path) {
         let mut path = trait_path;
-        let parameters = ast::AngleBracketedParameterData {
-            lifetimes: lifetimes,
-            types: types,
-            bindings: bindings,
+        let parameters = if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() {
+            ast::AngleBracketedParameterData { lifetimes, types, bindings }.into()
+        } else {
+            None
         };
         path.segments.push(ast::PathSegment {
             identifier: ident.node,
             span: ident.span,
-            parameters: Some(P(ast::PathParameters::AngleBracketed(parameters))),
+            parameters: parameters,
         });
 
         (ast::QSelf {
diff --git a/src/test/compile-fail/import-ty-params.rs b/src/test/compile-fail/import-ty-params.rs
index 7344f31535f..d1e3d20f4ba 100644
--- a/src/test/compile-fail/import-ty-params.rs
+++ b/src/test/compile-fail/import-ty-params.rs
@@ -20,6 +20,11 @@ macro_rules! import {
     ($p: path) => (use $p;);
 }
 
-import! { a::b::c::S<u8> } //~ERROR type or lifetime parameters in import path
+fn f1() {
+    import! { a::b::c::S<u8> } //~ ERROR generic arguments in import path
+}
+fn f2() {
+    import! { a::b::c::S<> } //~ ERROR generic arguments in import path
+}
 
 fn main() {}
diff --git a/src/test/compile-fail/macro-with-seps-err-msg.rs b/src/test/compile-fail/macro-with-seps-err-msg.rs
index c28e22d58f9..8e0c451959d 100644
--- a/src/test/compile-fail/macro-with-seps-err-msg.rs
+++ b/src/test/compile-fail/macro-with-seps-err-msg.rs
@@ -10,9 +10,28 @@
 
 // gate-test-use_extern_macros
 
+macro_rules! m {
+    ($p1: path) => {
+        #[derive($p1)] struct U;
+    }
+}
+
 fn main() {
     globnar::brotz!(); //~ ERROR non-ident macro paths are experimental
-    ::foo!(); //~ ERROR non-ident macro paths are experimental
-    foo::<T>!(); //~ ERROR type parameters are not allowed on macros
     #[derive(foo::Bar)] struct T; //~ ERROR non-ident macro paths are experimental
+    ::foo!(); //~ ERROR non-ident macro paths are experimental
+
+    foo::<T>!();
+    //~^ ERROR generic arguments in macro path
+    //~| ERROR generic arguments in macro path
+    //~| ERROR generic arguments in macro path
+    foo::<>!();
+    //~^ ERROR generic arguments in macro path
+    //~| ERROR generic arguments in macro path
+    //~| ERROR generic arguments in macro path
+    m!(MyTrait<>);
+    //~^ ERROR generic arguments in macro path
+    //~| ERROR generic arguments in macro path
+    //~| ERROR generic arguments in macro path
+    //~| ERROR generic arguments in macro path
 }
diff --git a/src/test/compile-fail/privacy/restricted/ty-params.rs b/src/test/compile-fail/privacy/restricted/ty-params.rs
index c83a4e56852..8d4817e80b9 100644
--- a/src/test/compile-fail/privacy/restricted/ty-params.rs
+++ b/src/test/compile-fail/privacy/restricted/ty-params.rs
@@ -13,7 +13,11 @@ macro_rules! m {
 }
 
 struct S<T>(T);
-m!{ S<u8> } //~ ERROR type or lifetime parameters in visibility path
+m!{ S<u8> } //~ ERROR generic arguments in visibility path
 //~^ ERROR expected module, found struct `S`
 
+mod m {
+    m!{ m<> } //~ ERROR generic arguments in visibility path
+}
+
 fn main() {}