mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-07 15:37:39 +00:00
internal: refactor missing unsafe diagnostic
This commit is contained in:
parent
886b66cd03
commit
bccf77f26c
@ -36,6 +36,7 @@ diagnostics![
|
|||||||
InactiveCode,
|
InactiveCode,
|
||||||
MacroError,
|
MacroError,
|
||||||
MissingFields,
|
MissingFields,
|
||||||
|
MissingUnsafe,
|
||||||
NoSuchField,
|
NoSuchField,
|
||||||
UnimplementedBuiltinMacro,
|
UnimplementedBuiltinMacro,
|
||||||
UnresolvedExternCrate,
|
UnresolvedExternCrate,
|
||||||
@ -104,28 +105,9 @@ pub struct BreakOutsideOfLoop {
|
|||||||
pub expr: InFile<AstPtr<ast::Expr>>,
|
pub expr: InFile<AstPtr<ast::Expr>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Diagnostic: missing-unsafe
|
|
||||||
//
|
|
||||||
// This diagnostic is triggered if an operation marked as `unsafe` is used outside of an `unsafe` function or block.
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MissingUnsafe {
|
pub struct MissingUnsafe {
|
||||||
pub file: HirFileId,
|
pub expr: InFile<AstPtr<ast::Expr>>,
|
||||||
pub expr: AstPtr<ast::Expr>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Diagnostic for MissingUnsafe {
|
|
||||||
fn code(&self) -> DiagnosticCode {
|
|
||||||
DiagnosticCode("missing-unsafe")
|
|
||||||
}
|
|
||||||
fn message(&self) -> String {
|
|
||||||
format!("This operation is unsafe and requires an unsafe function or block")
|
|
||||||
}
|
|
||||||
fn display_source(&self) -> InFile<SyntaxNodePtr> {
|
|
||||||
InFile { file_id: self.file, value: self.expr.clone().into() }
|
|
||||||
}
|
|
||||||
fn as_any(&self) -> &(dyn Any + Send + 'static) {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -1090,9 +1090,7 @@ impl Function {
|
|||||||
|
|
||||||
for expr in hir_ty::diagnostics::missing_unsafe(db, self.id.into()) {
|
for expr in hir_ty::diagnostics::missing_unsafe(db, self.id.into()) {
|
||||||
match source_map.expr_syntax(expr) {
|
match source_map.expr_syntax(expr) {
|
||||||
Ok(in_file) => {
|
Ok(expr) => acc.push(MissingUnsafe { expr }.into()),
|
||||||
sink.push(MissingUnsafe { file: in_file.file_id, expr: in_file.value })
|
|
||||||
}
|
|
||||||
Err(SyntheticSyntax) => {
|
Err(SyntheticSyntax) => {
|
||||||
// FIXME: Here and eslwhere in this file, the `expr` was
|
// FIXME: Here and eslwhere in this file, the `expr` was
|
||||||
// desugared, report or assert that this doesn't happen.
|
// desugared, report or assert that this doesn't happen.
|
||||||
|
@ -8,6 +8,7 @@ mod break_outside_of_loop;
|
|||||||
mod inactive_code;
|
mod inactive_code;
|
||||||
mod macro_error;
|
mod macro_error;
|
||||||
mod missing_fields;
|
mod missing_fields;
|
||||||
|
mod missing_unsafe;
|
||||||
mod no_such_field;
|
mod no_such_field;
|
||||||
mod unimplemented_builtin_macro;
|
mod unimplemented_builtin_macro;
|
||||||
mod unresolved_extern_crate;
|
mod unresolved_extern_crate;
|
||||||
@ -222,6 +223,7 @@ pub(crate) fn diagnostics(
|
|||||||
AnyDiagnostic::BreakOutsideOfLoop(d) => break_outside_of_loop::break_outside_of_loop(&ctx, &d),
|
AnyDiagnostic::BreakOutsideOfLoop(d) => break_outside_of_loop::break_outside_of_loop(&ctx, &d),
|
||||||
AnyDiagnostic::MacroError(d) => macro_error::macro_error(&ctx, &d),
|
AnyDiagnostic::MacroError(d) => macro_error::macro_error(&ctx, &d),
|
||||||
AnyDiagnostic::MissingFields(d) => missing_fields::missing_fields(&ctx, &d),
|
AnyDiagnostic::MissingFields(d) => missing_fields::missing_fields(&ctx, &d),
|
||||||
|
AnyDiagnostic::MissingUnsafe(d) => missing_unsafe::missing_unsafe(&ctx, &d),
|
||||||
AnyDiagnostic::NoSuchField(d) => no_such_field::no_such_field(&ctx, &d),
|
AnyDiagnostic::NoSuchField(d) => no_such_field::no_such_field(&ctx, &d),
|
||||||
AnyDiagnostic::UnimplementedBuiltinMacro(d) => unimplemented_builtin_macro::unimplemented_builtin_macro(&ctx, &d),
|
AnyDiagnostic::UnimplementedBuiltinMacro(d) => unimplemented_builtin_macro::unimplemented_builtin_macro(&ctx, &d),
|
||||||
AnyDiagnostic::UnresolvedExternCrate(d) => unresolved_extern_crate::unresolved_extern_crate(&ctx, &d),
|
AnyDiagnostic::UnresolvedExternCrate(d) => unresolved_extern_crate::unresolved_extern_crate(&ctx, &d),
|
||||||
@ -713,90 +715,6 @@ mod foo;
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn missing_unsafe_diagnostic_with_raw_ptr() {
|
|
||||||
check_diagnostics(
|
|
||||||
r#"
|
|
||||||
fn main() {
|
|
||||||
let x = &5 as *const usize;
|
|
||||||
unsafe { let y = *x; }
|
|
||||||
let z = *x;
|
|
||||||
} //^^ This operation is unsafe and requires an unsafe function or block
|
|
||||||
"#,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn missing_unsafe_diagnostic_with_unsafe_call() {
|
|
||||||
check_diagnostics(
|
|
||||||
r#"
|
|
||||||
struct HasUnsafe;
|
|
||||||
|
|
||||||
impl HasUnsafe {
|
|
||||||
unsafe fn unsafe_fn(&self) {
|
|
||||||
let x = &5 as *const usize;
|
|
||||||
let y = *x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn unsafe_fn() {
|
|
||||||
let x = &5 as *const usize;
|
|
||||||
let y = *x;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
unsafe_fn();
|
|
||||||
//^^^^^^^^^^^ This operation is unsafe and requires an unsafe function or block
|
|
||||||
HasUnsafe.unsafe_fn();
|
|
||||||
//^^^^^^^^^^^^^^^^^^^^^ This operation is unsafe and requires an unsafe function or block
|
|
||||||
unsafe {
|
|
||||||
unsafe_fn();
|
|
||||||
HasUnsafe.unsafe_fn();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"#,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn missing_unsafe_diagnostic_with_static_mut() {
|
|
||||||
check_diagnostics(
|
|
||||||
r#"
|
|
||||||
struct Ty {
|
|
||||||
a: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
static mut STATIC_MUT: Ty = Ty { a: 0 };
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let x = STATIC_MUT.a;
|
|
||||||
//^^^^^^^^^^ This operation is unsafe and requires an unsafe function or block
|
|
||||||
unsafe {
|
|
||||||
let x = STATIC_MUT.a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"#,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn no_missing_unsafe_diagnostic_with_safe_intrinsic() {
|
|
||||||
check_diagnostics(
|
|
||||||
r#"
|
|
||||||
extern "rust-intrinsic" {
|
|
||||||
pub fn bitreverse(x: u32) -> u32; // Safe intrinsic
|
|
||||||
pub fn floorf32(x: f32) -> f32; // Unsafe intrinsic
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let _ = bitreverse(12);
|
|
||||||
let _ = floorf32(12.0);
|
|
||||||
//^^^^^^^^^^^^^^ This operation is unsafe and requires an unsafe function or block
|
|
||||||
}
|
|
||||||
"#,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register the required standard library types to make the tests work
|
// Register the required standard library types to make the tests work
|
||||||
fn add_filter_map_with_find_next_boilerplate(body: &str) -> String {
|
fn add_filter_map_with_find_next_boilerplate(body: &str) -> String {
|
||||||
let prefix = r#"
|
let prefix = r#"
|
||||||
|
101
crates/ide/src/diagnostics/missing_unsafe.rs
Normal file
101
crates/ide/src/diagnostics/missing_unsafe.rs
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
use crate::diagnostics::{Diagnostic, DiagnosticsContext};
|
||||||
|
|
||||||
|
// Diagnostic: missing-unsafe
|
||||||
|
//
|
||||||
|
// This diagnostic is triggered if an operation marked as `unsafe` is used outside of an `unsafe` function or block.
|
||||||
|
pub(super) fn missing_unsafe(ctx: &DiagnosticsContext<'_>, d: &hir::MissingUnsafe) -> Diagnostic {
|
||||||
|
Diagnostic::new(
|
||||||
|
"missing-unsafe",
|
||||||
|
"this operation is unsafe and requires an unsafe function or block",
|
||||||
|
ctx.sema.diagnostics_display_range(d.expr.clone().map(|it| it.into())).range,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::diagnostics::tests::check_diagnostics;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn missing_unsafe_diagnostic_with_raw_ptr() {
|
||||||
|
check_diagnostics(
|
||||||
|
r#"
|
||||||
|
fn main() {
|
||||||
|
let x = &5 as *const usize;
|
||||||
|
unsafe { let y = *x; }
|
||||||
|
let z = *x;
|
||||||
|
} //^^ this operation is unsafe and requires an unsafe function or block
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn missing_unsafe_diagnostic_with_unsafe_call() {
|
||||||
|
check_diagnostics(
|
||||||
|
r#"
|
||||||
|
struct HasUnsafe;
|
||||||
|
|
||||||
|
impl HasUnsafe {
|
||||||
|
unsafe fn unsafe_fn(&self) {
|
||||||
|
let x = &5 as *const usize;
|
||||||
|
let y = *x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn unsafe_fn() {
|
||||||
|
let x = &5 as *const usize;
|
||||||
|
let y = *x;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
unsafe_fn();
|
||||||
|
//^^^^^^^^^^^ this operation is unsafe and requires an unsafe function or block
|
||||||
|
HasUnsafe.unsafe_fn();
|
||||||
|
//^^^^^^^^^^^^^^^^^^^^^ this operation is unsafe and requires an unsafe function or block
|
||||||
|
unsafe {
|
||||||
|
unsafe_fn();
|
||||||
|
HasUnsafe.unsafe_fn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn missing_unsafe_diagnostic_with_static_mut() {
|
||||||
|
check_diagnostics(
|
||||||
|
r#"
|
||||||
|
struct Ty {
|
||||||
|
a: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
static mut STATIC_MUT: Ty = Ty { a: 0 };
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x = STATIC_MUT.a;
|
||||||
|
//^^^^^^^^^^ this operation is unsafe and requires an unsafe function or block
|
||||||
|
unsafe {
|
||||||
|
let x = STATIC_MUT.a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_missing_unsafe_diagnostic_with_safe_intrinsic() {
|
||||||
|
check_diagnostics(
|
||||||
|
r#"
|
||||||
|
extern "rust-intrinsic" {
|
||||||
|
pub fn bitreverse(x: u32) -> u32; // Safe intrinsic
|
||||||
|
pub fn floorf32(x: f32) -> f32; // Unsafe intrinsic
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _ = bitreverse(12);
|
||||||
|
let _ = floorf32(12.0);
|
||||||
|
//^^^^^^^^^^^^^^ this operation is unsafe and requires an unsafe function or block
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user