ide_diagnostics/handlers/
trait_impl_missing_assoc_item.rs

1use hir::InFile;
2use itertools::Itertools;
3use syntax::{AstNode, ast};
4
5use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext, adjusted_display_range};
6
7// Diagnostic: trait-impl-missing-assoc_item
8//
9// Diagnoses missing trait items in a trait impl.
10pub(crate) fn trait_impl_missing_assoc_item(
11    ctx: &DiagnosticsContext<'_>,
12    d: &hir::TraitImplMissingAssocItems,
13) -> Diagnostic {
14    let missing = d.missing.iter().format_with(", ", |(name, item), f| {
15        f(&match *item {
16            hir::AssocItem::Function(_) => "`fn ",
17            hir::AssocItem::Const(_) => "`const ",
18            hir::AssocItem::TypeAlias(_) => "`type ",
19        })?;
20        f(&name.display(ctx.sema.db, ctx.edition))?;
21        f(&"`")
22    });
23    Diagnostic::new(
24        DiagnosticCode::RustcHardError("E0046"),
25        format!("not all trait items implemented, missing: {missing}"),
26        adjusted_display_range::<ast::Impl>(
27            ctx,
28            InFile { file_id: d.file_id, value: d.impl_ },
29            &|impl_| impl_.trait_().map(|t| t.syntax().text_range()),
30        ),
31    )
32    .stable()
33}
34
35#[cfg(test)]
36mod tests {
37    use crate::tests::check_diagnostics;
38
39    #[test]
40    fn trait_with_default_value() {
41        check_diagnostics(
42            r#"
43trait Marker {
44    const FLAG: bool = false;
45}
46struct Foo;
47impl Marker for Foo {}
48            "#,
49        )
50    }
51
52    #[test]
53    fn simple() {
54        check_diagnostics(
55            r#"
56trait Trait {
57    const C: ();
58    type T;
59    fn f();
60}
61
62impl Trait for () {
63    const C: () = ();
64    type T = ();
65    fn f() {}
66}
67
68impl Trait for () {
69   //^^^^^ error: not all trait items implemented, missing: `const C`
70    type T = ();
71    fn f() {}
72}
73
74impl Trait for () {
75   //^^^^^ error: not all trait items implemented, missing: `const C`, `type T`, `fn f`
76}
77
78"#,
79        );
80    }
81
82    #[test]
83    fn default() {
84        check_diagnostics(
85            r#"
86trait Trait {
87    const C: ();
88    type T = ();
89    fn f() {}
90}
91
92impl Trait for () {
93    const C: () = ();
94    type T = ();
95    fn f() {}
96}
97
98impl Trait for () {
99   //^^^^^ error: not all trait items implemented, missing: `const C`
100    type T = ();
101    fn f() {}
102}
103
104impl Trait for () {
105   //^^^^^ error: not all trait items implemented, missing: `const C`
106     type T = ();
107 }
108
109impl Trait for () {
110   //^^^^^ error: not all trait items implemented, missing: `const C`
111}
112
113"#,
114        );
115    }
116
117    #[test]
118    fn negative_impl() {
119        check_diagnostics(
120            r#"
121trait Trait {
122    fn item();
123}
124
125// Negative impls don't require any items (in fact, the forbid providing any)
126impl !Trait for () {}
127"#,
128        )
129    }
130
131    #[test]
132    fn impl_sized_for_unsized() {
133        check_diagnostics(
134            r#"
135//- minicore: sized
136trait Trait {
137    type Item
138    where
139        Self: Sized;
140
141    fn item()
142    where
143        Self: Sized;
144}
145
146trait OtherTrait {}
147
148impl Trait for () {
149    type Item = ();
150    fn item() {}
151}
152
153// Items with Self: Sized bound not required to be implemented for unsized types.
154impl Trait for str {}
155impl Trait for dyn OtherTrait {}
156 "#,
157        )
158    }
159}