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

UDTs used inside Options are not convertible to ScVal/Sc* #1385

Open
leighmcculloch opened this issue Oct 25, 2024 · 2 comments
Open

UDTs used inside Options are not convertible to ScVal/Sc* #1385

leighmcculloch opened this issue Oct 25, 2024 · 2 comments
Labels
bug Something isn't working

Comments

@leighmcculloch
Copy link
Member

What version are you using?

21.7.6
22.0.0-rc.3

What did you do?

#![no_std]
use soroban_sdk::contracttype;

#[contracttype]
#[derive(Clone)]
pub struct Struct1(pub ());

#[contracttype]
#[derive(Clone, Debug, PartialEq)]
pub enum Enum1 {
    V0(Option<Struct1>),
}

#[contracttype]
pub struct Struct2(pub Option<Struct1>);

What did you expect to see?

Build success when building for tests.

What did you see instead?

❯ cargo test
error[E0277]: the trait bound `soroban_sdk::xdr::ScVec: TryFrom<(soroban_sdk::xdr::ScSymbol, &core::option::Option<Struct1>)>` is not satisfied
 --> contracts/hello_world/src/lib.rs:8:1
  |
8 | #[contracttype]
  | ^^^^^^^^^^^^^^^ the trait `TryFrom<(soroban_sdk::xdr::ScSymbol, &core::option::Option<Struct1>)>` is not implemented for `soroban_sdk::xdr::ScVec`, which is required by `(soroban_sdk::xdr::ScSymbol, &core::option::Option<Struct1>): TryInto<_>`
  |
  = help: the following other types implement trait `TryFrom<T>`:
            `soroban_sdk::xdr::ScVec` implements `TryFrom<&(T0, T1)>`
            `soroban_sdk::xdr::ScVec` implements `TryFrom<&(T0, T1, T2)>`
            `soroban_sdk::xdr::ScVec` implements `TryFrom<&(T0, T1, T2, T3)>`
            `soroban_sdk::xdr::ScVec` implements `TryFrom<&(T0, T1, T2, T3, T4)>`
            `soroban_sdk::xdr::ScVec` implements `TryFrom<&(T0, T1, T2, T3, T4, T5)>`
            `soroban_sdk::xdr::ScVec` implements `TryFrom<&(T0, T1, T2, T3, T4, T5, T6)>`
            `soroban_sdk::xdr::ScVec` implements `TryFrom<&(T0, T1, T2, T3, T4, T5, T6, T7)>`
            `soroban_sdk::xdr::ScVec` implements `TryFrom<&(T0, T1, T2, T3, T4, T5, T6, T7, T8)>`
          and 32 others
  = note: required for `(soroban_sdk::xdr::ScSymbol, &core::option::Option<Struct1>)` to implement `TryInto<soroban_sdk::xdr::ScVec>`
  = note: this error originates in the attribute macro `contracttype` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `soroban_sdk::xdr::ScVal: TryFrom<&core::option::Option<Struct1>>` is not satisfied
  --> contracts/hello_world/src/lib.rs:14:1
   |
14 | #[contracttype]
   | ^^^^^^^^^^^^^^^ the trait `From<Struct1>` is not implemented for `soroban_sdk::xdr::ScVal`, which is required by `&core::option::Option<Struct1>: TryInto<_>`
   |
   = help: the following other types implement trait `From<T>`:
             `&'a soroban_sdk::xdr::ScVal` implements `From<soroban_env_common::object::ScValObjRef<'a>>`
             `soroban_sdk::xdr::ScVal` implements `From<&()>`
             `soroban_sdk::xdr::ScVal` implements `From<&bool>`
             `soroban_sdk::xdr::ScVal` implements `From<&core::option::Option<T>>`
             `soroban_sdk::xdr::ScVal` implements `From<&i128>`
             `soroban_sdk::xdr::ScVal` implements `From<&i32>`
             `soroban_sdk::xdr::ScVal` implements `From<&i64>`
             `soroban_sdk::xdr::ScVal` implements `From<&soroban_sdk::Address>`
           and 36 others
   = note: required for `Struct1` to implement `Into<soroban_sdk::xdr::ScVal>`
   = note: required for `soroban_sdk::xdr::ScVal` to implement `From<&core::option::Option<Struct1>>`
   = note: 1 redundant requirement hidden
   = note: required for `&core::option::Option<Struct1>` to implement `Into<soroban_sdk::xdr::ScVal>`
   = note: required for `soroban_sdk::xdr::ScVal` to implement `TryFrom<&core::option::Option<Struct1>>`
   = note: required for `&core::option::Option<Struct1>` to implement `TryInto<soroban_sdk::xdr::ScVal>`
   = note: this error originates in the attribute macro `contracttype` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0277`.
error: could not compile `hello-world` (lib test) due to 2 previous errors
✘ exit status 101                                                                                                  

cc @kalepail

@leighmcculloch leighmcculloch added the bug Something isn't working label Oct 25, 2024
@leighmcculloch
Copy link
Member Author

leighmcculloch commented Oct 25, 2024

I believe the issue is that when we build for tests we also code generate implementations for converting types from a variety of Sc* XDR types like ScVal and ScVec. Those conversion are only implemented for conversion from borrows, e.g. &ScVal, not from owned types, e.g. ScVal.

I don't remember why the conversions are limited to borrows, we could potentially go and add in conversions without the borrows too.

Another way to fix this may be to alter the generated code to appropriately "as_ref" each value, which would result in a the Option<ScVal> being used as a Option<&ScVal>. This solution would be preferred because very likely the reason we are borrowing is to not deconstruct the type, so even if we filled in the other above, it probably wouldn't be sufficient.

@leighmcculloch
Copy link
Member Author

leighmcculloch commented Oct 25, 2024

I took a look to see if there was a quick fix here. The as_ref idea won’t work because not all types support it. I tried adding support for impl From<Option<T>> for ScVal where &Tis convertible, instead of the existing whereT` is convertible, but ended up with recursion issues. This requires a more significant time investment to solve.

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

No branches or pull requests

1 participant