Pub(crate) keyword suggestion

The following compiles today, and the struct X contains an instance of Foo from the module declared here. With your proposal it would now refer to an instance of Foo from a (potentially non-existing) feature crate. This is a breaking change.

mod api {
    pub mod feature {
        pub struct Foo;
    }
}

struct X(api ::feature::Foo);
3 Likes

Yes, I got it. What I mean is, isn't pub::x almost the same as ::x, and thus unnecessary as api::x in regards to the top proposal here?

I don't think I understood the question. Are you saying that api::x should continue to have the current meaning since you can use pub ::x to get almost the other meaning? This seem pretty special cased to me.

1 Like

Yes, but you don't need pub:: when you can do :: (::feature::Foo for example).

pub is a visibility modifier, not part of the path

pub struct X(::foo::Foo);
pub struct X(pub ::foo::Foo);

are different, one allows external access to its field.

1 Like

Now I got confused. I tried both of these at the playground and got:

failed to resolve: could not find foo in the list of imported crates

Hmm... So both of these lines declare a X structure with a ::foo::Foo field, but the latter makes the field public, is that it? OK, got it...

mod x {
    pub struct X(pub ::std::string::String);
}

fn f() {
    let o = x::X("abc".to_owned());
    o.0;
}

It looks like pub struct X(pub std::string::String); also works. So maybe discard pub ::x or api ::x?

The leading :: has a meaning: it forces the next identifier to refer to a crate rather than any module. The following example doesn't work if you remove the leading ::

mod x {
    pub mod std {
        pub mod string {
            pub struct String;
        }
    }

    pub struct X(pub ::std::string::String);
}

fn f() {
    let o = x::X("abc".to_owned());
    o.0;
}
4 Likes

With api it’s a bit more mild, crate ::foo is strongly ambiguous, in that there’s no way to disambiguate that. With api, the disambiguating can be api ::r#api / r#api::r#api. So, in theory these two approaches would work, with varying degrees of churn:

  • make api a strong keyword in an edition X, requiring use of r#api if compat warnings are on in the previous edition.
  • make api a contextual keyword, which would only require r#api in genuinely ambiguous cases (namely, in tupple struct fields). That is, if api can be parsed as a keyword, it is parsed as a keyword, and r# is mandatory for alternative reading.
1 Like

The same non-problem, you mean.

We have several cases in the language requiring local disambiguation between possible parses, and this one is no different.

I've been consistently pointing this out in every thread discussing crate visibility, but in the end this nonsense was even declared the official reason to remove the feature :man_facepalming:

3 Likes

I stand corrected, thanks! There are indeed trivial disambiguators for crate ::foo:
pub(crate) ::foo
or
pub(self) crate::foo
(depending on which parse we pick by default), if I spend 30 seconds actually thinking about this :rofl:

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.