Repository: aptos-labs/aptos-core (language: python)

Issue:
[Bug][Compiler-v2] index notation does not check ability properly
# 🐛 Bug

When compiling the following code, 

```
    struct Wrapper<T: copy> has drop, key, store, copy {
        inner: T
    }

    fun unwrap<T: copy>(self: &Wrapper<T>): T {
        self.inner
    }

    fun dispatch<T: copy>(account: address): T acquires Wrapper {
        unwrap(&Wrapper<T>[account])
    }
```

The following bytecode verification error is generated:

```
 bug: bytecode verification failed with unexpected status code `CONSTRAINT_NOT_SATISFIED`. This is a compiler bug, consider reporting it.
Error message: missing abilities for `ImmBorrowGlobalGeneric(StructDefInstantiationIndex(0))` at code offset 1
```

If we change `unwrap(&Wrapper<T>[account])` into `unwrap(borrow_global<Wrapper<T>>)`, the following error is generated:

```
 error: type `T` is missing required ability `store`
    ┌─ TEMPFILE:298:23
    │
298 │         borrow_global<Wrapper<T>>(account).unwrap()
    │                       ^^^^^^^^^^
    │
```






Discussion / hints:

Fix patch:
diff --git a/third_party/move/move-model/src/builder/exp_builder.rs b/third_party/move/move-model/src/builder/exp_builder.rs
index 9b6427c19a260..992dbb07cf603 100644
--- a/third_party/move/move-model/src/builder/exp_builder.rs
+++ b/third_party/move/move-model/src/builder/exp_builder.rs
@@ -3645,32 +3645,21 @@ impl<'env, 'translator, 'module_translator> ExpTranslator<'env, 'translator, 'mo
         }
         let type_opt = convert_name_to_type(&resource_ty_exp.loc, resource_ty_exp.clone().value);
         if let Some(ty) = type_opt {
-            let resource_ty = self.translate_type(&ty);
-            let ref_t = Type::Reference(
-                ReferenceKind::from_is_mut(mutable),
-                Box::new(resource_ty.clone()),
-            );
-            let ty = self.check_type(loc, &ref_t, expected_type, context);
-            if ty.is_error() {
-                return self.new_error_exp();
-            }
-            let addr = self.translate_exp_in_context(
-                addr_exp,
-                &Type::Primitive(PrimitiveType::Address),
-                context,
-            );
-            let node = self.new_node_id_with_type_loc(
-                &Type::Reference(
-                    ReferenceKind::from_is_mut(mutable),
-                    Box::new(resource_ty.clone()),
-                ),
+            let name = if mutable {
+                self.symbol_pool().make("borrow_global_mut")
+            } else {
+                self.symbol_pool().make("borrow_global")
+            };
+            self.translate_call(
                 loc,
-            );
-            self.set_node_instantiation(node, vec![resource_ty.clone()]);
-            ExpData::Call(
-                node,
-                Operation::BorrowGlobal(ReferenceKind::from_is_mut(mutable)),
-                vec![addr.into()],
+                &self.to_loc(&resource_ty_exp.loc),
+                CallKind::Regular,
+                &Some(self.parent.parent.builtin_module()),
+                name,
+                &Some(vec![ty]),
+                &[addr_exp],
+                expected_type,
+                context,
             )
         } else {
             self.new_error_exp()


Test patch:
diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/bug_15274.exp b/third_party/move/move-compiler-v2/tests/checking/typing/bug_15274.exp
new file mode 100644
index 0000000000000..94258b243caa8
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/typing/bug_15274.exp
@@ -0,0 +1,41 @@
+
+Diagnostics:
+error: type `T` is missing required ability `store`
+   ┌─ tests/checking/typing/bug_15274.move:16:30
+   │
+16 │         unwrap_non_receiver(&Wrapper<T>[account])
+   │                              ^^^^^^^^^^
+   │
+   = required by instantiating type parameter `T:copy` of struct `Wrapper`
+   = required by instantiating type parameter `T:key` of function `borrow_global`
+
+error: type `T` is missing required ability `store`
+   ┌─ tests/checking/typing/bug_15274.move:20:9
+   │
+20 │         Wrapper<T>[account].unwrap()
+   │         ^^^^^^^^^^
+   │
+   = required by instantiating type parameter `T:copy` of struct `Wrapper`
+   = required by instantiating type parameter `T:key` of function `borrow_global`
+
+error: type `T` is missing required ability `copy`
+   ┌─ tests/checking/typing/bug_15274.move:23:39
+   │
+ 3 │     struct Wrapper<T: copy> has drop, key, store, copy {
+   │                    - declaration of type parameter `T`
+   ·
+23 │     fun test_vec<T>(v: vector<Wrapper<T>>): T {
+   │                                       ^
+   │
+   = required by instantiating type parameter `T:copy` of struct `Wrapper`
+
+error: type `T` is missing required ability `copy`
+   ┌─ tests/checking/typing/bug_15274.move:24:9
+   │
+ 7 │     fun unwrap<T: copy>(self: &Wrapper<T>): T {
+   │                - declaration of type parameter `T`
+   ·
+24 │         v[0].unwrap()
+   │         ^^^^^^^^^^^^^
+   │
+   = required by instantiating type parameter `T:copy` of function `unwrap`
diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/bug_15274.move b/third_party/move/move-compiler-v2/tests/checking/typing/bug_15274.move
new file mode 100644
index 0000000000000..e6c1b15356312
--- /dev/null
+++ b/third_party/move/move-compiler-v2/tests/checking/typing/bug_15274.move
@@ -0,0 +1,27 @@
+module 0x42::test {
+
+    struct Wrapper<T: copy> has drop, key, store, copy {
+        inner: T
+    }
+
+    fun unwrap<T: copy>(self: &Wrapper<T>): T {
+        self.inner
+    }
+
+    fun unwrap_non_receiver<T: copy>(self1: &Wrapper<T>): T {
+        self1.inner
+    }
+
+    fun dispatch_non_receiver<T: copy>(account: address): T acquires Wrapper {
+        unwrap_non_receiver(&Wrapper<T>[account])
+    }
+
+    fun dispatch<T: copy>(account: address): T acquires Wrapper {
+        Wrapper<T>[account].unwrap()
+    }
+
+    fun test_vec<T>(v: vector<Wrapper<T>>): T {
+        v[0].unwrap()
+    }
+
+}