Rollup merge of #91150 - dtolnay:qpath, r=davidtwco
Let qpath contain NtTy: `<$:ty as $:ty>::…` Example: ```rust macro_rules! m { (<$type:ty as $trait:ty>::$name:ident) => { <$type as $trait>::$name }; } fn main() { let _: m!(<str as ToOwned>::Owned); } ``` Previous behavior: ```console error: expected identifier, found `ToOwned` --> src/main.rs:3:19 | 3 | <$type as $trait>::$name | ^^^^^^ expected identifier ... 8 | let _: m!(<str as ToOwned>::Owned); | --------------------------- | | | this macro call doesn't expand to a type | in this macro invocation ``` The <code>expected identifier, found \`ToOwned\`</code> error is particularly silly. I think it should be fine to accept this code as long as $trait is of the form `TyKind::Path(None, path)`; if it is any other kind of `NtTy`, we'll keep the same behavior as before.
This commit is contained in:
commit
f372476d2c
@ -139,10 +139,19 @@ impl<'a> Parser<'a> {
|
|||||||
style: PathStyle,
|
style: PathStyle,
|
||||||
ty_generics: Option<&Generics>,
|
ty_generics: Option<&Generics>,
|
||||||
) -> PResult<'a, Path> {
|
) -> PResult<'a, Path> {
|
||||||
maybe_whole!(self, NtPath, |path| {
|
let reject_generics_if_mod_style = |parser: &Parser<'_>, path: &Path| {
|
||||||
|
// Ensure generic arguments don't end up in attribute paths, such as:
|
||||||
|
//
|
||||||
|
// macro_rules! m {
|
||||||
|
// ($p:path) => { #[$p] struct S; }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// m!(inline<u8>); //~ ERROR: unexpected generic arguments in path
|
||||||
|
//
|
||||||
if style == PathStyle::Mod && path.segments.iter().any(|segment| segment.args.is_some())
|
if style == PathStyle::Mod && path.segments.iter().any(|segment| segment.args.is_some())
|
||||||
{
|
{
|
||||||
self.struct_span_err(
|
parser
|
||||||
|
.struct_span_err(
|
||||||
path.segments
|
path.segments
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|segment| segment.args.as_ref())
|
.filter_map(|segment| segment.args.as_ref())
|
||||||
@ -152,9 +161,24 @@ impl<'a> Parser<'a> {
|
|||||||
)
|
)
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
maybe_whole!(self, NtPath, |path| {
|
||||||
|
reject_generics_if_mod_style(self, &path);
|
||||||
path
|
path
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if let token::Interpolated(nt) = &self.token.kind {
|
||||||
|
if let token::NtTy(ty) = &**nt {
|
||||||
|
if let ast::TyKind::Path(None, path) = &ty.kind {
|
||||||
|
let path = path.clone();
|
||||||
|
self.bump();
|
||||||
|
reject_generics_if_mod_style(self, &path);
|
||||||
|
return Ok(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let lo = self.token.span;
|
let lo = self.token.span;
|
||||||
let mut segments = Vec::new();
|
let mut segments = Vec::new();
|
||||||
let mod_sep_ctxt = self.token.span.ctxt();
|
let mod_sep_ctxt = self.token.span.ctxt();
|
||||||
|
@ -14,8 +14,20 @@ macro_rules! overly_complicated {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! qpath {
|
||||||
|
(path, <$type:ty as $trait:path>::$name:ident) => {
|
||||||
|
<$type as $trait>::$name
|
||||||
|
};
|
||||||
|
|
||||||
|
(ty, <$type:ty as $trait:ty>::$name:ident) => {
|
||||||
|
<$type as $trait>::$name
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
|
let _: qpath!(path, <str as ToOwned>::Owned);
|
||||||
|
let _: qpath!(ty, <str as ToOwned>::Owned);
|
||||||
|
|
||||||
assert!(overly_complicated!(f, x, Option<usize>, { return Some(x); },
|
assert!(overly_complicated!(f, x, Option<usize>, { return Some(x); },
|
||||||
Some(8), Some(y), y) == 8)
|
Some(8), Some(y), y) == 8)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user