about summary refs log tree commit diff
path: root/tests/ui/lint
diff options
context:
space:
mode:
authorUrgau <urgau@numericable.fr>2025-07-22 20:54:22 +0200
committerUrgau <urgau@numericable.fr>2025-07-31 22:35:22 +0200
commit8a3a7e625a8b607c018cdcf776fa79e29eaa56c8 (patch)
treeb34ccaa4dda9cf5e46ce33ace6ac34fc28be5af3 /tests/ui/lint
parentadcb3d3b4cd3b7c4cde642f3ed537037f293738e (diff)
downloadrust-8a3a7e625a8b607c018cdcf776fa79e29eaa56c8.tar.gz
rust-8a3a7e625a8b607c018cdcf776fa79e29eaa56c8.zip
Add lint against dangling pointers form local variables
Diffstat (limited to 'tests/ui/lint')
-rw-r--r--tests/ui/lint/dangling-pointers-from-locals.rs188
-rw-r--r--tests/ui/lint/dangling-pointers-from-locals.stderr247
2 files changed, 435 insertions, 0 deletions
diff --git a/tests/ui/lint/dangling-pointers-from-locals.rs b/tests/ui/lint/dangling-pointers-from-locals.rs
new file mode 100644
index 00000000000..e321df2f427
--- /dev/null
+++ b/tests/ui/lint/dangling-pointers-from-locals.rs
@@ -0,0 +1,188 @@
+//@ check-pass
+
+struct Zst((), ());
+struct Adt(u8);
+
+const X: u8 = 5;
+
+fn simple() -> *const u8 {
+    let x = 0;
+    &x
+    //~^ WARN a dangling pointer will be produced
+}
+
+fn bindings() -> *const u8 {
+    let x = 0;
+    let x = &x;
+    x
+    //~^ WARN a dangling pointer will be produced
+}
+
+fn bindings_with_return() -> *const u8 {
+    let x = 42;
+    let y = &x;
+    return y;
+    //~^ WARN a dangling pointer will be produced
+}
+
+fn with_simple_cast() -> *const u8 {
+    let x = 0u8;
+    &x as *const u8
+    //~^ WARN a dangling pointer will be produced
+}
+
+fn bindings_and_casts() -> *const u8 {
+    let x = 0u8;
+    let x = &x as *const u8;
+    x as *const u8
+    //~^ WARN a dangling pointer will be produced
+}
+
+fn return_with_complex_cast() -> *mut u8 {
+    let mut x = 0u8;
+    return &mut x as *mut u8 as *const u8 as *mut u8;
+    //~^ WARN a dangling pointer will be produced
+}
+
+fn with_block() -> *const u8 {
+    let x = 0;
+    &{ x }
+    //~^ WARN a dangling pointer will be produced
+}
+
+fn with_many_blocks() -> *const u8 {
+    let x = 0;
+    {
+        {
+            &{
+                //~^ WARN a dangling pointer will be produced
+                { x }
+            }
+        }
+    }
+}
+
+fn simple_return() -> *const u8 {
+    let x = 0;
+    return &x;
+    //~^ WARN a dangling pointer will be produced
+}
+
+fn return_mut() -> *mut u8 {
+    let mut x = 0;
+    return &mut x;
+    //~^ WARN a dangling pointer will be produced
+}
+
+fn const_and_flow() -> *const u8 {
+    if false {
+        let x = 8;
+        return &x;
+        //~^ WARN a dangling pointer will be produced
+    }
+    &X // not dangling
+}
+
+fn vector<T: Default>() -> *const Vec<T> {
+    let x = vec![T::default()];
+    &x
+    //~^ WARN a dangling pointer will be produced
+}
+
+fn local_adt() -> *const Adt {
+    let x = Adt(5);
+    return &x;
+    //~^ WARN a dangling pointer will be produced
+}
+
+fn closure() -> *const u8 {
+    let _x = || -> *const u8 {
+        let x = 8;
+        return &x;
+        //~^ WARN a dangling pointer will be produced
+    };
+    &X // not dangling
+}
+
+fn fn_ptr() -> *const fn() -> u8 {
+    fn ret_u8() -> u8 {
+        0
+    }
+
+    let x = ret_u8 as fn() -> u8;
+    &x
+    //~^ WARN a dangling pointer will be produced
+}
+
+fn as_arg(a: Adt) -> *const Adt {
+    &a
+    //~^ WARN a dangling pointer will be produced
+}
+
+fn fn_ptr_as_arg(a: fn() -> u8) -> *const fn() -> u8 {
+    &a
+    //~^ WARN a dangling pointer will be produced
+}
+
+fn ptr_as_arg(a: *const Adt) -> *const *const Adt {
+    &a
+    //~^ WARN a dangling pointer will be produced
+}
+
+fn adt_as_arg(a: &Adt) -> *const &Adt {
+    &a
+    //~^ WARN a dangling pointer will be produced
+}
+
+fn unit() -> *const () {
+    let x = ();
+    &x // not dangling
+}
+
+fn zst() -> *const Zst {
+    let x = Zst((), ());
+    &x // not dangling
+}
+
+fn ref_implicit(a: &Adt) -> *const Adt {
+    a // not dangling
+}
+
+fn ref_explicit(a: &Adt) -> *const Adt {
+    &*a // not dangling
+}
+
+fn identity(a: *const Adt) -> *const Adt {
+    a // not dangling
+}
+
+fn from_ref(a: &Adt) -> *const Adt {
+    std::ptr::from_ref(a) // not dangling
+}
+
+fn inner_static() -> *const u8 {
+    static U: u8 = 5;
+    if false {
+        return &U as *const u8; // not dangling
+    }
+    &U // not dangling
+}
+
+fn return_in_closure() {
+    let x = 0;
+    let c = || -> *const u8 {
+        &x // not dangling by it-self
+    };
+}
+
+fn option<T: Default>() -> *const Option<T> {
+    let x = Some(T::default());
+    &x // can't compute layout of `Option<T>`, so cnat' be sure it won't be a ZST
+}
+
+fn generic<T: Default>() -> *const T {
+    let x = T::default();
+    &x // can't compute layout of `T`, so can't be sure it won't be a ZST
+}
+
+fn main() {}
diff --git a/tests/ui/lint/dangling-pointers-from-locals.stderr b/tests/ui/lint/dangling-pointers-from-locals.stderr
new file mode 100644
index 00000000000..e1d28bf22a0
--- /dev/null
+++ b/tests/ui/lint/dangling-pointers-from-locals.stderr
@@ -0,0 +1,247 @@
+warning: a dangling pointer will be produced because the local variable `x` will be dropped
+  --> $DIR/dangling-pointers-from-locals.rs:10:5
+   |
+LL | fn simple() -> *const u8 {
+   |                --------- return type of the function is `*const u8`
+LL |     let x = 0;
+   |         - `x` is part the function and will be dropped at the end of the function
+LL |     &x
+   |     ^^
+   |
+   = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
+   = note: `#[warn(dangling_pointers_from_locals)]` on by default
+
+warning: a dangling pointer will be produced because the local variable `x` will be dropped
+  --> $DIR/dangling-pointers-from-locals.rs:17:5
+   |
+LL | fn bindings() -> *const u8 {
+   |                  --------- return type of the function is `*const u8`
+LL |     let x = 0;
+   |         - `x` is part the function and will be dropped at the end of the function
+LL |     let x = &x;
+   |             -- dangling pointer created here
+LL |     x
+   |     ^
+   |
+   = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
+
+warning: a dangling pointer will be produced because the local variable `x` will be dropped
+  --> $DIR/dangling-pointers-from-locals.rs:24:12
+   |
+LL | fn bindings_with_return() -> *const u8 {
+   |                              --------- return type of the function is `*const u8`
+LL |     let x = 42;
+   |         - `x` is part the function and will be dropped at the end of the function
+LL |     let y = &x;
+   |             -- dangling pointer created here
+LL |     return y;
+   |            ^
+   |
+   = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
+
+warning: a dangling pointer will be produced because the local variable `x` will be dropped
+  --> $DIR/dangling-pointers-from-locals.rs:30:5
+   |
+LL | fn with_simple_cast() -> *const u8 {
+   |                          --------- return type of the function is `*const u8`
+LL |     let x = 0u8;
+   |         - `x` is part the function and will be dropped at the end of the function
+LL |     &x as *const u8
+   |     --^^^^^^^^^^^^^
+   |     |
+   |     dangling pointer created here
+   |
+   = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
+
+warning: a dangling pointer will be produced because the local variable `x` will be dropped
+  --> $DIR/dangling-pointers-from-locals.rs:37:5
+   |
+LL | fn bindings_and_casts() -> *const u8 {
+   |                            --------- return type of the function is `*const u8`
+LL |     let x = 0u8;
+   |         - `x` is part the function and will be dropped at the end of the function
+LL |     let x = &x as *const u8;
+   |             -- dangling pointer created here
+LL |     x as *const u8
+   |     ^^^^^^^^^^^^^^
+   |
+   = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
+
+warning: a dangling pointer will be produced because the local variable `x` will be dropped
+  --> $DIR/dangling-pointers-from-locals.rs:43:12
+   |
+LL | fn return_with_complex_cast() -> *mut u8 {
+   |                                  ------- return type of the function is `*mut u8`
+LL |     let mut x = 0u8;
+   |         ----- `x` is part the function and will be dropped at the end of the function
+LL |     return &mut x as *mut u8 as *const u8 as *mut u8;
+   |            ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            |
+   |            dangling pointer created here
+   |
+   = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
+
+warning: a dangling pointer will be produced because the local variable `x` will be dropped
+  --> $DIR/dangling-pointers-from-locals.rs:49:5
+   |
+LL | fn with_block() -> *const u8 {
+   |                    --------- return type of the function is `*const u8`
+LL |     let x = 0;
+   |         - `x` is part the function and will be dropped at the end of the function
+LL |     &{ x }
+   |     ^^^^^^
+   |
+   = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
+
+warning: a dangling pointer will be produced because the local variable `x` will be dropped
+  --> $DIR/dangling-pointers-from-locals.rs:57:13
+   |
+LL |   fn with_many_blocks() -> *const u8 {
+   |                            --------- return type of the function is `*const u8`
+LL |       let x = 0;
+   |           - `x` is part the function and will be dropped at the end of the function
+...
+LL | /             &{
+LL | |
+LL | |                 { x }
+LL | |             }
+   | |_____________^
+   |
+   = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
+
+warning: a dangling pointer will be produced because the local variable `x` will be dropped
+  --> $DIR/dangling-pointers-from-locals.rs:67:12
+   |
+LL | fn simple_return() -> *const u8 {
+   |                       --------- return type of the function is `*const u8`
+LL |     let x = 0;
+   |         - `x` is part the function and will be dropped at the end of the function
+LL |     return &x;
+   |            ^^
+   |
+   = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
+
+warning: a dangling pointer will be produced because the local variable `x` will be dropped
+  --> $DIR/dangling-pointers-from-locals.rs:73:12
+   |
+LL | fn return_mut() -> *mut u8 {
+   |                    ------- return type of the function is `*mut u8`
+LL |     let mut x = 0;
+   |         ----- `x` is part the function and will be dropped at the end of the function
+LL |     return &mut x;
+   |            ^^^^^^
+   |
+   = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
+
+warning: a dangling pointer will be produced because the local variable `x` will be dropped
+  --> $DIR/dangling-pointers-from-locals.rs:80:16
+   |
+LL | fn const_and_flow() -> *const u8 {
+   |                        --------- return type of the function is `*const u8`
+LL |     if false {
+LL |         let x = 8;
+   |             - `x` is part the function and will be dropped at the end of the function
+LL |         return &x;
+   |                ^^
+   |
+   = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
+
+warning: a dangling pointer will be produced because the local variable `x` will be dropped
+  --> $DIR/dangling-pointers-from-locals.rs:88:5
+   |
+LL | fn vector<T: Default>() -> *const Vec<T> {
+   |                            ------------- return type of the function is `*const Vec<T>`
+LL |     let x = vec![T::default()];
+   |         - `x` is part the function and will be dropped at the end of the function
+LL |     &x
+   |     ^^
+   |
+   = note: pointers do not have a lifetime; after returning, the `Vec<T>` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
+
+warning: a dangling pointer will be produced because the local variable `x` will be dropped
+  --> $DIR/dangling-pointers-from-locals.rs:94:12
+   |
+LL | fn local_adt() -> *const Adt {
+   |                   ---------- return type of the function is `*const Adt`
+LL |     let x = Adt(5);
+   |         - `x` is part the function and will be dropped at the end of the function
+LL |     return &x;
+   |            ^^
+   |
+   = note: pointers do not have a lifetime; after returning, the `Adt` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
+
+warning: a dangling pointer will be produced because the local variable `x` will be dropped
+  --> $DIR/dangling-pointers-from-locals.rs:101:16
+   |
+LL |     let _x = || -> *const u8 {
+   |                    --------- return type of the closure is `*const u8`
+LL |         let x = 8;
+   |             - `x` is part the closure and will be dropped at the end of the closure
+LL |         return &x;
+   |                ^^
+   |
+   = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the closure because nothing is referencing it as far as the type system is concerned
+
+warning: a dangling pointer will be produced because the local variable `x` will be dropped
+  --> $DIR/dangling-pointers-from-locals.rs:113:5
+   |
+LL | fn fn_ptr() -> *const fn() -> u8 {
+   |                ----------------- return type of the function is `*const fn() -> u8`
+...
+LL |     let x = ret_u8 as fn() -> u8;
+   |         - `x` is part the function and will be dropped at the end of the function
+LL |     &x
+   |     ^^
+   |
+   = note: pointers do not have a lifetime; after returning, the `fn() -> u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
+
+warning: a dangling pointer will be produced because the local variable `a` will be dropped
+  --> $DIR/dangling-pointers-from-locals.rs:118:5
+   |
+LL | fn as_arg(a: Adt) -> *const Adt {
+   |           -          ---------- return type of the function is `*const Adt`
+   |           |
+   |           `a` is part the function and will be dropped at the end of the function
+LL |     &a
+   |     ^^
+   |
+   = note: pointers do not have a lifetime; after returning, the `Adt` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
+
+warning: a dangling pointer will be produced because the local variable `a` will be dropped
+  --> $DIR/dangling-pointers-from-locals.rs:123:5
+   |
+LL | fn fn_ptr_as_arg(a: fn() -> u8) -> *const fn() -> u8 {
+   |                  -                 ----------------- return type of the function is `*const fn() -> u8`
+   |                  |
+   |                  `a` is part the function and will be dropped at the end of the function
+LL |     &a
+   |     ^^
+   |
+   = note: pointers do not have a lifetime; after returning, the `fn() -> u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
+
+warning: a dangling pointer will be produced because the local variable `a` will be dropped
+  --> $DIR/dangling-pointers-from-locals.rs:128:5
+   |
+LL | fn ptr_as_arg(a: *const Adt) -> *const *const Adt {
+   |               -                 ----------------- return type of the function is `*const *const Adt`
+   |               |
+   |               `a` is part the function and will be dropped at the end of the function
+LL |     &a
+   |     ^^
+   |
+   = note: pointers do not have a lifetime; after returning, the `*const Adt` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
+
+warning: a dangling pointer will be produced because the local variable `a` will be dropped
+  --> $DIR/dangling-pointers-from-locals.rs:133:5
+   |
+LL | fn adt_as_arg(a: &Adt) -> *const &Adt {
+   |               -           ----------- return type of the function is `*const &Adt`
+   |               |
+   |               `a` is part the function and will be dropped at the end of the function
+LL |     &a
+   |     ^^
+   |
+   = note: pointers do not have a lifetime; after returning, the `&Adt` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
+
+warning: 19 warnings emitted
+