ide_diagnostics/handlers/
trait_impl_incorrect_safety.rs1use hir::InFile;
2use syntax::ast;
3
4use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext, Severity, adjusted_display_range};
5
6pub(crate) fn trait_impl_incorrect_safety(
10 ctx: &DiagnosticsContext<'_>,
11 d: &hir::TraitImplIncorrectSafety,
12) -> Diagnostic {
13 Diagnostic::new(
14 DiagnosticCode::Ra("trait-impl-incorrect-safety", Severity::Error),
15 if d.should_be_safe {
16 "unsafe impl for safe trait"
17 } else {
18 "impl for unsafe trait needs to be unsafe"
19 },
20 adjusted_display_range::<ast::Impl>(
21 ctx,
22 InFile { file_id: d.file_id, value: d.impl_ },
23 &|impl_| {
24 if d.should_be_safe {
25 Some(match (impl_.unsafe_token(), impl_.impl_token()) {
26 (None, None) => return None,
27 (None, Some(t)) | (Some(t), None) => t.text_range(),
28 (Some(t1), Some(t2)) => t1.text_range().cover(t2.text_range()),
29 })
30 } else {
31 impl_.impl_token().map(|t| t.text_range())
32 }
33 },
34 ),
35 )
36 .stable()
37}
38
39#[cfg(test)]
40mod tests {
41 use crate::tests::check_diagnostics;
42
43 #[test]
44 fn simple() {
45 check_diagnostics(
46 r#"
47trait Safe {}
48unsafe trait Unsafe {}
49
50 impl Safe for () {}
51
52 impl Unsafe for () {}
53//^^^^ error: impl for unsafe trait needs to be unsafe
54
55 unsafe impl Safe for () {}
56//^^^^^^^^^^^ error: unsafe impl for safe trait
57
58 unsafe impl Unsafe for () {}
59"#,
60 );
61 }
62
63 #[test]
64 fn drop_may_dangle() {
65 check_diagnostics(
66 r#"
67#[lang = "drop"]
68trait Drop {}
69struct S<T>;
70struct L<'l>;
71
72 impl<T> Drop for S<T> {}
73
74 impl<#[may_dangle] T> Drop for S<T> {}
75//^^^^ error: impl for unsafe trait needs to be unsafe
76
77 unsafe impl<T> Drop for S<T> {}
78//^^^^^^^^^^^ error: unsafe impl for safe trait
79
80 unsafe impl<#[may_dangle] T> Drop for S<T> {}
81
82 impl<'l> Drop for L<'l> {}
83
84 impl<#[may_dangle] 'l> Drop for L<'l> {}
85//^^^^ error: impl for unsafe trait needs to be unsafe
86
87 unsafe impl<'l> Drop for L<'l> {}
88//^^^^^^^^^^^ error: unsafe impl for safe trait
89
90 unsafe impl<#[may_dangle] 'l> Drop for L<'l> {}
91"#,
92 );
93 }
94
95 #[test]
96 fn negative() {
97 check_diagnostics(
98 r#"
99trait Trait {}
100
101 impl !Trait for () {}
102
103 unsafe impl !Trait for () {}
104//^^^^^^^^^^^ error: unsafe impl for safe trait
105
106unsafe trait UnsafeTrait {}
107
108 impl !UnsafeTrait for () {}
109
110 unsafe impl !UnsafeTrait for () {}
111//^^^^^^^^^^^ error: unsafe impl for safe trait
112
113"#,
114 );
115 }
116
117 #[test]
118 fn inherent() {
119 check_diagnostics(
120 r#"
121struct S;
122
123 impl S {}
124
125 unsafe impl S {}
126//^^^^^^^^^^^ error: unsafe impl for safe trait
127"#,
128 );
129 }
130
131 #[test]
132 fn unsafe_unresolved_trait() {
133 check_diagnostics(
134 r#"
135unsafe impl TestTrait for u32 {}
136 "#,
137 );
138 }
139}