Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge the namespaces (at next epoch) #2612

Open
Ekleog opened this issue Dec 14, 2018 · 4 comments
Open

Merge the namespaces (at next epoch) #2612

Ekleog opened this issue Dec 14, 2018 · 4 comments
Labels
A-resolve Proposals relating to name resolution. breaking-change The RFC proposes a breaking change. T-lang Relevant to the language team, which will review and decide on the RFC.

Comments

@Ekleog
Copy link

Ekleog commented Dec 14, 2018

I have seen this on IRC today, written by @amaranth:

eval: u8::max_value()
Notice(eval): 255    

eval: mod u8 { pub fn max_value() -> u32 { u32::max_value() } } u8::max_value()        
Notice(eval): 4294967295                                                               

Given that modules and types have very different recommended naming scheme, I think it would make sense to merge these two namespaces by forbidding having a module with the same name as a type. This would require shuffling some things from the u8 module to the u8 type, I guess, but hopefully little that could break backwards-compatibility too much for an epoch.

As for the variables namespace, I guess it's a bit harder, given that the recommended naming scheme is the same as for modules. My perfectionist self would rather have it be merged with the others too with variables able to shadow modules, but it may be harder to pull out from a “let's not break too much retro-compatibility” perspective.

Finally, for the “Why?”, the reason is that separate namespaces:

  • Make things tricky to learn (“wait so this is both a type and a module and a variable and a macro?”)
  • Increase the attack surface for underhanded Rust code

What do you think about this?

Cheers,
Leo

@ExpHP
Copy link

ExpHP commented Dec 15, 2018

The type namespace and the module namespace already do share a namespace. I think you just shadowed the type u8.

You can do this with a struct, too:

struct u8;
impl u8 {
    const fn max_value() -> u32 { u32::max_value() }
}

There is something weird you can do that almost suggests evidence to the contrary:

use std::u8;

fn lol() -> u8 { 0 } // This compiles!

...but if you try to replicate this for anything else, it becomes clear that this is just a hack for the builtin primitive types.

mod a {
    pub mod B {}
}

mod b {
    pub struct B;
}

use crate::a::B;
use crate::b::*;

// error[E0573]: expected type, found module `B`
fn lol() -> B { panic!() }

@petrochenkov
Copy link
Contributor

Yes, treatment of built-in types is special compatibility hack (rust-lang/rust#32131 is the relevant PR), otherwise types and modules share the same namespace.

@ExpHP
Copy link

ExpHP commented Dec 15, 2018

What do you think about this?

To give a more general response, I think it sounds like a dreadfully large breaking change. It only took me a couple of minutes to dredge up a few examples from my own codebase where it would be problematic for variables to "shadow" modules.

match config {
    // ...
    cfg::PotentialKind::ReboNew(cfg) => {
        let cfg = cfg.clone();
        let parallel = threading == &cfg::Threading::Rayon;  // <--- !
        Box::new(self::homestyle::Rebo { cfg, parallel })
    },
    // ...
}

// ...

impl LammpsPotential for Airebo {
    fn init_info(&self, _: &Coords, meta: &CommonMeta) -> InitInfo {
        let elements: meta::SiteElements = meta.pick();  // <--- !
        let masses: meta::SiteMasses = meta.pick();

        // ...
    }
}

// ...

unsafe { ptr::read(ptr) }

As I see it, the design of Rust to this point has largely embraced namespacing. This train has an awful lot of momentum if you want to turn it around.

@Ekleog
Copy link
Author

Ekleog commented Dec 16, 2018

@petrochenkov Good point, so my point about types and modules only holds for the primitives types.

@ExpHP Your point about variables shadowing modules is actually what I mentioned in the top post and it being harder due to being the same naming convention. Rewording it here, I do believe that things would be more readable if it was not possible, but it may be too big a breaking change even for an epoch.

@jonas-schievink jonas-schievink added A-resolve Proposals relating to name resolution. breaking-change The RFC proposes a breaking change. T-lang Relevant to the language team, which will review and decide on the RFC. labels Nov 19, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-resolve Proposals relating to name resolution. breaking-change The RFC proposes a breaking change. T-lang Relevant to the language team, which will review and decide on the RFC.
Projects
None yet
Development

No branches or pull requests

4 participants