move-language / move

Apache License 2.0
2.26k stars 688 forks source link

[Bug] When reuse mut reference in one liner, it wont pass the compile. #893

Closed ghost closed 1 year ago

ghost commented 1 year ago

🐛 Bug

https://github.com/aptos-labs/aptos-core/blob/86f4b1b6414fd7446567885c1fcf6e4d68c3a788/aptos-move/framework/aptos-framework/sources/coin.move#L893-L894

To reproduce

let demo_struct_mut = &mut borrow_global_mut<DemoStruct<FakeMoney>>(source_addr).coin;

deposit(source_addr, extract(demo_struct_mut, value_mut(demo_struct_mut) / 2));

It should be passed because it resolved be like :

  1. value_mut(demo_struct_mut)
  2. value_mut(demo_struct_mut) / 2
  3. extract(demo_struct_mut, value_mut(demo_struct_mut) / 2)
  4. deposit(source_addr, extract(demo_struct_mut, value_mut(demo_struct_mut) / 2))

at step 1, we got the value, then mut reference is not being used now, at step 3, the mut reference being used now. at step 4, the mut reference is not being used now.

https://github.com/aptos-labs/aptos-core/pull/6578

Code snippet to reproduce

# Your code goes here
# Please make sure it does not require any external dependencies

Stack trace/error message

// Paste the output here

Expected Behavior

System information

Please complete the following information:

Additional context

Add any other context about the problem here.

wrwg commented 1 year ago

Can you please give a full piece of valid Move code to reproduce when you report a bug? Thank you!

ghost commented 1 year ago

Can you please give a full piece of valid Move code to reproduce when you report a bug? Thank you!

I am sorry? That "a full piece of valid Move code" should displayed on our Aptos PR aptos-labs/aptos-core#6578 of test case... https://github.com/aptos-labs/aptos-core/blob/86f4b1b6414fd7446567885c1fcf6e4d68c3a788/aptos-move/framework/aptos-framework/sources/coin.move#L849-L911

    #[test(source = @0x1, alice = @0x2, bob = @0x3, carol = @0x4, dave = @0x5)]
    public entry fun test_extract_with_value_mut(
        source: signer,
        alice: &signer,
        bob: &signer,
        carol: &signer,
        dave: &signer,
    ) acquires CoinInfo, CoinStore, DemoStruct {
        let source_addr = signer::address_of(&source);
        account::create_account_for_test(source_addr);
        let alice_addr = signer::address_of(alice);
        account::create_account_for_test(alice_addr);
        let bob_addr = signer::address_of(bob);
        account::create_account_for_test(bob_addr);
        let carol_addr = signer::address_of(carol);
        account::create_account_for_test(carol_addr);
        let dave_addr = signer::address_of(dave);
        account::create_account_for_test(dave_addr);
        let (burn_cap, freeze_cap, mint_cap) = initialize_and_register_fake_money(&source, 1, true);
        {
            move_to(&source,
                DemoStruct<FakeMoney> {
                    coin: mint<FakeMoney>(2000, &mint_cap),
                }
            );
        };
        register<FakeMoney>(&source);
        register<FakeMoney>(alice);
        register<FakeMoney>(bob);
        register<FakeMoney>(carol);
        register<FakeMoney>(dave);
        let demo_struct_mut = &mut borrow_global_mut<DemoStruct<FakeMoney>>(source_addr).coin;
        {
            deposit(alice_addr, extract(demo_struct_mut, 25));
            assert!(value_mut(demo_struct_mut) == 1975, 0);
            deposit(bob_addr, extract(demo_struct_mut, 25));
            assert!(value_mut(demo_struct_mut) == 1950, 1);
            deposit(carol_addr, extract(demo_struct_mut, 25));
            assert!(value_mut(demo_struct_mut) == 1925, 2);
            deposit(dave_addr, extract(demo_struct_mut, 25));
            assert!(value_mut(demo_struct_mut) == 1900, 3);

        };

        // Invalid usage of reference as function argument. Cannot transfer a mutable reference that is being borrowed
        //deposit(source_addr, extract(demo_struct_mut, value_mut(demo_struct_mut) / 2)); // uncomment it

        let value = value_mut(demo_struct_mut); // comment it
        deposit(source_addr, extract(demo_struct_mut, value / 2)); // comment it

        assert!(balance<FakeMoney>(source_addr) == 950, 4);
        assert!(balance<FakeMoney>(alice_addr) == 25, 5);
        assert!(balance<FakeMoney>(bob_addr) == 25, 6);
        assert!(balance<FakeMoney>(carol_addr) == 25, 7);
        assert!(balance<FakeMoney>(dave_addr) == 25, 8);
        assert!(value_mut(demo_struct_mut) == 950, 9);

        move_to(&source, FakeMoneyCapabilities {
            burn_cap,
            freeze_cap,
            mint_cap,
        });
    }
ghost commented 1 year ago

Can you please give a full piece of valid Move code to reproduce when you report a bug? Thank you!

And check this please. https://github.com/aptos-labs/aptos-core/pull/6578

wrwg commented 1 year ago

When reporting bugs, if possible do not point to some PR. Include a small standalone Move example which reproduces the bug. If this is not possible, elaborate why.

It looks like what you are trying to tell us here is that you aren't happy with Move's borrow semantics. However, it is how it is. The behavior you are seeing is by design. Perhaps try to break down the expression in multiple lets.

ghost commented 1 year ago

When reporting bugs, if possible do not point to some PR. Include a small standalone Move example which reproduces the bug. If this is not possible, elaborate why.

It looks like what you are trying to tell us here is that you aren't happy with Move's borrow semantics. However, it is how it is. The behavior you are seeing is by design. Perhaps try to break down the expression in multiple lets.

if I try to break down the expression and using multiple lets on it, compiler will spawn some not necessary StLoc and MoveLoc instuctions which is not I wants.