Trying to understand the compiler for Use of undeclared type or module


#1

Hi , all
first of all I’m a complete newbie to rust but I really like what I’ve seen so far :grinning:.

I’m trying to read a directory and create an structure for each file, so:

use std::fs;
use std::env;
use std::fs::DirEntry;

pub struct Directory {
  path: std::fs::DirEntry
} 

fn readDir() {
    let p = env::current_dir().unwrap();
    let mut collection = vec![];
    let paths = fs::read_dir( &p.join("patches") ).unwrap();
    for path in paths {
      collection.push( Directory{ path: &path.unwrap().display() } );
    }
}

question: why the compiler complains of undeclared module if I’ve declared it with “use std::fs”?:

src/patches/mod.rs:6:9: 6:26 error: failed to resolve. Use of undeclared type or module `std::fs` [E0433]
src/patches/mod.rs:6   path: std::fs::DirEntry
                             ^~~~~~~~~~~~~~~~~
src/patches/mod.rs:6:9: 6:26 help: run `rustc --explain E0433` to see a detailed explanation
src/patches/mod.rs:6:9: 6:26 error: type name `std::fs::DirEntry` is undefined or not in scope [E0412]
src/patches/mod.rs:6   path: std::fs::DirEntry
                             ^~~~~~~~~~~~~~~~~
src/patches/mod.rs:6:9: 6:26 help: run `rustc --explain E0412` to see a detailed explanation
src/patches/mod.rs:6:9: 6:26 help: you can to import it into scope: `use std::fs::DirEntry;`.

best!


#2

Ha! got it

It seems that the module should be called with an prepending :: , like
pub struct Directory {
path: ::std::fs::DirEntry
}

this only happen when the file is outside main.rs , right ?


#3

this only happen when the file is outside main.rs , right ?

Yeah. To be more precise, Rust inserts an implicit extern crate std to the root module (and main.rs is a root module of binary). So in the root module you can use std while in other modules you need to ::std.

However use paths are imiplicitly global, that is

use foo;

is the same as

use ::foo;

So you usually

use std::fs::DirEntry;

without :: in any module.

Also, use declarations introduce names to the module’s scope, so your original example can be written a bit more idiomatically as

use std::fs::{self, DirEntry};
use std::env;

pub struct Directory {
  path: DirEntry
} 

or as

use std::fs;
use std::env;

pub struct Directory {
  path: fs::DirEntry
} 

#4

Since you’re already doing

use std::fs::DirEntry;

you have imported DirEntry into the scope and can write

    path: DirEntry

If you wanted, you could do entirely without use (except for bringing traits into scope), and fully qualify all APIs you’re using, but that quickly leads to an unreadable mess.


#5

Thanks for your replies @birkenfeld and @matklad.
Both solutions work fine. Thanks for give me more context on this

best