about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_parse/src/parser/path.rs44
-rw-r--r--src/test/ui/macros/macro-interpolation.rs14
2 files changed, 47 insertions, 11 deletions
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 4e60b7593c6..48502112e3a 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -139,22 +139,46 @@ impl<'a> Parser<'a> {
         style: PathStyle,
         ty_generics: Option<&Generics>,
     ) -> 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())
             {
-                self.struct_span_err(
-                    path.segments
-                        .iter()
-                        .filter_map(|segment| segment.args.as_ref())
-                        .map(|arg| arg.span())
-                        .collect::<Vec<_>>(),
-                    "unexpected generic arguments in path",
-                )
-                .emit();
+                parser
+                    .struct_span_err(
+                        path.segments
+                            .iter()
+                            .filter_map(|segment| segment.args.as_ref())
+                            .map(|arg| arg.span())
+                            .collect::<Vec<_>>(),
+                        "unexpected generic arguments in path",
+                    )
+                    .emit();
             }
+        };
+
+        maybe_whole!(self, NtPath, |path| {
+            reject_generics_if_mod_style(self, &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 mut segments = Vec::new();
         let mod_sep_ctxt = self.token.span.ctxt();
diff --git a/src/test/ui/macros/macro-interpolation.rs b/src/test/ui/macros/macro-interpolation.rs
index abe1f2aaf15..35003a79ad7 100644
--- a/src/test/ui/macros/macro-interpolation.rs
+++ b/src/test/ui/macros/macro-interpolation.rs
@@ -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() {
+    let _: qpath!(path, <str as ToOwned>::Owned);
+    let _: qpath!(ty, <str as ToOwned>::Owned);
+
     assert!(overly_complicated!(f, x, Option<usize>, { return Some(x); },
                                Some(8), Some(y), y) == 8)
-
 }