about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-03-21 17:46:48 +0100
committerGitHub <noreply@github.com>2024-03-21 17:46:48 +0100
commit2e41425de635480bac45c554d5fbdddc34a62bd1 (patch)
tree75a7320bf253e3af8ba8f702673f241dd5901897 /tests
parent2627e9f3012a97d3136b3e11bf6bd0853c38a534 (diff)
parent5568c569c03c8c22ce81185b9e49efcaa6866050 (diff)
downloadrust-2e41425de635480bac45c554d5fbdddc34a62bd1.tar.gz
rust-2e41425de635480bac45c554d5fbdddc34a62bd1.zip
Rollup merge of #122402 - weiznich:fix/122391, r=compiler-errors
Make `#[diagnostic::on_unimplemented]` format string parsing more robust

This commit fixes several issues with the format string parsing of the `#[diagnostic::on_unimplemented]` attribute that were pointed out by `@ehuss.`
In detail it fixes:

* Appearing format specifiers (display, etc). For these we generate a warning that the specifier is unsupported. Otherwise we ignore them
* Positional arguments. For these we generate a warning that positional arguments are unsupported in that location and replace them with the format string equivalent (so `{}` or `{n}` where n is the index of the positional argument)
* Broken format strings with enclosed }. For these we generate a warning about the broken format string and set the emitted message literally to the provided unformatted string
* Unknown format specifiers. For these we generate an additional warning about the unknown specifier. Otherwise we emit the literal string as message.

This essentially makes those strings behave like `format!` with the minor difference that we do not generate hard errors but only warnings. After that we continue trying to do something unsuprising (mostly either ignoring the broken parts or falling back to just giving back the literal string as provided).

Fix #122391

r? `@compiler-errors`
Diffstat (limited to 'tests')
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/broken_format.rs45
-rw-r--r--tests/ui/diagnostic_namespace/on_unimplemented/broken_format.stderr193
2 files changed, 238 insertions, 0 deletions
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.rs b/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.rs
new file mode 100644
index 00000000000..8d8917fd319
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.rs
@@ -0,0 +1,45 @@
+#[diagnostic::on_unimplemented(message = "{{Test } thing")]
+//~^WARN unmatched `}` found
+//~|WARN unmatched `}` found
+trait ImportantTrait1 {}
+
+#[diagnostic::on_unimplemented(message = "Test {}")]
+//~^WARN positional format arguments are not allowed here
+//~|WARN positional format arguments are not allowed here
+trait ImportantTrait2 {}
+
+#[diagnostic::on_unimplemented(message = "Test {1:}")]
+//~^WARN positional format arguments are not allowed here
+//~|WARN positional format arguments are not allowed here
+trait ImportantTrait3 {}
+
+#[diagnostic::on_unimplemented(message = "Test {Self:123}")]
+//~^WARN invalid format specifier
+//~|WARN invalid format specifier
+trait ImportantTrait4 {}
+
+#[diagnostic::on_unimplemented(message = "Test {Self:!}")]
+//~^WARN expected `'}'`, found `'!'`
+//~|WARN expected `'}'`, found `'!'`
+//~|WARN unmatched `}` found
+//~|WARN unmatched `}` found
+trait ImportantTrait5 {}
+
+fn check_1(_: impl ImportantTrait1) {}
+fn check_2(_: impl ImportantTrait2) {}
+fn check_3(_: impl ImportantTrait3) {}
+fn check_4(_: impl ImportantTrait4) {}
+fn check_5(_: impl ImportantTrait5) {}
+
+fn main() {
+    check_1(());
+    //~^ERROR {{Test } thing
+    check_2(());
+    //~^ERROR Test {}
+    check_3(());
+    //~^ERROR Test {1}
+    check_4(());
+    //~^ERROR Test ()
+    check_5(());
+    //~^ERROR Test {Self:!}
+}
diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.stderr
new file mode 100644
index 00000000000..932e81ca48e
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.stderr
@@ -0,0 +1,193 @@
+warning: unmatched `}` found
+  --> $DIR/broken_format.rs:1:32
+   |
+LL | #[diagnostic::on_unimplemented(message = "{{Test } thing")]
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
+
+warning: positional format arguments are not allowed here
+  --> $DIR/broken_format.rs:6:32
+   |
+LL | #[diagnostic::on_unimplemented(message = "Test {}")]
+   |                                ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: only named format arguments with the name of one of the generic types are allowed in this context
+
+warning: positional format arguments are not allowed here
+  --> $DIR/broken_format.rs:11:32
+   |
+LL | #[diagnostic::on_unimplemented(message = "Test {1:}")]
+   |                                ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: only named format arguments with the name of one of the generic types are allowed in this context
+
+warning: invalid format specifier
+  --> $DIR/broken_format.rs:16:32
+   |
+LL | #[diagnostic::on_unimplemented(message = "Test {Self:123}")]
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: no format specifier are supported in this position
+
+warning: expected `'}'`, found `'!'`
+  --> $DIR/broken_format.rs:21:32
+   |
+LL | #[diagnostic::on_unimplemented(message = "Test {Self:!}")]
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unmatched `}` found
+  --> $DIR/broken_format.rs:21:32
+   |
+LL | #[diagnostic::on_unimplemented(message = "Test {Self:!}")]
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unmatched `}` found
+  --> $DIR/broken_format.rs:1:32
+   |
+LL | #[diagnostic::on_unimplemented(message = "{{Test } thing")]
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0277]: {{Test } thing
+  --> $DIR/broken_format.rs:35:13
+   |
+LL |     check_1(());
+   |     ------- ^^ the trait `ImportantTrait1` is not implemented for `()`
+   |     |
+   |     required by a bound introduced by this call
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/broken_format.rs:4:1
+   |
+LL | trait ImportantTrait1 {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `check_1`
+  --> $DIR/broken_format.rs:28:20
+   |
+LL | fn check_1(_: impl ImportantTrait1) {}
+   |                    ^^^^^^^^^^^^^^^ required by this bound in `check_1`
+
+warning: positional format arguments are not allowed here
+  --> $DIR/broken_format.rs:6:32
+   |
+LL | #[diagnostic::on_unimplemented(message = "Test {}")]
+   |                                ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: only named format arguments with the name of one of the generic types are allowed in this context
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0277]: Test {}
+  --> $DIR/broken_format.rs:37:13
+   |
+LL |     check_2(());
+   |     ------- ^^ the trait `ImportantTrait2` is not implemented for `()`
+   |     |
+   |     required by a bound introduced by this call
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/broken_format.rs:9:1
+   |
+LL | trait ImportantTrait2 {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `check_2`
+  --> $DIR/broken_format.rs:29:20
+   |
+LL | fn check_2(_: impl ImportantTrait2) {}
+   |                    ^^^^^^^^^^^^^^^ required by this bound in `check_2`
+
+warning: positional format arguments are not allowed here
+  --> $DIR/broken_format.rs:11:32
+   |
+LL | #[diagnostic::on_unimplemented(message = "Test {1:}")]
+   |                                ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: only named format arguments with the name of one of the generic types are allowed in this context
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0277]: Test {1}
+  --> $DIR/broken_format.rs:39:13
+   |
+LL |     check_3(());
+   |     ------- ^^ the trait `ImportantTrait3` is not implemented for `()`
+   |     |
+   |     required by a bound introduced by this call
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/broken_format.rs:14:1
+   |
+LL | trait ImportantTrait3 {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `check_3`
+  --> $DIR/broken_format.rs:30:20
+   |
+LL | fn check_3(_: impl ImportantTrait3) {}
+   |                    ^^^^^^^^^^^^^^^ required by this bound in `check_3`
+
+warning: invalid format specifier
+  --> $DIR/broken_format.rs:16:32
+   |
+LL | #[diagnostic::on_unimplemented(message = "Test {Self:123}")]
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: no format specifier are supported in this position
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0277]: Test ()
+  --> $DIR/broken_format.rs:41:13
+   |
+LL |     check_4(());
+   |     ------- ^^ the trait `ImportantTrait4` is not implemented for `()`
+   |     |
+   |     required by a bound introduced by this call
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/broken_format.rs:19:1
+   |
+LL | trait ImportantTrait4 {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `check_4`
+  --> $DIR/broken_format.rs:31:20
+   |
+LL | fn check_4(_: impl ImportantTrait4) {}
+   |                    ^^^^^^^^^^^^^^^ required by this bound in `check_4`
+
+warning: expected `'}'`, found `'!'`
+  --> $DIR/broken_format.rs:21:32
+   |
+LL | #[diagnostic::on_unimplemented(message = "Test {Self:!}")]
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+warning: unmatched `}` found
+  --> $DIR/broken_format.rs:21:32
+   |
+LL | #[diagnostic::on_unimplemented(message = "Test {Self:!}")]
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0277]: Test {Self:!}
+  --> $DIR/broken_format.rs:43:13
+   |
+LL |     check_5(());
+   |     ------- ^^ the trait `ImportantTrait5` is not implemented for `()`
+   |     |
+   |     required by a bound introduced by this call
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/broken_format.rs:26:1
+   |
+LL | trait ImportantTrait5 {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `check_5`
+  --> $DIR/broken_format.rs:32:20
+   |
+LL | fn check_5(_: impl ImportantTrait5) {}
+   |                    ^^^^^^^^^^^^^^^ required by this bound in `check_5`
+
+error: aborting due to 5 previous errors; 12 warnings emitted
+
+For more information about this error, try `rustc --explain E0277`.