Skip to content

Commit bccf77f

Browse files
committed
internal: refactor missing unsafe diagnostic
1 parent 886b66c commit bccf77f

File tree

4 files changed

+106
-107
lines changed

4 files changed

+106
-107
lines changed

crates/hir/src/diagnostics.rs

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ diagnostics![
3636
InactiveCode,
3737
MacroError,
3838
MissingFields,
39+
MissingUnsafe,
3940
NoSuchField,
4041
UnimplementedBuiltinMacro,
4142
UnresolvedExternCrate,
@@ -104,28 +105,9 @@ pub struct BreakOutsideOfLoop {
104105
pub expr: InFile<AstPtr<ast::Expr>>,
105106
}
106107

107-
// Diagnostic: missing-unsafe
108-
//
109-
// This diagnostic is triggered if an operation marked as `unsafe` is used outside of an `unsafe` function or block.
110108
#[derive(Debug)]
111109
pub struct MissingUnsafe {
112-
pub file: HirFileId,
113-
pub expr: AstPtr<ast::Expr>,
114-
}
115-
116-
impl Diagnostic for MissingUnsafe {
117-
fn code(&self) -> DiagnosticCode {
118-
DiagnosticCode("missing-unsafe")
119-
}
120-
fn message(&self) -> String {
121-
format!("This operation is unsafe and requires an unsafe function or block")
122-
}
123-
fn display_source(&self) -> InFile<SyntaxNodePtr> {
124-
InFile { file_id: self.file, value: self.expr.clone().into() }
125-
}
126-
fn as_any(&self) -> &(dyn Any + Send + 'static) {
127-
self
128-
}
110+
pub expr: InFile<AstPtr<ast::Expr>>,
129111
}
130112

131113
#[derive(Debug)]

crates/hir/src/lib.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,9 +1090,7 @@ impl Function {
10901090

10911091
for expr in hir_ty::diagnostics::missing_unsafe(db, self.id.into()) {
10921092
match source_map.expr_syntax(expr) {
1093-
Ok(in_file) => {
1094-
sink.push(MissingUnsafe { file: in_file.file_id, expr: in_file.value })
1095-
}
1093+
Ok(expr) => acc.push(MissingUnsafe { expr }.into()),
10961094
Err(SyntheticSyntax) => {
10971095
// FIXME: Here and eslwhere in this file, the `expr` was
10981096
// desugared, report or assert that this doesn't happen.

crates/ide/src/diagnostics.rs

Lines changed: 2 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ mod break_outside_of_loop;
88
mod inactive_code;
99
mod macro_error;
1010
mod missing_fields;
11+
mod missing_unsafe;
1112
mod no_such_field;
1213
mod unimplemented_builtin_macro;
1314
mod unresolved_extern_crate;
@@ -222,6 +223,7 @@ pub(crate) fn diagnostics(
222223
AnyDiagnostic::BreakOutsideOfLoop(d) => break_outside_of_loop::break_outside_of_loop(&ctx, &d),
223224
AnyDiagnostic::MacroError(d) => macro_error::macro_error(&ctx, &d),
224225
AnyDiagnostic::MissingFields(d) => missing_fields::missing_fields(&ctx, &d),
226+
AnyDiagnostic::MissingUnsafe(d) => missing_unsafe::missing_unsafe(&ctx, &d),
225227
AnyDiagnostic::NoSuchField(d) => no_such_field::no_such_field(&ctx, &d),
226228
AnyDiagnostic::UnimplementedBuiltinMacro(d) => unimplemented_builtin_macro::unimplemented_builtin_macro(&ctx, &d),
227229
AnyDiagnostic::UnresolvedExternCrate(d) => unresolved_extern_crate::unresolved_extern_crate(&ctx, &d),
@@ -713,90 +715,6 @@ mod foo;
713715
);
714716
}
715717

716-
#[test]
717-
fn missing_unsafe_diagnostic_with_raw_ptr() {
718-
check_diagnostics(
719-
r#"
720-
fn main() {
721-
let x = &5 as *const usize;
722-
unsafe { let y = *x; }
723-
let z = *x;
724-
} //^^ This operation is unsafe and requires an unsafe function or block
725-
"#,
726-
)
727-
}
728-
729-
#[test]
730-
fn missing_unsafe_diagnostic_with_unsafe_call() {
731-
check_diagnostics(
732-
r#"
733-
struct HasUnsafe;
734-
735-
impl HasUnsafe {
736-
unsafe fn unsafe_fn(&self) {
737-
let x = &5 as *const usize;
738-
let y = *x;
739-
}
740-
}
741-
742-
unsafe fn unsafe_fn() {
743-
let x = &5 as *const usize;
744-
let y = *x;
745-
}
746-
747-
fn main() {
748-
unsafe_fn();
749-
//^^^^^^^^^^^ This operation is unsafe and requires an unsafe function or block
750-
HasUnsafe.unsafe_fn();
751-
//^^^^^^^^^^^^^^^^^^^^^ This operation is unsafe and requires an unsafe function or block
752-
unsafe {
753-
unsafe_fn();
754-
HasUnsafe.unsafe_fn();
755-
}
756-
}
757-
"#,
758-
);
759-
}
760-
761-
#[test]
762-
fn missing_unsafe_diagnostic_with_static_mut() {
763-
check_diagnostics(
764-
r#"
765-
struct Ty {
766-
a: u8,
767-
}
768-
769-
static mut STATIC_MUT: Ty = Ty { a: 0 };
770-
771-
fn main() {
772-
let x = STATIC_MUT.a;
773-
//^^^^^^^^^^ This operation is unsafe and requires an unsafe function or block
774-
unsafe {
775-
let x = STATIC_MUT.a;
776-
}
777-
}
778-
"#,
779-
);
780-
}
781-
782-
#[test]
783-
fn no_missing_unsafe_diagnostic_with_safe_intrinsic() {
784-
check_diagnostics(
785-
r#"
786-
extern "rust-intrinsic" {
787-
pub fn bitreverse(x: u32) -> u32; // Safe intrinsic
788-
pub fn floorf32(x: f32) -> f32; // Unsafe intrinsic
789-
}
790-
791-
fn main() {
792-
let _ = bitreverse(12);
793-
let _ = floorf32(12.0);
794-
//^^^^^^^^^^^^^^ This operation is unsafe and requires an unsafe function or block
795-
}
796-
"#,
797-
);
798-
}
799-
800718
// Register the required standard library types to make the tests work
801719
fn add_filter_map_with_find_next_boilerplate(body: &str) -> String {
802720
let prefix = r#"
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
use crate::diagnostics::{Diagnostic, DiagnosticsContext};
2+
3+
// Diagnostic: missing-unsafe
4+
//
5+
// This diagnostic is triggered if an operation marked as `unsafe` is used outside of an `unsafe` function or block.
6+
pub(super) fn missing_unsafe(ctx: &DiagnosticsContext<'_>, d: &hir::MissingUnsafe) -> Diagnostic {
7+
Diagnostic::new(
8+
"missing-unsafe",
9+
"this operation is unsafe and requires an unsafe function or block",
10+
ctx.sema.diagnostics_display_range(d.expr.clone().map(|it| it.into())).range,
11+
)
12+
}
13+
14+
#[cfg(test)]
15+
mod tests {
16+
use crate::diagnostics::tests::check_diagnostics;
17+
18+
#[test]
19+
fn missing_unsafe_diagnostic_with_raw_ptr() {
20+
check_diagnostics(
21+
r#"
22+
fn main() {
23+
let x = &5 as *const usize;
24+
unsafe { let y = *x; }
25+
let z = *x;
26+
} //^^ this operation is unsafe and requires an unsafe function or block
27+
"#,
28+
)
29+
}
30+
31+
#[test]
32+
fn missing_unsafe_diagnostic_with_unsafe_call() {
33+
check_diagnostics(
34+
r#"
35+
struct HasUnsafe;
36+
37+
impl HasUnsafe {
38+
unsafe fn unsafe_fn(&self) {
39+
let x = &5 as *const usize;
40+
let y = *x;
41+
}
42+
}
43+
44+
unsafe fn unsafe_fn() {
45+
let x = &5 as *const usize;
46+
let y = *x;
47+
}
48+
49+
fn main() {
50+
unsafe_fn();
51+
//^^^^^^^^^^^ this operation is unsafe and requires an unsafe function or block
52+
HasUnsafe.unsafe_fn();
53+
//^^^^^^^^^^^^^^^^^^^^^ this operation is unsafe and requires an unsafe function or block
54+
unsafe {
55+
unsafe_fn();
56+
HasUnsafe.unsafe_fn();
57+
}
58+
}
59+
"#,
60+
);
61+
}
62+
63+
#[test]
64+
fn missing_unsafe_diagnostic_with_static_mut() {
65+
check_diagnostics(
66+
r#"
67+
struct Ty {
68+
a: u8,
69+
}
70+
71+
static mut STATIC_MUT: Ty = Ty { a: 0 };
72+
73+
fn main() {
74+
let x = STATIC_MUT.a;
75+
//^^^^^^^^^^ this operation is unsafe and requires an unsafe function or block
76+
unsafe {
77+
let x = STATIC_MUT.a;
78+
}
79+
}
80+
"#,
81+
);
82+
}
83+
84+
#[test]
85+
fn no_missing_unsafe_diagnostic_with_safe_intrinsic() {
86+
check_diagnostics(
87+
r#"
88+
extern "rust-intrinsic" {
89+
pub fn bitreverse(x: u32) -> u32; // Safe intrinsic
90+
pub fn floorf32(x: f32) -> f32; // Unsafe intrinsic
91+
}
92+
93+
fn main() {
94+
let _ = bitreverse(12);
95+
let _ = floorf32(12.0);
96+
//^^^^^^^^^^^^^^ this operation is unsafe and requires an unsafe function or block
97+
}
98+
"#,
99+
);
100+
}
101+
}

0 commit comments

Comments
 (0)