Skip to content

Use.is_glob changes meaning of Use.id and Use.name #51

Open

Description

@kornelski

id of Use (from ItemEnum::Use) may refer either directly to the item that has been imported as item.name, or a parent module that has not been added to the namespace as item.name, but merely holds items that were imported.

This effectively creates two different types/variants of the Use, without there being types/variants in the type system for the different meanings. It causes bugs whenever the .id or .name is used without also checking is_glob and implementing two very distinct code paths for interpreting the same fields of the same type.

Additionally, figuring out which items have actually been imported requires reimplementing name resolution, which is quite inconvenient.

Use is already nicely broken down into individual imported items, so that use m::{foo, bar, baz} creates 3 Use items instead of one. It makes processing of the items simpler, because it avoids creating a one-to-many relationship between items. Unfortunately, that's not the case for glob imports. It would be great to have the same expansion and normalization happening for glob imports, and have use m::* create as many Use items as needed to represent every imported item individually. This way, processing of items from glob and non-glob imports would be unified for consumers of the rustdoc JSON.

Activity

  1. changed the title [-]Use.is_glob changes meaning of Use.id and Use.name[/-] [+]`Use.is_glob` changes meaning of `Use.id` and `Use.name`[/+] on Jul 15, 2025
  2. aDotInTheVoid commented on Jul 15, 2025

    @aDotInTheVoid
    Member

    This effectively creates two different types/variants of the Use, without there being types/variants in the type system for the different meanings. It causes bugs whenever the .id or .name is used without also checking is_glob and implementing two very distinct code paths for interpreting the same fields of the same type.

    Changing Use to have UseItem and UseGlob (names subject to bike shedding) seams like an obvious win.

    It would be great to have the same expansion and normalization happening for glob imports, and have use m::* create as many Use items as needed to represent every imported item individually. This way, processing of items from glob and non-glob imports would be unified for consumers of the rustdoc JSON.

    This will require more design. I don't think we want to totally unify them, as I'd want the difference to be available to tools that care. But it makes sense that this resolution is alot easier to do in rustc, so we should probably be doing it.

  3. kornelski commented on Jul 15, 2025

    @kornelski
    Author

    I'm not proposing to totally unify them to the point of erasing information.
    I'd just like a consistent design approach used for the normalized representation of use m::{a,b} and use m::*, so that consumers who only care about the items/namespaces, and not surface-level syntax, don't have to write very different code for UseItem and UseGlob. There can still be an additional glob-specific metadata attached to the objects created from globs.

    In the original post I've called reimplementation of imports "inconvenient", but that has been an understatement. It's not enough to look items up in the source module! The source module may contain glob imports itself. Glob imports allow cycles - a glob import can import another glob import, which glob imports from the first one. There can also be multiple glob imports shadowing each other, while forming multiple inter-connected cycles.

    pub mod a {
        pub use super::a as b;
        pub use super::d::*;
    }
    
    pub mod b {
        pub use super::d::*;
        pub use self::b as a;
    }
    
    pub mod c {
        pub use super::a::*;
        pub use self::b::*;
        pub mod a { pub use super::*; }
    }
    
    pub mod d {
        pub use super::b::a::a::a::a::a::a::a::a::a::a::a::a::a::a::a::a::a::a::a::a::a::a::a::a::a::a::a::a::a::a::a::a::a::a::a::a::b::*;
        pub use super::c::*;
        pub use super::a::*;
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions