ide_diagnostics/handlers/
unimplemented_trait.rs1use hir::HirDisplay;
2
3use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
4
5pub(crate) fn unimplemented_trait<'db>(
9 ctx: &DiagnosticsContext<'_, 'db>,
10 d: &hir::UnimplementedTrait<'db>,
11) -> Diagnostic {
12 let message = match &d.root_trait_predicate {
13 Some(root_predicate) if *root_predicate != d.trait_predicate => format!(
14 "the trait bound `{}` is not satisfied\n\
15 required by the bound `{}`\n",
16 d.trait_predicate.display(ctx.db(), ctx.display_target),
17 root_predicate.display(ctx.db(), ctx.display_target),
18 ),
19 _ => format!(
20 "the trait bound `{}` is not satisfied",
21 d.trait_predicate.display(ctx.db(), ctx.display_target),
22 ),
23 };
24 Diagnostic::new_with_syntax_node_ptr(
25 ctx,
26 DiagnosticCode::RustcHardError("E0277"),
27 message,
28 d.span.map(Into::into),
29 )
30}
31
32#[cfg(test)]
33mod tests {
34 use crate::tests::check_diagnostics;
35
36 #[test]
37 fn smoke_test() {
38 check_diagnostics(
39 r#"
40trait Trait {}
41impl<T: Trait, const N: usize> Trait for [T; N] {}
42fn foo(_v: impl Trait) {}
43fn bar() {
44 foo(1);
45 // ^^^ error: the trait bound `i32: Trait` is not satisfied
46 foo([1]);
47 // ^^^ error: the trait bound `i32: Trait` is not satisfied
48 // | required by the bound `[i32; 1]: Trait`
49}
50 "#,
51 );
52 }
53
54 #[test]
55 fn async_closure_does_not_trigger() {
56 check_diagnostics(
57 r#"
58//- minicore: async_fn
59fn spawn_in<AsyncFn>(_f: AsyncFn)
60where
61 AsyncFn: AsyncFnOnce(),
62{
63}
64
65fn foo() {
66 spawn_in(async move || {});
67}
68
69 "#,
70 );
71 }
72}