'?' Operator has incompatible types

Hey guys. Im writing a contract for secret network in the cosmwasm ecosystem using rust. I have a function


#[allow(clippy::too_many_arguments)]
fn receiver_callback_msgs<S: Storage, A: Api, Q: Querier>(
    deps: &mut Extern<S, A, Q>,
    env: &Env,
    contract_human: &HumanAddr,
    contract: &CanonicalAddr,
    receiver_info: Option<ReceiverInfo>,
    send_from_list: Vec<SendFrom>,
    msg: &Option<Binary>,
    sender: &HumanAddr,
    receivers: &mut Vec<CacheReceiverInfo>,
) -> StdResult<Vec<CosmosMsg>> {
    let (code_hash, impl_batch) = if let Some(supplied) = receiver_info {
        (
            supplied.recipient_code_hash,
            supplied.also_implements_batch_receive_nft.unwrap_or(false),
        )
    } else if let Some(receiver) = receivers.iter().find(|&r| r.contract == *contract) {
        (
            receiver.registration.code_hash.clone(),
            receiver.registration.impl_batch,
        )
    } else {
        let store = ReadonlyPrefixedStorage::new(PREFIX_RECEIVERS, &deps.storage);
        let registration: ReceiveRegistration =
            may_load(&store, contract.as_slice())?.unwrap_or(ReceiveRegistration {
                code_hash: String::new(),
                impl_batch: false,
            });
        let receiver = CacheReceiverInfo {
            contract: contract.clone(),
            registration: registration.clone(),
        };
        receivers.push(receiver);
        (registration.code_hash, registration.impl_batch)
    };
    if code_hash.is_empty() {
        return Ok(Vec::new());
    }
    let mut callbacks: Vec<CosmosMsg> = Vec::new();
    for send_from in send_from_list.into_iter() {
        // if BatchReceiveNft is implemented, use it
        if impl_batch {
            callbacks.push(try_receive(
                &mut deps,
                sender.clone(),
                send_from.owner,
                &send_from.token_ids,
                msg.clone(),
                code_hash.clone(),
               // contract_human.clone(),
            )?);
        }
        }
        Ok(callbacks)
    }

which returns the error:

? operator has incompatible types
--> src/contract.rs:622:28
|
622 | callbacks.push(try_receive(
| ____________________________^
623 | | &mut deps,
624 | | sender.clone(),
625 | | send_from.owner,
... |
629 | | // contract_human.clone(),
630 | | )?);
| |______________^ expected enum CosmosMsg, found struct HandleResponse
|
= note: ? operator cannot convert from HandleResponse to CosmosMsg
= note: expected enum CosmosMsg
found struct HandleResponse

I am new to rust so need some help in resolving this

When you use the ? operator, it must be applied to the error type that your function returns, or something that can be converted into that error type via From. That must not be the case in your code.

What is StdResult defined as, and also, what does try_receive() return?

Hey :slight_smile:

? operator works only if the function it is applied to returns a Result<T> enum holding an underlying type T.

At the end of a function call, ? operator is a shortcut for "unwrap value if successful, else do return Error(From::from(err))" as explained here.

In your case, try_receive()? tries to unwrap a Result of type HandleResponse (Result<HandleResponse>) and put it in an Vec of type CosmosMsg (Vec<CosmosMsg>).

You might fix this error by editing try_receive() to return a CosmosMsg, or handle try_receive()? returned value in a variable, or a match for example.

Not just Result. ? also works with Option<_> most notably.