about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/ui/proc-macro/quote-debug.stdout49
-rw-r--r--tests/ui/proc-macro/quote/auxiliary/basic.rs361
-rw-r--r--tests/ui/proc-macro/quote/basic.rs8
-rw-r--r--tests/ui/proc-macro/quote/debug.rs (renamed from tests/ui/proc-macro/quote-debug.rs)1
-rw-r--r--tests/ui/proc-macro/quote/debug.stdout72
-rw-r--r--tests/ui/proc-macro/quote/does-not-have-iter-interpolated-dup.rs17
-rw-r--r--tests/ui/proc-macro/quote/does-not-have-iter-interpolated-dup.stderr10
-rw-r--r--tests/ui/proc-macro/quote/does-not-have-iter-interpolated.rs17
-rw-r--r--tests/ui/proc-macro/quote/does-not-have-iter-interpolated.stderr10
-rw-r--r--tests/ui/proc-macro/quote/does-not-have-iter-separated.rs13
-rw-r--r--tests/ui/proc-macro/quote/does-not-have-iter-separated.stderr10
-rw-r--r--tests/ui/proc-macro/quote/does-not-have-iter.rs13
-rw-r--r--tests/ui/proc-macro/quote/does-not-have-iter.stderr10
-rw-r--r--tests/ui/proc-macro/quote/not-quotable.rs12
-rw-r--r--tests/ui/proc-macro/quote/not-quotable.stderr24
-rw-r--r--tests/ui/proc-macro/quote/not-repeatable.rs16
-rw-r--r--tests/ui/proc-macro/quote/not-repeatable.stderr10
17 files changed, 604 insertions, 49 deletions
diff --git a/tests/ui/proc-macro/quote-debug.stdout b/tests/ui/proc-macro/quote-debug.stdout
deleted file mode 100644
index d84b4e051e8..00000000000
--- a/tests/ui/proc-macro/quote-debug.stdout
+++ /dev/null
@@ -1,49 +0,0 @@
-#![feature(prelude_import)]
-#![no_std]
-//@ check-pass
-//@ force-host
-//@ no-prefer-dynamic
-//@ compile-flags: -Z unpretty=expanded
-//@ needs-unwind compiling proc macros with panic=abort causes a warning
-//
-// This file is not actually used as a proc-macro - instead,
-// it's just used to show the output of the `quote!` macro
-
-#![feature(proc_macro_quote)]
-#![crate_type = "proc-macro"]
-#[prelude_import]
-use ::std::prelude::rust_2015::*;
-#[macro_use]
-extern crate std;
-
-extern crate proc_macro;
-
-fn main() {
-    [crate::TokenStream::from(crate::TokenTree::Ident(crate::Ident::new("let",
-                                    crate::Span::recover_proc_macro_span(0)))),
-                        crate::TokenStream::from(crate::TokenTree::Ident(crate::Ident::new("hello",
-                                    crate::Span::recover_proc_macro_span(1)))),
-                        crate::TokenStream::from(crate::TokenTree::Punct(crate::Punct::new('=',
-                                    crate::Spacing::Alone))),
-                        crate::TokenStream::from(crate::TokenTree::Literal({
-                                    let mut iter =
-                                        "\"world\"".parse::<crate::TokenStream>().unwrap().into_iter();
-                                    if let (Some(crate::TokenTree::Literal(mut lit)), None) =
-                                                (iter.next(), iter.next()) {
-                                            lit.set_span(crate::Span::recover_proc_macro_span(2));
-                                            lit
-                                        } else {
-                                           ::core::panicking::panic("internal error: entered unreachable code")
-                                       }
-                                })),
-                        crate::TokenStream::from(crate::TokenTree::Punct(crate::Punct::new(';',
-                                    crate::Spacing::Alone)))].iter().cloned().collect::<crate::TokenStream>()
-}
-const _: () =
-    {
-        extern crate proc_macro;
-        #[rustc_proc_macro_decls]
-        #[used]
-        #[allow(deprecated)]
-        static _DECLS: &[proc_macro::bridge::client::ProcMacro] = &[];
-    };
diff --git a/tests/ui/proc-macro/quote/auxiliary/basic.rs b/tests/ui/proc-macro/quote/auxiliary/basic.rs
new file mode 100644
index 00000000000..ef726bbfbe3
--- /dev/null
+++ b/tests/ui/proc-macro/quote/auxiliary/basic.rs
@@ -0,0 +1,361 @@
+#![feature(proc_macro_quote)]
+#![feature(proc_macro_totokens)]
+
+extern crate proc_macro;
+
+use std::borrow::Cow;
+use std::ffi::{CStr, CString};
+
+use proc_macro::*;
+
+#[proc_macro]
+pub fn run_tests(_: TokenStream) -> TokenStream {
+    test_quote_impl();
+    test_substitution();
+    test_advanced();
+    test_integer();
+    test_floating();
+    test_char();
+    test_str();
+    test_string();
+    test_c_str();
+    test_c_string();
+    test_interpolated_literal();
+    test_ident();
+    test_underscore();
+    test_duplicate();
+    test_empty_quote();
+    test_box_str();
+    test_cow();
+    test_append_tokens();
+    test_outer_line_comment();
+    test_inner_line_comment();
+    test_outer_block_comment();
+    test_inner_block_comment();
+    test_outer_attr();
+    test_inner_attr();
+    test_quote_raw_id();
+
+    TokenStream::new()
+}
+
+// Based on https://github.com/dtolnay/quote/blob/0245506323a3616daa2ee41c6ad0b871e4d78ae4/tests/test.rs
+//
+// FIXME(quote):
+// The following tests are removed because they are not supported yet in `proc_macro::quote!`
+//
+// - quote_spanned:
+//   - fn test_quote_spanned_impl
+//   - fn test_type_inference_for_span
+//   - wrong-type-span.rs
+// - format_ident:
+//   - fn test_format_ident
+//   - fn test_format_ident_strip_raw
+// - repetition:
+//   - fn test_iter
+//   - fn test_array
+//   - fn test_fancy_repetition
+//   - fn test_nested_fancy_repetition
+//   - fn test_duplicate_name_repetition
+//   - fn test_duplicate_name_repetition_no_copy
+//   - fn test_btreeset_repetition
+//   - fn test_variable_name_conflict
+//   - fn test_nonrep_in_repetition
+//   - fn test_closure
+//   - fn test_star_after_repetition
+
+struct X;
+
+impl ToTokens for X {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Ident::new("X", Span::call_site()).to_tokens(tokens)
+    }
+}
+
+fn test_quote_impl() {
+    let tokens = quote! {
+        impl<'a, T: ToTokens> ToTokens for &'a T {
+            fn to_tokens(&self, tokens: &mut TokenStream) {
+                (**self).to_tokens(tokens)
+            }
+        }
+    };
+
+    let expected = r#"impl < 'a, T : ToTokens > ToTokens for & 'a T
+{
+    fn to_tokens(& self, tokens : & mut TokenStream)
+    { (** self).to_tokens(tokens) }
+}"#;
+
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_substitution() {
+    let x = X;
+    let tokens = quote!($x <$x> ($x) [$x] {$x});
+
+    let expected = "X <X > (X) [X] { X }";
+
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_advanced() {
+    let generics = quote!( <'a, T> );
+
+    let where_clause = quote!( where T: Serialize );
+
+    let field_ty = quote!(String);
+
+    let item_ty = quote!(Cow<'a, str>);
+
+    let path = quote!(SomeTrait::serialize_with);
+
+    let value = quote!(self.x);
+
+    let tokens = quote! {
+        struct SerializeWith $generics $where_clause {
+            value: &'a $field_ty,
+            phantom: ::std::marker::PhantomData<$item_ty>,
+        }
+
+        impl $generics ::serde::Serialize for SerializeWith $generics $where_clause {
+            fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error>
+                where S: ::serde::Serializer
+            {
+                $path(self.value, s)
+            }
+        }
+
+        SerializeWith {
+            value: $value,
+            phantom: ::std::marker::PhantomData::<$item_ty>,
+        }
+    };
+
+    let expected = r#"struct SerializeWith < 'a, T > where T : Serialize
+{
+    value : & 'a String, phantom : :: std :: marker :: PhantomData <Cow < 'a,
+    str > >,
+} impl < 'a, T > :: serde :: Serialize for SerializeWith < 'a, T > where T :
+Serialize
+{
+    fn serialize < S > (& self, s : & mut S) -> Result < (), S :: Error >
+    where S : :: serde :: Serializer
+    { SomeTrait :: serialize_with(self.value, s) }
+} SerializeWith
+{
+    value : self.x, phantom : :: std :: marker :: PhantomData ::<Cow < 'a, str
+    > >,
+}"#;
+
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_integer() {
+    let ii8 = -1i8;
+    let ii16 = -1i16;
+    let ii32 = -1i32;
+    let ii64 = -1i64;
+    let ii128 = -1i128;
+    let iisize = -1isize;
+    let uu8 = 1u8;
+    let uu16 = 1u16;
+    let uu32 = 1u32;
+    let uu64 = 1u64;
+    let uu128 = 1u128;
+    let uusize = 1usize;
+
+    let tokens = quote! {
+        1 1i32 1u256
+        $ii8 $ii16 $ii32 $ii64 $ii128 $iisize
+        $uu8 $uu16 $uu32 $uu64 $uu128 $uusize
+    };
+    let expected = r#"1 1i32 1u256 -1i8 -1i16 -1i32 -1i64 -1i128 -1isize 1u8 1u16 1u32 1u64 1u128
+1usize"#;
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_floating() {
+    let e32 = 2.345f32;
+
+    let e64 = 2.345f64;
+
+    let tokens = quote! {
+        $e32
+        $e64
+    };
+    let expected = concat!("2.345f32 2.345f64");
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_char() {
+    let zero = '\u{1}';
+    let dollar = '$';
+    let pound = '#';
+    let quote = '"';
+    let apost = '\'';
+    let newline = '\n';
+    let heart = '\u{2764}';
+
+    let tokens = quote! {
+        $zero $dollar $pound $quote $apost $newline $heart
+    };
+    let expected = "'\\u{1}' '$' '#' '\"' '\\'' '\\n' '\u{2764}'";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_str() {
+    let s = "\u{1} a 'b \" c";
+    let tokens = quote!($s);
+    let expected = "\"\\u{1} a 'b \\\" c\"";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_string() {
+    let s = "\u{1} a 'b \" c".to_string();
+    let tokens = quote!($s);
+    let expected = "\"\\u{1} a 'b \\\" c\"";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_c_str() {
+    let s = CStr::from_bytes_with_nul(b"\x01 a 'b \" c\0").unwrap();
+    let tokens = quote!($s);
+    let expected = "c\"\\u{1} a 'b \\\" c\"";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_c_string() {
+    let s = CString::new(&b"\x01 a 'b \" c"[..]).unwrap();
+    let tokens = quote!($s);
+    let expected = "c\"\\u{1} a 'b \\\" c\"";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_interpolated_literal() {
+    macro_rules! m {
+        ($literal:literal) => {
+            quote!($literal)
+        };
+    }
+
+    let tokens = m!(1);
+    let expected = "1";
+    assert_eq!(expected, tokens.to_string());
+
+    let tokens = m!(-1);
+    let expected = "- 1";
+    assert_eq!(expected, tokens.to_string());
+
+    let tokens = m!(true);
+    let expected = "true";
+    assert_eq!(expected, tokens.to_string());
+
+    let tokens = m!(-true);
+    let expected = "- true";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_ident() {
+    let foo = Ident::new("Foo", Span::call_site());
+    let bar = Ident::new(&format!("Bar{}", 7), Span::call_site());
+    let tokens = quote!(struct $foo; enum $bar {});
+    let expected = "struct Foo; enum Bar7 {}";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_underscore() {
+    let tokens = quote!(let _;);
+    let expected = "let _;";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_duplicate() {
+    let ch = 'x';
+
+    let tokens = quote!($ch $ch);
+
+    let expected = "'x' 'x'";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_empty_quote() {
+    let tokens = quote!();
+    assert_eq!("", tokens.to_string());
+}
+
+fn test_box_str() {
+    let b = "str".to_owned().into_boxed_str();
+    let tokens = quote! { $b };
+    assert_eq!("\"str\"", tokens.to_string());
+}
+
+fn test_cow() {
+    let owned: Cow<Ident> = Cow::Owned(Ident::new("owned", Span::call_site()));
+
+    let ident = Ident::new("borrowed", Span::call_site());
+    let borrowed = Cow::Borrowed(&ident);
+
+    let tokens = quote! { $owned $borrowed };
+    assert_eq!("owned borrowed", tokens.to_string());
+}
+
+fn test_append_tokens() {
+    let mut a = quote!(a);
+    let b = quote!(b);
+    a.extend(b);
+    assert_eq!("a b", a.to_string());
+}
+
+fn test_outer_line_comment() {
+    let tokens = quote! {
+        /// doc
+    };
+    let expected = "#[doc = \" doc\"]";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_inner_line_comment() {
+    let tokens = quote! {
+        //! doc
+    };
+    let expected = "# ! [doc = \" doc\"]";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_outer_block_comment() {
+    let tokens = quote! {
+        /** doc */
+    };
+    let expected = "#[doc = \" doc \"]";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_inner_block_comment() {
+    let tokens = quote! {
+        /*! doc */
+    };
+    let expected = "# ! [doc = \" doc \"]";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_outer_attr() {
+    let tokens = quote! {
+        #[inline]
+    };
+    let expected = "#[inline]";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_inner_attr() {
+    let tokens = quote! {
+        #![no_std]
+    };
+    let expected = "#! [no_std]";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_quote_raw_id() {
+    let id = quote!(r#raw_id);
+    assert_eq!(id.to_string(), "r#raw_id");
+}
diff --git a/tests/ui/proc-macro/quote/basic.rs b/tests/ui/proc-macro/quote/basic.rs
new file mode 100644
index 00000000000..0336dbb7856
--- /dev/null
+++ b/tests/ui/proc-macro/quote/basic.rs
@@ -0,0 +1,8 @@
+//@ run-pass
+//@ proc-macro: basic.rs
+
+extern crate basic;
+
+fn main() {
+    basic::run_tests!();
+}
diff --git a/tests/ui/proc-macro/quote-debug.rs b/tests/ui/proc-macro/quote/debug.rs
index 11d144d609f..ce113079e56 100644
--- a/tests/ui/proc-macro/quote-debug.rs
+++ b/tests/ui/proc-macro/quote/debug.rs
@@ -15,5 +15,6 @@ extern crate proc_macro;
 fn main() {
     proc_macro::quote! {
         let hello = "world";
+        let r#raw_ident = r#"raw"literal"#;
     }
 }
diff --git a/tests/ui/proc-macro/quote/debug.stdout b/tests/ui/proc-macro/quote/debug.stdout
new file mode 100644
index 00000000000..3eaad9eb969
--- /dev/null
+++ b/tests/ui/proc-macro/quote/debug.stdout
@@ -0,0 +1,72 @@
+#![feature(prelude_import)]
+#![no_std]
+//@ check-pass
+//@ force-host
+//@ no-prefer-dynamic
+//@ compile-flags: -Z unpretty=expanded
+//@ needs-unwind compiling proc macros with panic=abort causes a warning
+//
+// This file is not actually used as a proc-macro - instead,
+// it's just used to show the output of the `quote!` macro
+
+#![feature(proc_macro_quote)]
+#![crate_type = "proc-macro"]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+
+extern crate proc_macro;
+
+fn main() {
+    {
+        let mut ts = crate::TokenStream::new();
+        crate::ToTokens::to_tokens(&crate::TokenTree::Ident(crate::Ident::new("let",
+                        crate::Span::recover_proc_macro_span(0))), &mut ts);
+        crate::ToTokens::to_tokens(&crate::TokenTree::Ident(crate::Ident::new("hello",
+                        crate::Span::recover_proc_macro_span(1))), &mut ts);
+        crate::ToTokens::to_tokens(&crate::TokenTree::Punct(crate::Punct::new('=',
+                        crate::Spacing::Alone)), &mut ts);
+        crate::ToTokens::to_tokens(&crate::TokenTree::Literal({
+                        let mut iter =
+                            "\"world\"".parse::<crate::TokenStream>().unwrap().into_iter();
+                        if let (Some(crate::TokenTree::Literal(mut lit)), None) =
+                                    (iter.next(), iter.next()) {
+                                lit.set_span(crate::Span::recover_proc_macro_span(2));
+                                lit
+                            } else {
+                               ::core::panicking::panic("internal error: entered unreachable code")
+                           }
+                    }), &mut ts);
+        crate::ToTokens::to_tokens(&crate::TokenTree::Punct(crate::Punct::new(';',
+                        crate::Spacing::Alone)), &mut ts);
+        crate::ToTokens::to_tokens(&crate::TokenTree::Ident(crate::Ident::new("let",
+                        crate::Span::recover_proc_macro_span(3))), &mut ts);
+        crate::ToTokens::to_tokens(&crate::TokenTree::Ident(crate::Ident::new_raw("raw_ident",
+                        crate::Span::recover_proc_macro_span(4))), &mut ts);
+        crate::ToTokens::to_tokens(&crate::TokenTree::Punct(crate::Punct::new('=',
+                        crate::Spacing::Alone)), &mut ts);
+        crate::ToTokens::to_tokens(&crate::TokenTree::Literal({
+                        let mut iter =
+                            "r#\"raw\"literal\"#".parse::<crate::TokenStream>().unwrap().into_iter();
+                        if let (Some(crate::TokenTree::Literal(mut lit)), None) =
+                                    (iter.next(), iter.next()) {
+                                lit.set_span(crate::Span::recover_proc_macro_span(5));
+                                lit
+                            } else {
+                               ::core::panicking::panic("internal error: entered unreachable code")
+                           }
+                    }), &mut ts);
+        crate::ToTokens::to_tokens(&crate::TokenTree::Punct(crate::Punct::new(';',
+                        crate::Spacing::Alone)), &mut ts);
+        ts
+    }
+}
+const _: () =
+    {
+        extern crate proc_macro;
+        #[rustc_proc_macro_decls]
+        #[used]
+        #[allow(deprecated)]
+        static _DECLS: &[proc_macro::bridge::client::ProcMacro] = &[];
+    };
diff --git a/tests/ui/proc-macro/quote/does-not-have-iter-interpolated-dup.rs b/tests/ui/proc-macro/quote/does-not-have-iter-interpolated-dup.rs
new file mode 100644
index 00000000000..2f67ae1bc6e
--- /dev/null
+++ b/tests/ui/proc-macro/quote/does-not-have-iter-interpolated-dup.rs
@@ -0,0 +1,17 @@
+// FIXME(quote): `proc_macro::quote!` doesn't support repetition at the moment, so the stderr is
+// expected to be incorrect.
+//@ known-bug: #54722
+
+#![feature(proc_macro_quote)]
+
+extern crate proc_macro;
+
+use proc_macro::quote;
+
+fn main() {
+    let nonrep = "";
+
+    // Without some protection against repetitions with no iterator somewhere
+    // inside, this would loop infinitely.
+    quote!($($nonrep $nonrep)*);
+}
diff --git a/tests/ui/proc-macro/quote/does-not-have-iter-interpolated-dup.stderr b/tests/ui/proc-macro/quote/does-not-have-iter-interpolated-dup.stderr
new file mode 100644
index 00000000000..5f28a46f318
--- /dev/null
+++ b/tests/ui/proc-macro/quote/does-not-have-iter-interpolated-dup.stderr
@@ -0,0 +1,10 @@
+error: proc macro panicked
+  --> $DIR/does-not-have-iter-interpolated-dup.rs:16:5
+   |
+LL |     quote!($($nonrep $nonrep)*);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: message: `$` must be followed by an ident or `$` in `quote!`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/proc-macro/quote/does-not-have-iter-interpolated.rs b/tests/ui/proc-macro/quote/does-not-have-iter-interpolated.rs
new file mode 100644
index 00000000000..1efb3eac642
--- /dev/null
+++ b/tests/ui/proc-macro/quote/does-not-have-iter-interpolated.rs
@@ -0,0 +1,17 @@
+// FIXME(quote): `proc_macro::quote!` doesn't support repetition at the moment, so the stderr is
+// expected to be incorrect.
+//@ known-bug: #54722
+
+#![feature(proc_macro_quote)]
+
+extern crate proc_macro;
+
+use proc_macro::quote;
+
+fn main() {
+    let nonrep = "";
+
+    // Without some protection against repetitions with no iterator somewhere
+    // inside, this would loop infinitely.
+    quote!($($nonrep)*);
+}
diff --git a/tests/ui/proc-macro/quote/does-not-have-iter-interpolated.stderr b/tests/ui/proc-macro/quote/does-not-have-iter-interpolated.stderr
new file mode 100644
index 00000000000..595aa858763
--- /dev/null
+++ b/tests/ui/proc-macro/quote/does-not-have-iter-interpolated.stderr
@@ -0,0 +1,10 @@
+error: proc macro panicked
+  --> $DIR/does-not-have-iter-interpolated.rs:16:5
+   |
+LL |     quote!($($nonrep)*);
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: message: `$` must be followed by an ident or `$` in `quote!`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/proc-macro/quote/does-not-have-iter-separated.rs b/tests/ui/proc-macro/quote/does-not-have-iter-separated.rs
new file mode 100644
index 00000000000..5f2ddabc390
--- /dev/null
+++ b/tests/ui/proc-macro/quote/does-not-have-iter-separated.rs
@@ -0,0 +1,13 @@
+// FIXME(quote): `proc_macro::quote!` doesn't support repetition at the moment, so the stderr is
+// expected to be incorrect.
+//@ known-bug: #54722
+
+#![feature(proc_macro_quote)]
+
+extern crate proc_macro;
+
+use proc_macro::quote;
+
+fn main() {
+    quote!($(a b),*);
+}
diff --git a/tests/ui/proc-macro/quote/does-not-have-iter-separated.stderr b/tests/ui/proc-macro/quote/does-not-have-iter-separated.stderr
new file mode 100644
index 00000000000..f6f5d7e007d
--- /dev/null
+++ b/tests/ui/proc-macro/quote/does-not-have-iter-separated.stderr
@@ -0,0 +1,10 @@
+error: proc macro panicked
+  --> $DIR/does-not-have-iter-separated.rs:12:5
+   |
+LL |     quote!($(a b),*);
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: message: `$` must be followed by an ident or `$` in `quote!`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/proc-macro/quote/does-not-have-iter.rs b/tests/ui/proc-macro/quote/does-not-have-iter.rs
new file mode 100644
index 00000000000..25ffd786cc6
--- /dev/null
+++ b/tests/ui/proc-macro/quote/does-not-have-iter.rs
@@ -0,0 +1,13 @@
+// FIXME(quote): `proc_macro::quote!` doesn't support repetition at the moment, so the stderr is
+// expected to be incorrect.
+//@ known-bug: #54722
+
+#![feature(proc_macro_quote)]
+
+extern crate proc_macro;
+
+use proc_macro::quote;
+
+fn main() {
+    quote!($(a b)*);
+}
diff --git a/tests/ui/proc-macro/quote/does-not-have-iter.stderr b/tests/ui/proc-macro/quote/does-not-have-iter.stderr
new file mode 100644
index 00000000000..0ed1daffc8c
--- /dev/null
+++ b/tests/ui/proc-macro/quote/does-not-have-iter.stderr
@@ -0,0 +1,10 @@
+error: proc macro panicked
+  --> $DIR/does-not-have-iter.rs:12:5
+   |
+LL |     quote!($(a b)*);
+   |     ^^^^^^^^^^^^^^^
+   |
+   = help: message: `$` must be followed by an ident or `$` in `quote!`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/proc-macro/quote/not-quotable.rs b/tests/ui/proc-macro/quote/not-quotable.rs
new file mode 100644
index 00000000000..7e38b441052
--- /dev/null
+++ b/tests/ui/proc-macro/quote/not-quotable.rs
@@ -0,0 +1,12 @@
+#![feature(proc_macro_quote)]
+
+extern crate proc_macro;
+
+use std::net::Ipv4Addr;
+
+use proc_macro::quote;
+
+fn main() {
+    let ip = Ipv4Addr::LOCALHOST;
+    let _ = quote! { $ip }; //~ ERROR the trait bound `Ipv4Addr: ToTokens` is not satisfied
+}
diff --git a/tests/ui/proc-macro/quote/not-quotable.stderr b/tests/ui/proc-macro/quote/not-quotable.stderr
new file mode 100644
index 00000000000..e349b2dce53
--- /dev/null
+++ b/tests/ui/proc-macro/quote/not-quotable.stderr
@@ -0,0 +1,24 @@
+error[E0277]: the trait bound `Ipv4Addr: ToTokens` is not satisfied
+  --> $DIR/not-quotable.rs:11:13
+   |
+LL |     let _ = quote! { $ip };
+   |             ^^^^^^^^^^^^^^
+   |             |
+   |             the trait `ToTokens` is not implemented for `Ipv4Addr`
+   |             required by a bound introduced by this call
+   |
+   = help: the following other types implement trait `ToTokens`:
+             &T
+             &mut T
+             Box<T>
+             CString
+             Cow<'_, T>
+             Option<T>
+             Rc<T>
+             bool
+           and 24 others
+   = note: this error originates in the macro `quote` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/proc-macro/quote/not-repeatable.rs b/tests/ui/proc-macro/quote/not-repeatable.rs
new file mode 100644
index 00000000000..d115da73181
--- /dev/null
+++ b/tests/ui/proc-macro/quote/not-repeatable.rs
@@ -0,0 +1,16 @@
+// FIXME(quote): `proc_macro::quote!` doesn't support repetition at the moment, so the stderr is
+// expected to be incorrect.
+//@ known-bug: #54722
+
+#![feature(proc_macro_quote)]
+
+extern crate proc_macro;
+
+use proc_macro::quote;
+
+struct Ipv4Addr;
+
+fn main() {
+    let ip = Ipv4Addr;
+    let _ = quote! { $($ip)* };
+}
diff --git a/tests/ui/proc-macro/quote/not-repeatable.stderr b/tests/ui/proc-macro/quote/not-repeatable.stderr
new file mode 100644
index 00000000000..18fbcd73798
--- /dev/null
+++ b/tests/ui/proc-macro/quote/not-repeatable.stderr
@@ -0,0 +1,10 @@
+error: proc macro panicked
+  --> $DIR/not-repeatable.rs:15:13
+   |
+LL |     let _ = quote! { $($ip)* };
+   |             ^^^^^^^^^^^^^^^^^^
+   |
+   = help: message: `$` must be followed by an ident or `$` in `quote!`
+
+error: aborting due to 1 previous error
+