iroha icon indicating copy to clipboard operation
iroha copied to clipboard

Static type checking of `EvaluatesTo` not working

Open mversic opened this issue 3 years ago • 1 comments

I've noticed that our type checking of EvaluatesTo is not giving out compile errors when it is expected to do so.

The following test should not compile, yet it does:

#[test]
fn genesis_block_is_commited_with_some_offline_peers() {
    // Given
    let rt = Runtime::test();
    let (network, mut iroha_client) = rt.block_on(<Network>::start_test_with_offline(4, 1, 1));
    wait_for_genesis_committed(&network.clients(), 1);

    //When
    // NOTE: I have used `AssetDefinitionId` instead of `AccountId` for demonstration purpose
    let alice_id: AssetDefinitionId = "alice#wonderland".parse().expect("Valid");					
    let alice_has_roses = 13;

    //Then
    let assets = iroha_client
        // NOTE: This should not compile because `client::asset::by_account_id`
        // should only accept expressions that evaluate to `AccountId`!
        .request(client::asset::by_account_id(alice_id))
        .expect("Failed to execute request.");
    let asset = assets
        .iter()
        .find(|asset| asset.id().definition_id == "rose#wonderland".parse().expect("Valid"))
        .unwrap();
    assert_eq!(AssetValue::Quantity(alice_has_roses), *asset.value());
}

Notice that client::asset::by_account_id as it's argument accepts impl Into<EvaluatesTo<AccountId>>, yet when given AssetDefinitionId it still compiles as if there is an implementation AssetDefinitionId: Into<AccountId>.

mversic avatar Mar 23 '22 16:03 mversic

@appetrosyan, @mversic if we look at:

impl<V: TryFrom<Value>, E: Into<ExpressionBox>> From<E> for EvaluatesTo<V> {
    fn from(expression: E) -> Self {
        Self {
            expression: expression.into(),
            _value_type: PhantomData::default(),
        }
    }
}

Nothing prevent us from having:

impl From<AssetDefinitionId> for EvaluatesTo<AccountId> {
    fn from(expression: AssetDefinitionId) -> Self {
        Self {
            // AssetDefinitionId into ExpressionBox
            expression: expression.into(),
            _value_type: PhantomData::default(),
        }
    }
}

impl From<AccountId> for EvaluatesTo<AccountId> {
    fn from(expression: AccountId) -> Self {
        Self {
           // AccountId into ExpressionBox
            expression: expression.into(),
            _value_type: PhantomData::default(),
        }
    }
}

EDIT: so the problem is that when we require type value: impl Into<EvaluatesTo<V>, we really only require value: impl Into<ExpressionBox>.

Erigara avatar Jun 09 '22 10:06 Erigara