diff --git a/dev/Cargo.toml b/dev/Cargo.toml
index ae380d17..f5b701a9 100644
--- a/dev/Cargo.toml
+++ b/dev/Cargo.toml
@@ -116,6 +116,8 @@ bin = [
   { name = "generics1_sol", path = "../solutions/14_generics/generics1.rs" },
   { name = "generics2", path = "../exercises/14_generics/generics2.rs" },
   { name = "generics2_sol", path = "../solutions/14_generics/generics2.rs" },
+  { name = "generics3", path = "../exercises/14_generics/generics3.rs" },
+  { name = "generics3_sol", path = "../solutions/14_generics/generics3.rs" },
   { name = "traits1", path = "../exercises/15_traits/traits1.rs" },
   { name = "traits1_sol", path = "../solutions/15_traits/traits1.rs" },
   { name = "traits2", path = "../exercises/15_traits/traits2.rs" },
diff --git a/exercises/14_generics/generics3.rs b/exercises/14_generics/generics3.rs
new file mode 100644
index 00000000..a60b396a
--- /dev/null
+++ b/exercises/14_generics/generics3.rs
@@ -0,0 +1,54 @@
+// generics3.rs
+// Execute `rustlings hint generics3` or use the `hint` watch subcommand for a hint.
+
+// This function should take an array of `Option` elements and returns array of not None elements
+// TODO fix this function signature
+fn into_dispose_nulls(list: Vec<Option<&str>>) -> Vec<&str> {
+    list.into_iter().flatten().collect()
+}
+
+fn main() {
+    // You can optionally experiment here.
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn store_str_on_list() {
+        let names_list = vec![Some("maria"), Some("jacob"), None, Some("kacper"), None];
+        let only_values = into_dispose_nulls(names_list);
+        assert_eq!(only_values.len(), 3);
+    }
+
+    #[test]
+    fn store_numbers_on_list() {
+        let numbers_list = vec![Some(1), Some(2), None, Some(3)];
+        let only_values = into_dispose_nulls(numbers_list);
+        assert_eq!(only_values.len(), 3);
+    }
+
+    #[test]
+    fn store_custom_type_on_list() {
+        #[allow(dead_code)]
+        struct Rectangle {
+            width: i32,
+            height: i32,
+        }
+        impl Rectangle {
+            fn new(width: i32, height: i32) -> Self {
+                Self { width, height }
+            }
+        }
+
+        let custom_list = vec![
+            Some(Rectangle::new(1, 2)),
+            None,
+            None,
+            Some(Rectangle::new(3, 4)),
+        ];
+        let only_values = into_dispose_nulls(custom_list);
+        assert_eq!(only_values.len(), 2);
+    }
+}
diff --git a/rustlings-macros/info.toml b/rustlings-macros/info.toml
index e7055981..b2970a6f 100644
--- a/rustlings-macros/info.toml
+++ b/rustlings-macros/info.toml
@@ -745,6 +745,17 @@ hint = """
 Related section in The Book:
 https://doc.rust-lang.org/book/ch10-01-syntax.html#in-method-definitions"""
 
+[[exercises]]
+name = "generics3"
+dir = "14_generics"
+hint = """
+Vectors in Rust use generics to create dynamically-sized arrays of any type.
+The `into_dispose_nulls` function takes a vector as an argument, but only accepts vectors that store the &str type.
+To allow the function to accept vectors that store any type, you can leverage your knowledge about generics.
+If you're unsure how to proceed, please refer to the Rust Book at:
+https://doc.rust-lang.org/book/ch10-01-syntax.html#in-function-definitions.
+"""
+
 # TRAITS
 
 [[exercises]]
diff --git a/solutions/14_generics/generics3.rs b/solutions/14_generics/generics3.rs
new file mode 100644
index 00000000..8c137ec1
--- /dev/null
+++ b/solutions/14_generics/generics3.rs
@@ -0,0 +1,53 @@
+// generics3.rs
+// Execute `rustlings hint generics3` or use the `hint` watch subcommand for a hint.
+
+// Here we added generic type `T` to function signature
+// Now this function can be used with vector of any
+fn into_dispose_nulls<T>(list: Vec<Option<T>>) -> Vec<T> {
+    list.into_iter().flatten().collect()
+}
+
+fn main() {
+    // You can optionally experiment here.
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn store_str_on_list() {
+        let names_list = vec![Some("maria"), Some("jacob"), None, Some("kacper"), None];
+        let only_values = into_dispose_nulls(names_list);
+        assert_eq!(only_values.len(), 3);
+    }
+
+    #[test]
+    fn store_numbers_on_list() {
+        let numbers_list = vec![Some(1), Some(2), None, Some(3)];
+        let only_values = into_dispose_nulls(numbers_list);
+        assert_eq!(only_values.len(), 3);
+    }
+
+    #[test]
+    fn store_custom_type_on_list() {
+        struct Rectangle {
+            width: i32,
+            height: i32,
+        }
+        impl Rectangle {
+            fn new(width: i32, height: i32) -> Self {
+                Self { width, height }
+            }
+        }
+
+        let custom_list = vec![
+            Some(Rectangle::new(1, 2)),
+            None,
+            None,
+            Some(Rectangle::new(3, 4)),
+        ];
+        let only_values = into_dispose_nulls(custom_list);
+        assert_eq!(only_values.len(), 2);
+    }
+}