You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/attributes/diagnostics.md
+78-34
Original file line number
Diff line number
Diff line change
@@ -576,58 +576,102 @@ The attribute should be placed on a [trait implementation item][trait-impl], tho
576
576
r[attributes.diagnostic.do_not_recommend.syntax]
577
577
The attribute does not accept any arguments, though unexpected arguments are not considered as an error.
578
578
579
-
In this example,
579
+
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`.
580
580
581
581
```rust,compile_fail,E0277
582
-
trait Foo {}
583
-
584
-
impl<T> Foo for T where T: Send {}
582
+
# pub trait Expression {
583
+
# type SqlType;
584
+
# }
585
+
#
586
+
# pub trait AsExpression<ST> {
587
+
# type Expression: Expression<SqlType = ST>;
588
+
# }
589
+
#
590
+
# pub struct Text;
591
+
# pub struct Integer;
592
+
#
593
+
# pub struct Bound<T>(T);
594
+
# pub struct SelectInt;
595
+
#
596
+
# impl Expression for SelectInt {
597
+
# type SqlType = Integer;
598
+
# }
599
+
#
600
+
# impl<T> Expression for Bound<T> {
601
+
# type SqlType = T;
602
+
# }
603
+
#
604
+
# impl AsExpression<Integer> for i32 {
605
+
# type Expression = Bound<Integer>;
606
+
# }
607
+
#
608
+
# impl AsExpression<Text> for &'_ str {
609
+
# type Expression = Bound<Text>;
610
+
# }
611
+
#
612
+
# impl<T> Foo for T where T: Expression {}
613
+
614
+
// Uncomment this line to change the recommendation.
615
+
// #[diagnostic::do_not_recommend]
616
+
impl<T, ST> AsExpression<ST> for T
617
+
where
618
+
T: Expression<SqlType = ST>,
619
+
{
620
+
type Expression = T;
621
+
}
585
622
586
-
fn needs_foo<T: Foo>() {}
623
+
trait Foo: Expression + Sized {
624
+
fn check<T>(&self, _: T) -> <T as AsExpression<<Self as Expression>::SqlType>>::Expression
625
+
where
626
+
T: AsExpression<Self::SqlType>,
627
+
{
628
+
todo!()
629
+
}
630
+
}
587
631
588
632
fn main() {
589
-
// Mutable pointers do not implement `Send`, so this will not work.
590
-
needs_foo::<*mut ()>();
633
+
SelectInt.check("bar");
591
634
}
592
635
```
593
636
594
-
the compiler may generate an error message about the `Send` bound in the impl which looks like this:
637
+
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:
595
638
596
639
```text
597
-
error[E0277]: the trait bound `*mut (): Foo` is not satisfied
598
-
--> src/main.rs:9:17
599
-
|
600
-
9 | needs_foo::<*mut ()>();
601
-
| ^^^^^^^ the trait `Send` is not implemented for `*mut ()`
602
-
|
603
-
note: required for `*mut ()` to implement `Foo`
604
-
--> src/main.rs:3:9
605
-
|
606
-
3 | impl<T> Foo for T where T: Send {}
607
-
| ^^^ ^ ---- unsatisfied trait bound introduced here
608
-
note: required by a bound in `needs_foo`
609
-
--> src/main.rs:5:17
610
-
|
611
-
5 | fn needs_foo<T: Foo>() {}
612
-
| ^^^ required by this bound in `needs_foo`
640
+
error[E0277]: the trait bound `&str: Expression` is not satisfied
641
+
--> src/main.rs:53:15
642
+
|
643
+
53 | SelectInt.check("bar");
644
+
| ^^^^^ the trait `Expression` is not implemented for `&str`
645
+
|
646
+
= help: the following other types implement trait `Expression`:
647
+
Bound<T>
648
+
SelectInt
649
+
note: required for `&str` to implement `AsExpression<Integer>`
650
+
--> src/main.rs:45:13
651
+
|
652
+
45 | impl<T, ST> AsExpression<ST> for T
653
+
| ^^^^^^^^^^^^^^^^ ^
654
+
46 | where
655
+
47 | T: Expression<SqlType = ST>,
656
+
| ------------------------ unsatisfied trait bound introduced here
613
657
```
614
658
615
-
By adding the `#[diagnostic::do_no_recommend]` attribute to the `impl`, the message would no longer suggest it:
659
+
By adding the `#[diagnostic::do_no_recommend]` attribute to the blanket `impl` for `AsExpression`, the message changes to:
616
660
617
661
```text
618
-
error[E0277]: the trait bound `*mut (): Foo` is not satisfied
619
-
--> src/main.rs:11:17
662
+
error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied
663
+
--> src/main.rs:53:15
620
664
|
621
-
11 | needs_foo::<*mut ()>();
622
-
| ^^^^^^^ the trait `Foo` is not implemented for `*mut ()`
665
+
53 | SelectInt.check("bar");
666
+
| ^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str`
623
667
|
624
-
note: required by a bound in `needs_foo`
625
-
--> src/main.rs:7:17
626
-
|
627
-
7 | fn needs_foo<T: Foo>() {}
628
-
| ^^^ required by this bound in `needs_foo`
668
+
= help: the trait `AsExpression<Integer>` is not implemented for `&str`
669
+
but trait `AsExpression<Text>` is implemented for it
670
+
= help: for that trait implementation, expected `Text`, found `Integer`
629
671
```
630
672
673
+
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_no_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`.
0 commit comments