Skip to main content

ide_diagnostics/handlers/
unimplemented_trait.rs

1use hir::HirDisplay;
2
3use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
4
5// Diagnostic: unimplemented-trait
6//
7// This diagnostic is triggered when rust-analyzer cannot infer some type.
8pub(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}