Tymon
Tymon

Reputation: 13

Mismatched types with modules

I am making small program for validating and computing IPs. I wanted to try out modules and I encountered an error I do not know how to solve and can't find anything on the internet.

Here is my project structure:

src/
    ip.rs
    main.rs
    mask.rs
    show.rs   

ip.rs

pub struct Ip {
    pub first: u8,
    pub second: u8,
    pub third: u8,
    pub forth: u8,

    pub bin: [bool; 32]
}



pub fn build_ip(ip: String) -> Ip {
    let split = ip.replace(".", ":");
    let split = split.split(":");
    let split_vec = split.collect::<Vec<&str>>();
    let mut bin: [bool; 32] = [false; 32];
    let mut octets: [u8; 4] = [0; 4];

    if split_vec.len() != 4 {
        panic!("Wrong amount of octets!");
    }
    for i in 0..4 {
        let octet: u8 = match split_vec[i].trim().parse() {
            Ok(num) => num,
            Err(_) => panic!("Something wrong with first octet"),
        };
        octets[i] = octet;

        let soctet = format!("{:b}", octet);
        for (j, c) in soctet.chars().enumerate() {
            bin[j + i*8] = c == '1';
        }
    }


    Ip {
        first: octets[0],
        second: octets[1],
        third: octets[2],
        forth: octets[3], 
        bin: bin
    }
}

show.rs

#[path = "ip.rs"] mod ip;
#[path = "mask.rs"] mod mask;

pub use ip::Ip;


pub fn print(name: String, ip: ip::Ip) {
    println!("{}: ", name);
    println!("{}.{}.{}.{}", ip.first, ip.second, ip.third, ip.forth);
    for c in ip.bin.iter() {
        print!("{}", *c as i32);
    }
    println!("");
    println!("");
}

main.rs

pub mod mask;
pub mod ip;
pub mod show;

fn main() {
    let ip = ip::build_ip("255:255:25:8:0".to_string());
    // let mask = mask::build_mask("255.255.255.252".to_string());
    show::print("ip".to_string(), ip)
}

When I try to compile it throws this at me and I have no idea what to do:

 --> src\main.rs:9:32
  |
9 |     show::print("ip".to_string(), ip)
  |                                   ^^ expected struct `show::ip::Ip`, found struct `ip::Ip`

Upvotes: 1

Views: 650

Answers (2)

Masklinn
Masklinn

Reputation: 42592

#[path = "ip.rs"] mod ip;
#[path = "mask.rs"] mod mask;

This declares new submodules, independent from the ones declared in mod.rs. That they have the same source code is immaterial, as far as typechecking and object identity are concerned they're completely unrelated.

Essentially, you've defined the following structure:

pub mod mask { ... }
pub mod ip {
    pub struct Ip { ... }
    pub fn build_ip(ip: String) -> Ip { ... }
}
pub mod show {
    mod ip  {
        pub struct Ip { ... }
        pub fn build_ip(ip: String) -> Ip { ... }
    }
    mod mask { ... }
    pub fn print(name: String, ip: ip::Ip) { ... }
}

If you want to import modules, you should use use. If you need to import sibling modules, you can use the crate:: segment (in order to start resolving from the current crate's root), or super:: (to move up a level from the current module).

So here show should contain either use crate::{ip, mask} or use super::{ip, crate} in order to "see" its siblings.

The pub for use ip::Ip; is also completely unnecessary, you only needed it because you were declaring a new ip module, and thus needed its Ip to be public since you were using it in a pub function.

Upvotes: 5

Gabaa
Gabaa

Reputation: 1

In show.rs, you write add the modules ip and mask, but these are already added in main.rs.

Instead, in show.rs use something like the following:

use crate::ip::Ip;

pub fn print(name: String, ip: Ip) {
    ...
}

Upvotes: 0

Related Questions