Idea: Associated anonymous module item

At least for me many times when i'm writing impls, i feel a lack of ability to write use items, auxiliary functions, and so on, for the ergonomics of writing associated item signatures. I can put them in to the outer scope, but its scope will become unnecessarily large.

Here i suggest adding anonymous associated module item to the language, and put its inner items in scope of resolution of all associated items within the same impl block.

Let's do not generalize this to trait items too, only inherent and trait impl items.

Example, old way of implementation:

struct DeviceContext(usize);
fn helper_fn1() {}
impl DeviceContext {
    fn from_ptr(v: winapi::shared::windef::HDC) -> Self {
        DeviceContext(v as _)
    }
    fn into_inner(&self) -> winapi::shared::windef::HDC {
        helper_fn1();
        self.0 as _
    }
}

new approach:

struct DeviceContext(usize);

impl DeviceContext {
    mod {
        use winapi::shared::windef::HDC;
        fn helper_fn1() {}
    }

    fn from_ptr(v: HDC) -> Self {
        DeviceContext(v as _)
    }
    fn into_inner(&self) -> HDC {
        helper_fn1();
        self.0 as _
    }
}
5 Likes

For inherent implementations, what's preventing you from doing this now? Visibility isn't an issue like it would be with trait impls.

currently inherent implementations can only contain associated items, including associated constant, type and function.

This would be really useful for macros, for example if a macro needs to access a global without anyone else being able to access it. (Right now if I declare a global in a macro, it becomes visible outside the macro. No hygiene)

Yes, what I'm saying is that you can currently have a private method in the inherent impl, which would have the same effect.

That particular example can also be written as:
Playground link(with tweaks because winapi::shared doesn't exist in the playground)

struct DeviceContext(usize);

const _: () = {
    use winapi::shared::windef::HDC;
    fn helper_fn1() {}

    impl DeviceContext {
        fn from_ptr(v: HDC) -> Self {
            DeviceContext(v as _)
        }
        fn into_inner(&self) -> HDC {
            helper_fn1();
            self.0 as _
        }
    }
};

If you're curious, const _: Foo = bar; was stabilized in Rust 1.37, and proposed in RFC 2526

Indeed that works, other than... it's a little unpretty.

1 Like

Still, i want to highlight that the ability to "intermix" non methods within trait impls and keep them in any order i wanted is something that i wish rust had from time to time. Not sure if this is best way to do so, it is absolutely one of the approaches.