self and super behave inconsistently in use statements and as module names

d2516a3
Opened by Collin J. Sutton at 2020-01-25 17:28:45

Handling of self and super in use and mod statements is inconsistent. Playpen:

use self;                        // error: `self` imports are only allowed within a { } list [E0429] (expected)
                                 // error: unresolved import `self`. There is no `self` in the crate root [E0432]

mod super {                      // error: expected identifier, found keyword `super`
    type Test = u32;
    mod submodule {
        use super;               // error: a module named `super` has already been imported in this module [E0252]
        use super::{self, Test}; // (^^^ apparently "already" means "on the next line"?)
    }
    use super;                  // (no error for this one?)
}

There are probably several (related) issues here.

  • Inconsistent handling of keyword status for self and super as module names: if we add a mod self { } to the above, we get the two "expected identifier, found keyword" errors we'd expect -- and no other output. It appears that mod self { } causes an immediate "aborting due to previous error", while mod super { } does not.
  • use super::{self, ...}; doesn't special-case the self keyword as a keyword like use foo::bar::{self, ...}; does.
  • use super; doesn't special-case the super keyword as a keyword.
  • use self; does do some special-casing so it can produce "error: self imports are only allowed within a { } list [E0429]", but it then continues by attempting to resolve self as an ident.
  1. I'd be happy to take a shot at fixing these issues, but I'd like some feedback on my summary of what's going on before I do.

    Collin J. Sutton at 2016-08-12 00:01:39

  2. use super::{self, ...}; doesn't special-case the self keyword as a keyword like use foo::bar::{self, ...}; does.

    Why do you say this? Judging by the errors, use super::{self}; is equivalent to use super;.

    Eduard-Mihai Burtescu at 2016-08-12 03:18:52

  3. This is similar to https://github.com/rust-lang/rust/issues/29036

    Vadim Petrochenkov at 2016-08-12 08:15:56

  4. Inconsistent handling of keyword status for self and super as module names

    This is not true, try to experiment more. Keywords in identifier positions do the next things: 1) report a non-fatal error, 2) define an identifier with keyword name - this is a part of error recovery in parser.

    So, mod super actually defines a module named super. This is ok because the code is already erroneous and we can do anything more or less reasonable, perfect error recovery is not guaranteed.

    mod super { // reports an error and defines a module
        mod m {
            pub struct S;
        }
    
        // no error, module super is imported, this is bug #29036,
        // naked self and super are not treated correctly in imports
        use super as ident;
        // no error, everything is correctly routed to "super"::m::S
        type Z = ident::m::S;
    }
    

    Vadim Petrochenkov at 2016-08-12 08:32:59

  5. I'm not sure what action should be taken here. @petrochenkov do we need to change any behaviour or should we just improve diagnostics?

    Oli Scherer at 2020-01-25 17:23:20

  6. In general, the behavior needs to be changed. Imports of self and super need to be accepted if they are renamed into something that is not a keyword, similarly to crate.

    use crate as name; // OK
    use crate; // ERROR, needs the "as name" part
    

    For the examples in the issue it will only result in diagnostic changes though, because they are all erroneous.

    Vadim Petrochenkov at 2020-01-25 17:28:45