diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index da2a22df997d1..0ea2cab75d619 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5518,6 +5518,7 @@ impl<'a> Parser<'a> { }; // Parse both types and traits as a type, then reinterpret if necessary. + let ty_first_interpolated = if self.token.is_ty() { Some(self.span) } else { None }; let ty_first = self.parse_ty()?; // If `for` is missing we try to recover. @@ -5547,8 +5548,16 @@ impl<'a> Parser<'a> { let ty_first = ty_first.into_inner(); let path = match ty_first.node { - // This notably includes paths passed through `ty` macro fragments (#46438). - TyKind::Path(None, path) => path, + TyKind::Path(None, path) => { + if let Some(span) = ty_first_interpolated { + self.diagnostic() + .struct_span_warn(span, "expected a trait, found type") + .note("this warning will become a hard error in a future release") + .span_label(span, "try using `path` instead of `ty` \ + for this macro fragment").emit(); + } + path + } _ => { self.span_err(ty_first.span, "expected a trait, found type"); ast::Path::from_ident(ty_first.span, keywords::Invalid.ident()) diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 097a2eb89fdf4..be15168d6d402 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -315,6 +315,16 @@ impl Token { false } + /// Returns `true` if the token is an interpolated type. + pub fn is_ty(&self) -> bool { + if let Interpolated(ref nt) = *self { + if let NtTy(..) = nt.0 { + return true; + } + } + false + } + /// Returns a lifetime with the span and a dummy id if it is a lifetime, /// or the original lifetime if it is an interpolated lifetime, ignoring /// the span. diff --git a/src/test/compile-fail/issue-46438.rs b/src/test/ui/issue-46438.rs similarity index 89% rename from src/test/compile-fail/issue-46438.rs rename to src/test/ui/issue-46438.rs index d84b58133853f..c9b24daf72e55 100644 --- a/src/test/compile-fail/issue-46438.rs +++ b/src/test/ui/issue-46438.rs @@ -10,7 +10,7 @@ macro_rules! m { ($my_type: ty) => { - impl $my_type for u8 {} + impl $my_type for u8 {} //~ WARN expected a trait, found type } } diff --git a/src/test/ui/issue-46438.stderr b/src/test/ui/issue-46438.stderr new file mode 100644 index 0000000000000..7396677ebf771 --- /dev/null +++ b/src/test/ui/issue-46438.stderr @@ -0,0 +1,19 @@ +warning: expected a trait, found type + --> $DIR/issue-46438.rs:13:14 + | +LL | impl $my_type for u8 {} //~ WARN expected a trait, found type + | ^^^^^^^^ try using `path` instead of `ty` for this macro fragment +... +LL | m!(Tr); + | ------- in this macro invocation + | + = note: this warning will become a hard error in a future release + +error: expected a trait, found type + --> $DIR/issue-46438.rs:21:4 + | +LL | m!(&'static u8); //~ ERROR expected a trait, found type + | ^^^^^^^^^^^ + +error: aborting due to previous error +