Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] Type mismatch when awaiting Future from tuple #28312

Open
chirswomack opened this issue Aug 8, 2024 · 5 comments · Fixed by #28316
Open

[Bug] Type mismatch when awaiting Future from tuple #28312

chirswomack opened this issue Aug 8, 2024 · 5 comments · Fixed by #28316
Assignees
Labels
bug Something isn't working

Comments

@chirswomack
Copy link

🐛 Bug Report

When calling a function that returns a Future as part of a tuple (e.g. transfer_public_to_private) the compiler fails

Steps to Reproduce

Code snippet to reproduce

let transfer_output: (credits.aleo/credits, Future) = credits.aleo/transfer_public_to_private(input_token.owner, amount);
let future: Future = transfer_output.1;

Stack trace & error message

Error [ETYC0372003]: Expected type `Future<Fn()>` but type `Future<Fn()>` was found

Expected Behavior

The compiler should recognize the Future as the correct type

Your Environment

  • leo 2.1.0
  • rustc 1.76.0
  • macOS 14.5
@chirswomack chirswomack added the bug Something isn't working label Aug 8, 2024
@d0cd
Copy link
Collaborator

d0cd commented Aug 8, 2024

Adding another example.

import credits.aleo;

program test_credits.aleo {
    async transition send_credits(input: credits.aleo/credits, amount: u64) -> (credits.aleo/credits, Future) {
        let result: (credits.aleo/credits, Future) = credits.aleo/transfer_private_to_public(input, self.address, amount);
        return (result.0, finish(result.1));
    }

    async function finish(f: Future) {
        f.await();
    }
}

@chirswomack
Copy link
Author

I'm running into a slightly different issue now. If two different Futures are included in tuples, it duplicates one of them.

Given this program:

import credits.aleo;
import multi_token_support_program.aleo;

program mtsp_credits.aleo {
  async transition deposit_credits_private(
    input_record: credits.aleo/credits,
    amount: u64
  ) -> (credits.aleo/credits, multi_token_support_program.aleo/Token, Future) {
    let transfer_output: (credits.aleo/credits, Future) = credits.aleo/transfer_private_to_public(input_record, self.address, amount);
    let mint_output: (multi_token_support_program.aleo/Token, Future) = multi_token_support_program.aleo/mint_private(
      CREDITS_RESERVED_TOKEN_ID,
      self.address,
      amount as u128,
      false,
      4294967295u32
    );
    return (transfer_output.0, mint_output.0, finalize_deposit_credits_private(transfer_output.1, mint_output.1));
  }

  async function finalize_deposit_credits_private(f0: Future, f1: Future) {
    f0.await();
    f1.await();
  }
}

With the fix on the mainnet branch, the compiler outputs

function deposit_credits_private:
    input r0 as credits.aleo/credits.record;
    input r1 as u64.private;
    call credits.aleo/transfer_private_to_public r0 mtsp_credits.aleo r1 into r2 r3;
    cast r1 into r4 as u128;
    call multi_token_support_program.aleo/mint_private 3443843282313283355522573239085696902919850365217539366784739393210722344986field mtsp_credits.aleo r4 false 4294967295u32 into r5 r6;
    async deposit_credits_private r3 r6 into r7;
    output r2 as credits.aleo/credits.record;
    output r5 as multi_token_support_program.aleo/Token.record;
    output r7 as mtsp_credits.aleo/deposit_credits_private.future;

finalize deposit_credits_private:
    input r0 as multi_token_support_program.aleo/mint_private.future;
    input r1 as multi_token_support_program.aleo/mint_private.future;
    await r0;
    await r1;

where I would expect the finalize to be

finalize deposit_credits_private:
    input r0 as credits.aleo/transfer_private_to_public.future;
    input r1 as multi_token_support_program.aleo/mint_private.future;
    await r0;
    await r1;

@d0cd d0cd reopened this Aug 14, 2024
@akalmykov
Copy link

@d0cd I can confirm this problem. We independently tried a similar patch and this has broken type inference exactly as Chris has reported. So at the moment we have to manually patch our compiled code. Are there any ETAs for a fix?

@evan-schott evan-schott removed their assignment Aug 27, 2024
@d0cd
Copy link
Collaborator

d0cd commented Sep 4, 2024

@akalmykov the team is working on a fix, however, you can get around this issue by destructuring your tuple
let (a, b): (credits.aleo/credits, Future) = ...

@d0cd
Copy link
Collaborator

d0cd commented Dec 4, 2024

Attaching a test case

/*
namespace = "Compile"
expectation = "Pass"
*/
program credits.aleo {
    record credits {
        owner: address,
        amount: u64,
    }

    async transition transfer_private_to_public(input: credits, addr: address, amount:u64) -> (credits, Future) {
        let f: Future = finalize();
        return (input, f);
    }

    async function finalize() {
        assert_eq(1u8, 1u8);
    }
}

// --- Next Program --- //

program multi_token_support_program.aleo {
    record Token {
        owner: address,
        amount: u64,
    }

    async transition mint_private() -> (Token, Future) {
        let f: Future = finalize();
        return (Token{owner: self.caller, amount: 100u64}, f);
    }

    async function finalize() {
        assert_eq(1u8, 1u8);
    }
}

// --- Next Program --- //

import credits.aleo;
import multi_token_support_program.aleo;

program mtsp_credits.aleo {
  async transition deposit_credits_private(
    input_record: credits.aleo/credits,
    amount: u64
  ) -> (credits.aleo/credits, multi_token_support_program.aleo/Token, Future) {
    let transfer_output: (credits.aleo/credits, Future) = credits.aleo/transfer_private_to_public(input_record, self.address, amount);
    let mint_output: (multi_token_support_program.aleo/Token, Future) = multi_token_support_program.aleo/mint_private();
    return (transfer_output.0, mint_output.0, finalize_deposit(transfer_output.1, mint_output.1));
  }

  async function finalize_deposit(f0: Future, f1: Future) {
    f0.await();
    f1.await();
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants