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#![feature(lang_items)]
68#[lang = "drop"]
69trait Drop {}
70struct S<T>;
71struct L<'l>;
72
73 impl<T> Drop for S<T> {}
74
75 impl<#[may_dangle] T> Drop for S<T> {}
76//^^^^ error: impl for unsafe trait needs to be unsafe
77
78 unsafe impl<T> Drop for S<T> {}
79//^^^^^^^^^^^ error: unsafe impl for safe trait
80
81 unsafe impl<#[may_dangle] T> Drop for S<T> {}
82
83 impl<'l> Drop for L<'l> {}
84
85 impl<#[may_dangle] 'l> Drop for L<'l> {}
86//^^^^ error: impl for unsafe trait needs to be unsafe
87
88 unsafe impl<'l> Drop for L<'l> {}
89//^^^^^^^^^^^ error: unsafe impl for safe trait
90
91 unsafe impl<#[may_dangle] 'l> Drop for L<'l> {}
92"#,
93 );
94 }
95
96 #[test]
97 fn negative() {
98 check_diagnostics(
99 r#"
100trait Trait {}
101
102 impl !Trait for () {}
103
104 unsafe impl !Trait for () {}
105//^^^^^^^^^^^ error: unsafe impl for safe trait
106
107unsafe trait UnsafeTrait {}
108
109 impl !UnsafeTrait for () {}
110
111 unsafe impl !UnsafeTrait for () {}
112//^^^^^^^^^^^ error: unsafe impl for safe trait
113
114"#,
115 );
116 }
117
118 #[test]
119 fn inherent() {
120 check_diagnostics(
121 r#"
122struct S;
123
124 impl S {}
125
126 unsafe impl S {}
127//^^^^^^^^^^^ error: unsafe impl for safe trait
128"#,
129 );
130 }
131
132 #[test]
133 fn unsafe_unresolved_trait() {
134 check_diagnostics(
135 r#"
136unsafe impl TestTrait for u32 {}
137 "#,
138 );
139 }
140}