FuelLabs / sway

🌴 Empowering everyone to build reliable and efficient smart contracts.
https://docs.fuel.network/docs/sway/
Apache License 2.0
62.58k stars 5.37k forks source link

Trait: "method dummy and was not properly replaced" error in 0.63.6 #6572

Closed Lukasz2891 closed 2 weeks ago

Lukasz2891 commented 1 month ago

Related Component

compiler

Problem

Let have a library (named redstone) with the lib file:

lib.sw

library;

use std::{bytes::Bytes};

pub trait FromBytesConvertible {
    fn size() -> u64;
    fn _from_be_bytes(bytes: Bytes) -> Self;
}

pub trait FromBytes {
    fn from_bytes(bytes: Bytes) -> Self;
}

impl<T> FromBytes for T
where
    T: FromBytesConvertible,
{
    fn from_bytes(bytes: Bytes) -> Self {
        assert(bytes.len() <= Self::size());

        let mut bytes = bytes;

        while (bytes.len() < Self::size()) {
            bytes.insert(0, 0u8);
        }

        Self::_from_be_bytes(bytes)
    }
}

pub struct DataPoint {}
pub struct DataPackage {}
pub struct Payload {}

pub fn make_data_package(bytes: Bytes) -> (DataPackage, u64) {
    let mut data_points = Vec::new();
    data_points.push(DataPoint::from_bytes(bytes));

    return (DataPackage {}, 0);
}

impl FromBytes for DataPoint {
    fn from_bytes(bytes: Bytes) -> Self {
        Self {
        }
    }
}

impl Payload {
    pub fn from_bytes(bytes: Bytes) -> Self {
        let mut data_packages = Vec::new();
        let (data_package, _) = make_data_package(bytes);
        data_packages.push(data_package);

        Self {}
    }
}

pub fn process_input(bytes: Bytes) -> (Vec<u256>, u64) {
    let payload = Payload::from_bytes(bytes);

    (Vec::new(), 0)
}

and the contract:

contract;

use std::{
    bytes::Bytes,
    vec::Vec,
};
use redstone::process_input;

abi RedStoneCore {
    fn get_prices(feed_ids: Vec<u256>, payload: Bytes) -> (Vec<u256>, u64);
}

impl RedStoneCore for Contract {
    fn get_prices(feed_ids: Vec<u256>, payload_bytes: Bytes) -> (Vec<u256>, u64) {
        process_input(payload_bytes)
    }
}

The library compiles properly, but the contract using the library does not. It leads to an error:

error
 --> /[Redacted]/redstone-fuel-sdk/src/lib.sw:7:8
  |
5 | 
6 |     fn size() -> u64;
7 |     fn _from_be_bytes(bytes: Bytes) -> Self;
  |        ^^^^^^^^^^^^^^ Internal compiler error: Method _from_be_bytes_70 is a trait method dummy and was not properly replaced.
Please file an issue on the repository and include the code that triggered this error.
8 | }

The code compiles in 0.63.1. It doesn't compile in 0.63.2 due to https://github.com/FuelLabs/sway/issues/6491.

Steps

As above

Possible Solution(s)

Didn't find.

Notes

The repo with the issue:

https://github.com/redstone-finance/fuel-test-contract/tree/0.63.6

use

make build

Installed components

active toolchain
----------------
nightly-aarch64-apple-darwin (default)
  forc : 0.63.6+nightly.20240919.10a78a7624
    - forc-client
      - forc-deploy : 0.63.6+nightly.20240919.10a78a7624
      - forc-run : 0.63.6+nightly.20240919.10a78a7624
    - forc-crypto : 0.63.6+nightly.20240919.10a78a7624
    - forc-debug : 0.63.6+nightly.20240919.10a78a7624
    - forc-doc : 0.63.6+nightly.20240919.10a78a7624
    - forc-fmt : 0.63.6+nightly.20240919.10a78a7624
    - forc-lsp : 0.63.6+nightly.20240919.10a78a7624
    - forc-tx : 0.63.6+nightly.20240919.10a78a7624
    - forc-wallet : 0.9.0+nightly.20240919.29d9b25c2c
  fuel-core : 0.36.0+nightly.20240919.408c468098
  fuel-core-keygen : not found
IGI-111 commented 1 month ago

This looks like a failure of type checking as this is not a valid call.

    data_points.push(DataPoint::from_bytes(bytes));

Changing that line to this produces the correct error:

    let points = DataPoint::from_bytes(bytes);
    data_points.push(points);
error
  --> /home/igi-111/Code/test_sway/src/main.sw:32:13
   |
30 | pub fn make_data_package(bytes: Bytes) -> (DataPackage, u64) {
31 |     let mut data_points = Vec::new();
32 |     let a = DataPoint::from_bytes(bytes);
   |             ^^^^^^^^^^^^^^^^^^^^^ Trait "FromBytesConvertible" is not implemented for type "DataPoint".
33 |     data_points.push(a);
34 |
   |
____

Evidently, call parameters expressions are not properly checked for type constraints here.

IGI-111 commented 1 month ago

Here's a minimal example that reproduces the error:

script;

use std::{
    bytes::Bytes,
    vec::Vec,
};

pub trait FromBytesConvertible {
    fn _from_be_bytes(bytes: Bytes) -> Self;
}

pub trait FromBytes {
    fn from_bytes(bytes: Bytes) -> Self;
}

impl<T> FromBytes for T
where
    T: FromBytesConvertible,
{
    fn from_bytes(bytes: Bytes) -> Self {
        Self::_from_be_bytes(bytes)
    }
}

pub struct DataPoint {}
pub struct Payload {}

impl FromBytes for DataPoint {
    fn from_bytes(bytes: Bytes) -> Self {
        Self {}
    }
}

impl Payload {
    pub fn from_bytes(bytes: Bytes) {
        let mut data_points = Vec::new();

        data_points.push(DataPoint::from_bytes(bytes));

        // let a = DataPoint::from_bytes(bytes);
        // data_points.push(a);
    }
}

pub fn main() {
    Payload::from_bytes(Bytes::new());
}