Discern between Path
and Path<>
in AST
This commit is contained in:
parent
da77a1a0ac
commit
ce3beb609f
7 changed files with 50 additions and 32 deletions
|
@ -197,7 +197,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
let path = view_path.node.path();
|
let path = view_path.node.path();
|
||||||
if path.segments.iter().any(|segment| segment.parameters.is_some()) {
|
if path.segments.iter().any(|segment| segment.parameters.is_some()) {
|
||||||
self.err_handler()
|
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) => {
|
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) {
|
fn visit_vis(&mut self, vis: &'a Visibility) {
|
||||||
match *vis {
|
match *vis {
|
||||||
Visibility::Restricted { ref path, .. } => {
|
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()
|
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> {
|
-> Result<Def, Determinacy> {
|
||||||
let ast::Path { ref segments, span } = *path;
|
let ast::Path { ref segments, span } = *path;
|
||||||
if segments.iter().any(|segment| segment.parameters.is_some()) {
|
if segments.iter().any(|segment| segment.parameters.is_some()) {
|
||||||
let kind =
|
self.session.span_err(span, "generic arguments in macro path");
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let path: Vec<_> = segments.iter().map(|seg| respan(seg.span, seg.identifier)).collect();
|
let path: Vec<_> = segments.iter().map(|seg| respan(seg.span, seg.identifier)).collect();
|
||||||
|
|
|
@ -120,12 +120,11 @@ pub struct PathSegment {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
|
||||||
/// Type/lifetime parameters attached to this path. They come in
|
/// Type/lifetime parameters attached to this path. They come in
|
||||||
/// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`. Note that
|
/// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`.
|
||||||
/// this is more than just simple syntactic sugar; the use of
|
/// `None` means that no parameter list is supplied (`Path`),
|
||||||
/// parens affects the region binding rules, so we preserve the
|
/// `Some` means that parameter list is supplied (`Path<X, Y>`)
|
||||||
/// distinction.
|
/// but it can be empty (`Path<>`).
|
||||||
/// The `Option<P<..>>` wrapper is purely a size optimization;
|
/// `P` is used as a size optimization for the common case with no parameters.
|
||||||
/// `None` is used to represent both `Path` and `Path<>`.
|
|
||||||
pub parameters: Option<P<PathParameters>>,
|
pub parameters: Option<P<PathParameters>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,8 +180,7 @@ pub struct AngleBracketedParameterData {
|
||||||
|
|
||||||
impl Into<Option<P<PathParameters>>> for AngleBracketedParameterData {
|
impl Into<Option<P<PathParameters>>> for AngleBracketedParameterData {
|
||||||
fn into(self) -> Option<P<PathParameters>> {
|
fn into(self) -> Option<P<PathParameters>> {
|
||||||
let empty = self.lifetimes.is_empty() && self.types.is_empty() && self.bindings.is_empty();
|
Some(P(PathParameters::AngleBracketed(self)))
|
||||||
if empty { None } else { 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)));
|
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() {
|
let parameters = if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() {
|
||||||
None
|
ast::AngleBracketedParameterData { lifetimes, types, bindings }.into()
|
||||||
} else {
|
} else {
|
||||||
Some(P(ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
|
None
|
||||||
lifetimes: lifetimes,
|
|
||||||
types: types,
|
|
||||||
bindings: bindings,
|
|
||||||
})))
|
|
||||||
};
|
};
|
||||||
segments.push(ast::PathSegment {
|
segments.push(ast::PathSegment {
|
||||||
identifier: last_identifier,
|
identifier: last_identifier,
|
||||||
|
@ -369,15 +365,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||||
bindings: Vec<ast::TypeBinding>)
|
bindings: Vec<ast::TypeBinding>)
|
||||||
-> (ast::QSelf, ast::Path) {
|
-> (ast::QSelf, ast::Path) {
|
||||||
let mut path = trait_path;
|
let mut path = trait_path;
|
||||||
let parameters = ast::AngleBracketedParameterData {
|
let parameters = if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() {
|
||||||
lifetimes: lifetimes,
|
ast::AngleBracketedParameterData { lifetimes, types, bindings }.into()
|
||||||
types: types,
|
} else {
|
||||||
bindings: bindings,
|
None
|
||||||
};
|
};
|
||||||
path.segments.push(ast::PathSegment {
|
path.segments.push(ast::PathSegment {
|
||||||
identifier: ident.node,
|
identifier: ident.node,
|
||||||
span: ident.span,
|
span: ident.span,
|
||||||
parameters: Some(P(ast::PathParameters::AngleBracketed(parameters))),
|
parameters: parameters,
|
||||||
});
|
});
|
||||||
|
|
||||||
(ast::QSelf {
|
(ast::QSelf {
|
||||||
|
|
|
@ -20,6 +20,11 @@ macro_rules! import {
|
||||||
($p: path) => (use $p;);
|
($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() {}
|
fn main() {}
|
||||||
|
|
|
@ -10,9 +10,28 @@
|
||||||
|
|
||||||
// gate-test-use_extern_macros
|
// gate-test-use_extern_macros
|
||||||
|
|
||||||
|
macro_rules! m {
|
||||||
|
($p1: path) => {
|
||||||
|
#[derive($p1)] struct U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
globnar::brotz!(); //~ ERROR non-ident macro paths are experimental
|
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
|
#[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);
|
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`
|
//~^ ERROR expected module, found struct `S`
|
||||||
|
|
||||||
|
mod m {
|
||||||
|
m!{ m<> } //~ ERROR generic arguments in visibility path
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue