Skip to content

Commit 29d6d79

Browse files
committed
Move do_not_recommend example to the intro
1 parent b300f00 commit 29d6d79

File tree

1 file changed

+97
-96
lines changed

1 file changed

+97
-96
lines changed

src/attributes/diagnostics.md

Lines changed: 97 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,103 @@ r[attributes.diagnostic.do_not_recommend]
555555
r[attributes.diagnostic.do_not_recommend.intro]
556556
The *`diagnostic::do_not_recommend` [attribute][attributes]* is a hint to the compiler to not show the annotated trait implementation as part of a diagnostic message.
557557

558+
> [!EXAMPLE]
559+
> In the following example, there is a trait called `AsExpression` which is used for casting arbitrary types to the `Expression` type used in an SQL library. There is a method called `check` which takes an `AsExpression`.
560+
>
561+
> ```rust,compile_fail,E0277
562+
> # pub trait Expression {
563+
> # type SqlType;
564+
> # }
565+
> #
566+
> # pub trait AsExpression<ST> {
567+
> # type Expression: Expression<SqlType = ST>;
568+
> # }
569+
> #
570+
> # pub struct Text;
571+
> # pub struct Integer;
572+
> #
573+
> # pub struct Bound<T>(T);
574+
> # pub struct SelectInt;
575+
> #
576+
> # impl Expression for SelectInt {
577+
> # type SqlType = Integer;
578+
> # }
579+
> #
580+
> # impl<T> Expression for Bound<T> {
581+
> # type SqlType = T;
582+
> # }
583+
> #
584+
> # impl AsExpression<Integer> for i32 {
585+
> # type Expression = Bound<Integer>;
586+
> # }
587+
> #
588+
> # impl AsExpression<Text> for &'_ str {
589+
> # type Expression = Bound<Text>;
590+
> # }
591+
> #
592+
> # impl<T> Foo for T where T: Expression {}
593+
>
594+
> // Uncomment this line to change the recommendation.
595+
> // #[diagnostic::do_not_recommend]
596+
> impl<T, ST> AsExpression<ST> for T
597+
> where
598+
> T: Expression<SqlType = ST>,
599+
> {
600+
> type Expression = T;
601+
> }
602+
>
603+
> trait Foo: Expression + Sized {
604+
> fn check<T>(&self, _: T) -> <T as AsExpression<<Self as Expression>::SqlType>>::Expression
605+
> where
606+
> T: AsExpression<Self::SqlType>,
607+
> {
608+
> todo!()
609+
> }
610+
> }
611+
>
612+
> fn main() {
613+
> SelectInt.check("bar");
614+
> }
615+
> ```
616+
>
617+
> The `SelectInt` type's `check` method is expecting an `Integer` type. Calling it with an i32 type works, as it gets converted to an `Integer` by the `AsExpression` trait. However, calling it with a string does not, and generates a an error that may look like this:
618+
>
619+
> ```text
620+
> error[E0277]: the trait bound `&str: Expression` is not satisfied
621+
> --> src/main.rs:53:15
622+
> |
623+
> 53 | SelectInt.check("bar");
624+
> | ^^^^^ the trait `Expression` is not implemented for `&str`
625+
> |
626+
> = help: the following other types implement trait `Expression`:
627+
> Bound<T>
628+
> SelectInt
629+
> note: required for `&str` to implement `AsExpression<Integer>`
630+
> --> src/main.rs:45:13
631+
> |
632+
> 45 | impl<T, ST> AsExpression<ST> for T
633+
> | ^^^^^^^^^^^^^^^^ ^
634+
> 46 | where
635+
> 47 | T: Expression<SqlType = ST>,
636+
> | ------------------------ unsatisfied trait bound introduced here
637+
> ```
638+
>
639+
> By adding the `#[diagnostic::do_not_recommend]` attribute to the blanket `impl` for `AsExpression`, the message changes to:
640+
>
641+
> ```text
642+
> error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied
643+
> --> src/main.rs:53:15
644+
> |
645+
> 53 | SelectInt.check("bar");
646+
> | ^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str`
647+
> |
648+
> = help: the trait `AsExpression<Integer>` is not implemented for `&str`
649+
> but trait `AsExpression<Text>` is implemented for it
650+
> = help: for that trait implementation, expected `Text`, found `Integer`
651+
> ```
652+
>
653+
> The first error message includes a somewhat confusing error message about the relationship of `&str` and `Expression`, as well as the unsatisfied trait bound in the blanket impl. After adding `#[diagnostic::do_not_recommend]`, it no longer considers the blanket impl for the recommendation. The message should be a little clearer, with an indication that a string cannot be converted to an `Integer`.
654+
558655
> [!NOTE]
559656
> Suppressing the recommendation can be useful if you know that the recommendation would normally not be useful to the programmer. This often occurs with broad, blanket impls. The recommendation may send the programmer down the wrong path, or the trait implementation may be an internal detail that you don't want to expose, or the bounds may not be able to be satisfied by the programmer.
560657
>
@@ -566,102 +663,6 @@ The attribute should be placed on a [trait implementation item][trait-impl], tho
566663
r[attributes.diagnostic.do_not_recommend.syntax]
567664
The attribute does not accept any arguments, though unexpected arguments are not considered as an error.
568665
569-
In the following example, there is a trait called `AsExpression` which is used for casting arbitrary types to the `Expression` type used in an SQL library. There is a method called `check` which takes an `AsExpression`.
570-
571-
```rust,compile_fail,E0277
572-
# pub trait Expression {
573-
# type SqlType;
574-
# }
575-
#
576-
# pub trait AsExpression<ST> {
577-
# type Expression: Expression<SqlType = ST>;
578-
# }
579-
#
580-
# pub struct Text;
581-
# pub struct Integer;
582-
#
583-
# pub struct Bound<T>(T);
584-
# pub struct SelectInt;
585-
#
586-
# impl Expression for SelectInt {
587-
# type SqlType = Integer;
588-
# }
589-
#
590-
# impl<T> Expression for Bound<T> {
591-
# type SqlType = T;
592-
# }
593-
#
594-
# impl AsExpression<Integer> for i32 {
595-
# type Expression = Bound<Integer>;
596-
# }
597-
#
598-
# impl AsExpression<Text> for &'_ str {
599-
# type Expression = Bound<Text>;
600-
# }
601-
#
602-
# impl<T> Foo for T where T: Expression {}
603-
604-
// Uncomment this line to change the recommendation.
605-
// #[diagnostic::do_not_recommend]
606-
impl<T, ST> AsExpression<ST> for T
607-
where
608-
T: Expression<SqlType = ST>,
609-
{
610-
type Expression = T;
611-
}
612-
613-
trait Foo: Expression + Sized {
614-
fn check<T>(&self, _: T) -> <T as AsExpression<<Self as Expression>::SqlType>>::Expression
615-
where
616-
T: AsExpression<Self::SqlType>,
617-
{
618-
todo!()
619-
}
620-
}
621-
622-
fn main() {
623-
SelectInt.check("bar");
624-
}
625-
```
626-
627-
The `SelectInt` type's `check` method is expecting an `Integer` type. Calling it with an i32 type works, as it gets converted to an `Integer` by the `AsExpression` trait. However, calling it with a string does not, and generates a an error that may look like this:
628-
629-
```text
630-
error[E0277]: the trait bound `&str: Expression` is not satisfied
631-
--> src/main.rs:53:15
632-
|
633-
53 | SelectInt.check("bar");
634-
| ^^^^^ the trait `Expression` is not implemented for `&str`
635-
|
636-
= help: the following other types implement trait `Expression`:
637-
Bound<T>
638-
SelectInt
639-
note: required for `&str` to implement `AsExpression<Integer>`
640-
--> src/main.rs:45:13
641-
|
642-
45 | impl<T, ST> AsExpression<ST> for T
643-
| ^^^^^^^^^^^^^^^^ ^
644-
46 | where
645-
47 | T: Expression<SqlType = ST>,
646-
| ------------------------ unsatisfied trait bound introduced here
647-
```
648-
649-
By adding the `#[diagnostic::do_not_recommend]` attribute to the blanket `impl` for `AsExpression`, the message changes to:
650-
651-
```text
652-
error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied
653-
--> src/main.rs:53:15
654-
|
655-
53 | SelectInt.check("bar");
656-
| ^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str`
657-
|
658-
= help: the trait `AsExpression<Integer>` is not implemented for `&str`
659-
but trait `AsExpression<Text>` is implemented for it
660-
= help: for that trait implementation, expected `Text`, found `Integer`
661-
```
662-
663-
The first error message includes a somewhat confusing error message about the relationship of `&str` and `Expression`, as well as the unsatisfied trait bound in the blanket impl. After adding `#[diagnostic::do_not_recommend]`, it no longer considers the blanket impl for the recommendation. The message should be a little clearer, with an indication that a string cannot be converted to an `Integer`.
664-
665666
[Clippy]: https://github.com/rust-lang/rust-clippy
666667
[`Drop`]: ../special-types-and-traits.md#drop
667668
[attributes]: ../attributes.md

0 commit comments

Comments
 (0)