1. 28

  2. 12

    In addition to these pain points (most of which I can say I’ve also run into, personally), the way it encourages a proliferation of files uselessly named “mod.rs” has always seemed like a bad thing as well, to me.

    (A good example here is libc, which had 27 files named mod.rs last time I looked at it. Always fun to play “guess which mod.rs is the one you want to switch to” in your editor)

    1. 6

      Rust’s module system is arcane, to be sure. I regularly trip over it myself.

      I loathe file system based module approaches though - invariably it makes complex integrations harder than they already area.

      1. 8

        What do you mean by ‘integrations’, here?

        The thing I like about using the filesystem hierarchy as the module hierarchy (as Python does) is that the hierarchy is obvious and explorable even before I open my text-editor.

      2. 5

        both mod and extern crate are semi-redundant with other user actions (creating a new file, adding a dependency to Cargo.toml).

        No, mod is not redundant. Oftentimes I have half-baked modules, which I know won’t typecheck (which is a part of normal exploratory programming in a typeful language like Rust). I don’t want that to stop me from building and testing the parts of my program that do typecheck.

        In languages with an implicit canonical module tree, it is not uncommon for every file to be treated as a ‘leaf’ node of that tree. That is, no modules are actually submodules of other modules; there are just namespaces which contain nested namespaces (that is, they lack - or rarely utilize - an equivalent of the mod.rs file).

        Yes, and this is a really bad idea. Haskell works like this, and it isn’t uncommon for Haskell modules to begin with half a screenful of module imports. (Depending on the size of your screen, of course.) It doesn’t help to use helper modules just to reexport stuff from other modules, because it isn’t possible to export a qualified name while retaining the qualification. It’s really painful.

        Lastly, one thing that makes this a bit more complicated is that use takes paths starting from the root of the crate, while paths used inline in the module start from that module.

        One solution to this problem is to make module scope work just like block scope: everything declared in a parent module is automatically available in a child module unless shadowed by another declaration in the latter. This eliminates the need to use self and super in use declarations. If, in foo::bar, you need to import foo::baz::qux, you just use baz::qux;. In my experience, this works reasonably well, and it works even better if your module system supports signature ascription, so you can hide part of a module’s contents before reexporting it.

        Edit: Incidentally, this isn’t exactly a problem with Rust’s module system, but rather with rustdoc. When you pub use foo::qux; inside a mod bar;, rustdoc doesn’t make it clear that bar::qux is just foo::qux reexported. This is painful when I want to use the documentation as a guide for navigating a library’s source code.

        Edit: Tweaked example of hierarchical module scopes.

        1. 3

          I had trouble with the module system at first as well. The reason has more to do with the Rust book than with the module system itself, I think. Although the book is great, if the Crates and Modules chapter were more thorough then I think there would be much fewer people searching for answers elsewhere. Version two of the book is underway so maybe this will be addressed.

          1. 6

            You can read the current incarnation of the chapter here, seems like they’ve improved it and added more step-by-step examples.

          2. 2

            I’d be interested in reading a guide to Rust’s module system for {C, Java, Python, Ruby, etc} programmers. Does anyone know of a good guide like this, or for moving to Rust from another language in general?

            1. 2

              It’s not specifically what you requested, but there is a modules chapter in the new book that might help: http://rust-lang.github.io/book/ch07-00-modules.html