FuelLabs / sway

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

Generic argument name can spawn errors #6624

Open IGI-111 opened 6 days ago

IGI-111 commented 6 days ago

The following does not compile:

script;

struct StructB<T> { propB: StructC<Vec<T>> }
struct StructC<T> { propC: T }

fn main(a: StructB<u8>) -> StructB<u8> {
    a
}

However changing StructC<T> to StructC<T2> indeed compiles.

There are similar errors we have found over time such as in the following examples, but the cause of this remains mysterious.

script;

struct StructB<T> { propB: StructC<Vec<T>> }
struct StructC<T> { propC: T }

trait Log {
    fn log(self);
}

impl<T> Log for Vec<T> {
    fn log(self) {
    }
}

impl<T> Log for StructB<T> {
    fn log(self) {
        self.propB.log();
    }
}

impl<T> Log for StructC<T> where T: Log {
    fn log(self) {
        self.propC.log();
    }
}

fn main() {
}
contract;

struct StructA {
    propA: StructB<u8>,
}

struct StructB<T1> {
    propB: StructC<Vec<T1>>,
}

struct StructC<T1> {
    propC: T1,
}

abi MyContract {
    fn entry(z: StructA) -> bool;
}

impl MyContract for Contract {
    fn entry(z: StructA) -> bool {
        true
    }
}
Namanedogawa commented 6 days ago

I noticed some compilation issues in the following code snippets:

Struct Definitions: The first snippet fails to compile due to conflicting type parameters in StructC. Changing StructC to StructC resolves the issue, allowing the code to compile correctly.

Trait Implementations: In the second example, the trait implementations for Log may also fail due to the nested type parameters not being resolved correctly. Ensuring that all type parameters are independent can help avoid these issues.

Suggested Code Changes: Here’s a proposed modification that should resolve the compilation issues:

struct StructB<T> { propB: StructC<Vec<T>> }
struct StructC<T> { propC: T }

trait Log {
    fn log(self);
}

impl<T> Log for Vec<T> {
    fn log(self) {}
}

impl<T> Log for StructB<T> {
    fn log(self) {
        self.propB.log();
    }
}

impl<T> Log for StructC<T> where T: Log {
    fn log(self) {
        self.propC.log();
    }
}

fn main() {
    // Пример использования
    let example = StructB { propB: StructC { propC: vec![1u8] } };
    example.log();
}

This change ensures that all type parameters are appropriately resolved, leading to successful compilation. I hope this helps!