Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Discern between Path and Path<> in AST
  • Loading branch information
petrochenkov committed Jul 27, 2017
1 parent da77a1a commit ce3beb6
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 32 deletions.
6 changes: 3 additions & 3 deletions src/librustc_passes/ast_validation.rs
Expand Up @@ -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) => {
Expand Down Expand Up @@ -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");
}
}
_ => {}
Expand Down
6 changes: 1 addition & 5 deletions src/librustc_resolve/macros.rs
Expand Up @@ -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();
Expand Down
14 changes: 6 additions & 8 deletions src/libsyntax/ast.rs
Expand Up @@ -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>>,
}

Expand Down Expand Up @@ -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)))
}
}

Expand Down
20 changes: 8 additions & 12 deletions src/libsyntax/ext/build.rs
Expand Up @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down
7 changes: 6 additions & 1 deletion src/test/compile-fail/import-ty-params.rs
Expand Up @@ -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() {}
23 changes: 21 additions & 2 deletions src/test/compile-fail/macro-with-seps-err-msg.rs
Expand Up @@ -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
}
6 changes: 5 additions & 1 deletion src/test/compile-fail/privacy/restricted/ty-params.rs
Expand Up @@ -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() {}

0 comments on commit ce3beb6

Please sign in to comment.