# Pub(crate) keyword suggestion

**URL:** <https://internals.rust-lang.org/t/pub-crate-keyword-suggestion/18367>\
**Category:** Uncategorized\
**Created:** [February 18, 2023, 2:10pm UTC](https://internals.rust-lang.org/t/pub-crate-keyword-suggestion/18367 "2023-02-18T14:10:01Z")\
**Posts on this page:** 11\
**Page:** 2

<div class="post-metadata">

**Author:** ![SkiFire13](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/skifire13/32/7579_2.png) [@SkiFire13](https://internals.rust-lang.org/u/SkiFire13)\
**Post date:** [February 20, 2023, 7:43am UTC](https://internals.rust-lang.org/t/pub-crate-keyword-suggestion/18367/21 "2023-02-20T07:43:42Z")

</div>

> [@hydroper1](#):
>
> I see, but is that syntax really needed? The proposal didn't mention anywhere of using `api` as a prefix qualifier with `::`. Like, I think `::x` is more useful than `api::x`.

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.

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

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

```

---

<div class="post-metadata">

**Author:** ![hydroper1](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hydroper1/32/12099_2.png) [@hydroper1](https://internals.rust-lang.org/u/hydroper1)\
**Post date:** [February 20, 2023, 10:48am UTC](https://internals.rust-lang.org/t/pub-crate-keyword-suggestion/18367/22 "2023-02-20T10:48:33Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![SkiFire13](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/skifire13/32/7579_2.png) [@SkiFire13](https://internals.rust-lang.org/u/SkiFire13)\
**Post date:** [February 20, 2023, 12:31pm UTC](https://internals.rust-lang.org/t/pub-crate-keyword-suggestion/18367/23 "2023-02-20T12:31:43Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![hydroper1](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hydroper1/32/12099_2.png) [@hydroper1](https://internals.rust-lang.org/u/hydroper1)\
**Post date:** [February 20, 2023, 12:33pm UTC](https://internals.rust-lang.org/t/pub-crate-keyword-suggestion/18367/24 "2023-02-20T12:33:28Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)\
**Post date:** [February 20, 2023, 12:38pm UTC](https://internals.rust-lang.org/t/pub-crate-keyword-suggestion/18367/25 "2023-02-20T12:38:22Z")

</div>

`pub` is a _visibility modifier_, not part of the path

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

```

are different, one allows external access to its field.

---

<div class="post-metadata">

**Author:** ![hydroper1](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hydroper1/32/12099_2.png) [@hydroper1](https://internals.rust-lang.org/u/hydroper1)\
**Post date:** [February 20, 2023, 12:43pm UTC](https://internals.rust-lang.org/t/pub-crate-keyword-suggestion/18367/26 "2023-02-20T12:43:23Z")

</div>

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...

```rust
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`?

---

<div class="post-metadata">

**Author:** ![SkiFire13](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/skifire13/32/7579_2.png) [@SkiFire13](https://internals.rust-lang.org/u/SkiFire13)\
**Post date:** [February 20, 2023, 4:03pm UTC](https://internals.rust-lang.org/t/pub-crate-keyword-suggestion/18367/27 "2023-02-20T16:03:34Z")

</div>

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 `::`

```rust
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;
}

```

---

<div class="post-metadata">

**Author:** ![matklad](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/matklad/32/12266_2.png) [@matklad](https://internals.rust-lang.org/u/matklad)\
**Post date:** [February 20, 2023, 7:45pm UTC](https://internals.rust-lang.org/t/pub-crate-keyword-suggestion/18367/28 "2023-02-20T19:45:31Z")

</div>

> [@scottmcm](#):
>
> but `api ::blahblah` is -- it's the same problem as `crate`.

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.

---

<div class="post-metadata">

**Author:** ![petrochenkov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/petrochenkov/32/2784_2.png) [@petrochenkov](https://internals.rust-lang.org/u/petrochenkov)\
**Post date:** [February 20, 2023, 8:30pm UTC](https://internals.rust-lang.org/t/pub-crate-keyword-suggestion/18367/29 "2023-02-20T20:30:30Z")

</div>

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](https://github.com/rust-lang/rust/issues/53120#issuecomment-622137179) this out in every thread discussing `crate` visibility, but in the end this nonsense was even declared the official reason to remove the feature 🤦‍♂️

---

<div class="post-metadata">

**Author:** ![matklad](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/matklad/32/12266_2.png) [@matklad](https://internals.rust-lang.org/u/matklad)\
**Post date:** [February 20, 2023, 8:45pm UTC](https://internals.rust-lang.org/t/pub-crate-keyword-suggestion/18367/30 "2023-02-20T20:45:20Z")

</div>

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 🤣

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [May 21, 2023, 8:45pm UTC](https://internals.rust-lang.org/t/pub-crate-keyword-suggestion/18367/31 "2023-05-21T20:45:35Z")

</div>

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

[Previous page](https://internals.rust-lang.org/t/pub-crate-keyword-suggestion/18367.md?page=1)
