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 { 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` 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>` wrapper is purely a size optimization; - /// `None` is used to represent both `Path` and `Path<>`. + /// two flavors: `Path` and `Path(A,B) -> C`. + /// `None` means that no parameter list is supplied (`Path`), + /// `Some` means that parameter list is supplied (`Path`) + /// but it can be empty (`Path<>`). + /// `P` is used as a size optimization for the common case with no parameters. pub parameters: Option>, } @@ -181,8 +180,7 @@ pub struct AngleBracketedParameterData { impl Into>> for AngleBracketedParameterData { fn into(self) -> Option> { - 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::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 } //~ERROR type or lifetime parameters in import path +fn f1() { + import! { a::b::c::S } //~ 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::!(); //~ 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::!(); + //~^ 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); -m!{ S } //~ ERROR type or lifetime parameters in visibility path +m!{ S } //~ ERROR generic arguments in visibility path //~^ ERROR expected module, found struct `S` +mod m { + m!{ m<> } //~ ERROR generic arguments in visibility path +} + fn main() {}