diff --git a/sway-core/src/semantic_analysis/namespace/trait_map.rs b/sway-core/src/semantic_analysis/namespace/trait_map.rs
index c867cfe211a..0fb87dceaa2 100644
--- a/sway-core/src/semantic_analysis/namespace/trait_map.rs
+++ b/sway-core/src/semantic_analysis/namespace/trait_map.rs
@@ -773,7 +773,6 @@ fn are_equal_minus_dynamic_types(type_engine: &TypeEngine, left: TypeId, right:
         (TypeInfo::Unknown, TypeInfo::Unknown) => false,
         (TypeInfo::SelfType, TypeInfo::SelfType) => false,
         (TypeInfo::Numeric, TypeInfo::Numeric) => false,
-        (TypeInfo::UnknownGeneric { .. }, TypeInfo::UnknownGeneric { .. }) => false,
         (TypeInfo::Contract, TypeInfo::Contract) => false,
         (TypeInfo::Storage { .. }, TypeInfo::Storage { .. }) => false,
 
@@ -785,6 +784,11 @@ fn are_equal_minus_dynamic_types(type_engine: &TypeEngine, left: TypeId, right:
         (TypeInfo::UnsignedInteger(l), TypeInfo::UnsignedInteger(r)) => l == r,
         (TypeInfo::RawUntypedPtr, TypeInfo::RawUntypedPtr) => true,
         (TypeInfo::RawUntypedSlice, TypeInfo::RawUntypedSlice) => true,
+        (TypeInfo::UnknownGeneric { .. }, TypeInfo::UnknownGeneric { .. }) => {
+            // return true if left and right were unified previously
+            type_engine.get_unified_types(left).contains(&right)
+                || type_engine.get_unified_types(right).contains(&left)
+        }
 
         // these cases may contain dynamic types
         (
diff --git a/sway-core/src/type_system/type_engine.rs b/sway-core/src/type_system/type_engine.rs
index 9b83c1cd102..1a3b8725511 100644
--- a/sway-core/src/type_system/type_engine.rs
+++ b/sway-core/src/type_system/type_engine.rs
@@ -20,6 +20,7 @@ pub struct TypeEngine {
     pub(super) slab: ConcurrentSlab<TypeInfo>,
     storage_only_types: ConcurrentSlab<TypeInfo>,
     id_map: RwLock<HashMap<TypeInfo, TypeId>>,
+    unify_map: RwLock<HashMap<TypeId, Vec<TypeId>>>,
 }
 
 impl fmt::Display for TypeEngine {
@@ -69,6 +70,40 @@ impl TypeEngine {
         }
     }
 
+    pub(crate) fn insert_unified_type(&self, received: TypeId, expected: TypeId) {
+        let mut unify_map = self.unify_map.write().unwrap();
+        if let Some(type_ids) = unify_map.get(&received) {
+            if type_ids.contains(&expected) {
+                return;
+            }
+            let mut type_ids = type_ids.clone();
+            type_ids.push(expected);
+            unify_map.insert(received, type_ids);
+            return;
+        }
+
+        unify_map.insert(received, vec![expected]);
+    }
+
+    pub(crate) fn get_unified_types(&self, type_id: TypeId) -> Vec<TypeId> {
+        let mut final_unify_ids: Vec<TypeId> = vec![];
+        self.get_unified_types_rec(type_id, &mut final_unify_ids);
+        final_unify_ids
+    }
+
+    fn get_unified_types_rec(&self, type_id: TypeId, final_unify_ids: &mut Vec<TypeId>) {
+        let unify_map = self.unify_map.read().unwrap();
+        if let Some(unify_ids) = unify_map.get(&type_id) {
+            for unify_id in unify_ids {
+                if final_unify_ids.contains(unify_id) {
+                    continue;
+                }
+                final_unify_ids.push(*unify_id);
+                self.get_unified_types_rec(*unify_id, final_unify_ids);
+            }
+        }
+    }
+
     /// Currently the [TypeEngine] is a lazy static object, so when we run
     /// cargo tests, we can either choose to use a local [TypeEngine] and bypass
     /// all of the global methods or we can use the lazy static [TypeEngine].
diff --git a/sway-core/src/type_system/unify.rs b/sway-core/src/type_system/unify.rs
index 2b21d00d6a0..08536497d94 100644
--- a/sway-core/src/type_system/unify.rs
+++ b/sway-core/src/type_system/unify.rs
@@ -236,7 +236,11 @@ pub(super) fn unify(
                 name: en,
                 trait_constraints: etc,
             },
-        ) if rn.as_str() == en.as_str() && rtc.eq(&etc, type_engine) => (vec![], vec![]),
+        ) if rn.as_str() == en.as_str() && rtc.eq(&etc, type_engine) => {
+            type_engine.insert_unified_type(received, expected);
+            type_engine.insert_unified_type(expected, received);
+            (vec![], vec![])
+        }
         (ref r @ UnknownGeneric { .. }, e) => {
             match type_engine.slab.replace(received, r, e, type_engine) {
                 None => (vec![], vec![]),
@@ -444,8 +448,12 @@ pub(super) fn unify_right(
                 name: en,
                 trait_constraints: etc,
             },
-        ) if rn.as_str() == en.as_str() && rtc.eq(&etc, type_engine) => (vec![], vec![]),
+        ) if rn.as_str() == en.as_str() && rtc.eq(&etc, type_engine) => {
+            type_engine.insert_unified_type(received, expected);
+            (vec![], vec![])
+        }
         (r, ref e @ UnknownGeneric { .. }) => {
+            type_engine.insert_unified_type(received, expected);
             match type_engine.slab.replace(expected, e, r, type_engine) {
                 None => (vec![], vec![]),
                 Some(_) => unify_right(type_engine, received, expected, span, help_text),
diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/eq_generic/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/eq_generic/Forc.lock
new file mode 100644
index 00000000000..1375faff5cb
--- /dev/null
+++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/eq_generic/Forc.lock
@@ -0,0 +1,13 @@
+[[package]]
+name = 'core'
+source = 'path+from-root-D8A8CF23B4069FF9'
+
+[[package]]
+name = 'eq_generic'
+source = 'member'
+dependencies = ['std']
+
+[[package]]
+name = 'std'
+source = 'path+from-root-D8A8CF23B4069FF9'
+dependencies = ['core']
diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/eq_generic/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/eq_generic/Forc.toml
new file mode 100644
index 00000000000..179bc98016b
--- /dev/null
+++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/eq_generic/Forc.toml
@@ -0,0 +1,8 @@
+[project]
+authors = ["Fuel Labs <contact@fuel.sh>"]
+entry = "main.sw"
+license = "Apache-2.0"
+name = "eq_generic"
+
+[dependencies]
+std = { path = "../../../../../../../sway-lib-std" }
diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/eq_generic/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/eq_generic/json_abi_oracle.json
new file mode 100644
index 00000000000..542c5d96b7c
--- /dev/null
+++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/eq_generic/json_abi_oracle.json
@@ -0,0 +1,22 @@
+{
+  "functions": [
+    {
+      "inputs": [],
+      "name": "main",
+      "output": {
+        "name": "",
+        "type": 0,
+        "typeArguments": null
+      }
+    }
+  ],
+  "loggedTypes": [],
+  "types": [
+    {
+      "components": [],
+      "type": "()",
+      "typeId": 0,
+      "typeParameters": null
+    }
+  ]
+}
\ No newline at end of file
diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/eq_generic/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/eq_generic/src/main.sw
new file mode 100644
index 00000000000..28278791386
--- /dev/null
+++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/eq_generic/src/main.sw
@@ -0,0 +1,21 @@
+script;
+
+use core::ops::*;
+
+impl<T> Option<T> {
+    pub fn ok_or<E>(self, err: E) -> Result<T, E> {
+        match self {
+            Option::Some(v) => Result::Ok(v),
+            Option::None => Result::Err(err),
+        }
+    }
+}
+
+fn test_ok_or<T, E>(val: T, default: E) where T: Eq {
+    match Option::Some(val).ok_or(default) {
+        Result::Ok(inner) => assert(inner == val),
+        Result::Err(_) => revert(0),
+    };
+}
+
+fn main() {}
diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/eq_generic/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/eq_generic/test.toml
new file mode 100644
index 00000000000..44ca8ea93c4
--- /dev/null
+++ b/test/src/e2e_vm_tests/test_programs/should_pass/stdlib/eq_generic/test.toml
@@ -0,0 +1,3 @@
+category = "run"
+expected_result = { action = "return", value = 0 }
+validate_abi = true