Discern between Path
and Path<>
in AST
This commit is contained in:
parent
da77a1a0ac
commit
ce3beb609f
@ -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");
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
@ -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();
|
||||
|
@ -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)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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() {}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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() {}
|
||||
|
Loading…
Reference in New Issue
Block a user