From 01800caddf74375e17bbdedb9606139704fc3aed Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 22 Nov 2021 19:57:08 -0800 Subject: [PATCH 1/4] Add test of qpath interpolations --- src/test/ui/macros/macro-interpolation.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/test/ui/macros/macro-interpolation.rs b/src/test/ui/macros/macro-interpolation.rs index abe1f2aaf153b..2dee804fb31e8 100644 --- a/src/test/ui/macros/macro-interpolation.rs +++ b/src/test/ui/macros/macro-interpolation.rs @@ -14,8 +14,15 @@ macro_rules! overly_complicated { } +macro_rules! qpath { + (<$type:ty as $trait:path>::$name:ident) => { + <$type as $trait>::$name + }; +} + pub fn main() { + let _: qpath!(::Owned); + assert!(overly_complicated!(f, x, Option, { return Some(x); }, Some(8), Some(y), y) == 8) - } From 558ddee2cea3063a487393ea292126259702fe97 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 22 Nov 2021 19:58:18 -0800 Subject: [PATCH 2/4] Add test of NtTy in a qpath Currently fails: error: expected identifier, found `ToOwned` --> src/test/ui/macros/macro-interpolation.rs:23:19 | LL | <$type as $trait>::$name | ^^^^^^ expected identifier ... LL | let _: qpath!(ty, ::Owned); | ----------------------------------- | | | this macro call doesn't expand to a type | in this macro invocation --- src/test/ui/macros/macro-interpolation.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/test/ui/macros/macro-interpolation.rs b/src/test/ui/macros/macro-interpolation.rs index 2dee804fb31e8..35003a79ad703 100644 --- a/src/test/ui/macros/macro-interpolation.rs +++ b/src/test/ui/macros/macro-interpolation.rs @@ -15,13 +15,18 @@ macro_rules! overly_complicated { } macro_rules! qpath { - (<$type:ty as $trait:path>::$name:ident) => { + (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!(::Owned); + let _: qpath!(path, ::Owned); + let _: qpath!(ty, ::Owned); assert!(overly_complicated!(f, x, Option, { return Some(x); }, Some(8), Some(y), y) == 8) From 0cbb00f89875c085181f1d55bbe46d39ec36be3f Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 22 Nov 2021 19:43:51 -0800 Subject: [PATCH 3/4] Let qpath contain NtTy: <$:ty as $:ty>::rest --- compiler/rustc_parse/src/parser/path.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 7f8fadb33bd8a..04ede1f7e3ba1 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -155,6 +155,16 @@ impl<'a> Parser<'a> { 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(); + return Ok(path); + } + } + } + let lo = self.token.span; let mut segments = Vec::new(); let mod_sep_ctxt = self.token.span.ctxt(); From 87a7defa8e08c971a30b152509c6c1ab9f718092 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 22 Nov 2021 20:16:28 -0800 Subject: [PATCH 4/4] Reject generic arguments on mod style interpolated path --- compiler/rustc_parse/src/parser/path.rs | 34 +++++++++++++++++-------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 04ede1f7e3ba1..e140b23f5d66f 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -139,19 +139,32 @@ 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); //~ 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::>(), - "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::>(), + "unexpected generic arguments in path", + ) + .emit(); } + }; + + maybe_whole!(self, NtPath, |path| { + reject_generics_if_mod_style(self, &path); path }); @@ -160,6 +173,7 @@ impl<'a> Parser<'a> { 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); } }