Rust 2018: an early preview

Problem here is what "a while" is. This would work if we were doing a 2021 edition (vs. 2018 edition), where new idioms between the 2 editions would be documented, and even that should really only be about those which happen to also break compatibility with the 2018 edition.

The thing about idioms is they change frequently, such that in 2024, even 2015 edition idioms will have changed (supposing people would remain with such an old edition, which will, according to plan, still be a supported setup).

(The plan is to make a new edition every few years, so it is very possible that weā€™ll have a Rust 2021 in addition to 2018 and 2015.)

@tshepang I think weā€™re making the same point. We give the same ā€œeditionā€ name to two things: ā€œhey look, these feature are new since the last couple of yearsā€ v.s. ā€œyou can opt into some incompatibility and get this subset of new features in exchangeā€. The new features are not the same in both cases, so not having separate terms to talk about them can be confusing.

1 Like

The in-band lifetime:

fn two_args(foo: &Foo, bar: &'bar Bar) -> &'bar Baz

Is easier to read as:

fn two_args2(foo: &Foo, bar: &Bar@bar) -> &Baz@bar

Or something like:

fn two_args3(foo: &Foo, bar: &Bar::bar) -> &Baz::bar
fn two_args4(foo: &Foo, bar: &Bar:bar) -> &Baz:bar

Maybe in-band generics:

fn other_args<'a, T:'a> (v: &'a T, size: int) -> T:'a

To:

fn other_args(T: type@a, v: &T@a, size: int) -> T@a

ā€¦

Yeah, am aware... sorry that it wasn't clear.

Really digging the new extern crate semantics!

With #![warn(rust_2018_idioms)], though, Iā€™m getting some weird warnings about extern crate being unidiomatic, even though I have no actual extern crate lines anywhere. They all point to #[derive()]'s for serde::Serialize and serde::Deserialize as far as Iā€™ve seen - is this because thereā€™s an extern crate being generated as a part of the custom deriveā€™s codegen?

I also managed somehow to get the same warning to point to the first line of my main.rs, which was just a comment, though I havenā€™t been able to reproduce it.

Yes.

1 Like

Iā€™ll add my voice here to the list of people who think simplifying ā€œpub(crate)ā€ is an anti-feature. Itā€™s not used often enough IMO to need shortening, and it overlaps with too many other constructs.

9 Likes

Is it intentional that absolute paths starting with a leading :: rather than crate:: no longer work?

For example:

struct Foo;

// works in 2015, not in 2018, can't find crate for Foo error
struct Bar(::Foo);

// works in 2018, not in 2015
struct Baz(crate::Foo);

At least partially yes, though last I heard itā€™s still somewhat up in the air what will happen to :: in the 2018 edition. ::Foo will certainly not be idiomatic, will most likely be deprecated, and may either change meaning like what you see there or even be removed entirely.

About pub(crate) vs crate: I think pub(crate) is better. Itā€™s consistent with pub(super). Also, crate is just Rustā€™s equivalent to what other languages call package. Itā€™d look weird to use package in that position, so I donā€™t see why using crate in that position should be any less weird. Iā€™d prefer to stick with pub, pub(crate) and pub(super).

13 Likes

This begs the question of whether pub(super) is consistent with pub. pub(super) limits visibility to the parent module in the same crate. Thus, pub(super) isn't public; it's more like java's package-private, C#'s internal, or C++'s "not listed in a header file". It's more consistent for pub(super) to be crate(super).

FWIW, crate wouldn't be my first choice for this-- I'd prefer local (as noted in the RFC), or appropriating internal from C#.

1 Like

pub(super) means it is made public to the parent module. I think the keyword fits quite well.

1 Like

For a fair comparison on pub(crate) versus pub usage, turn on #![warn(unreachable_pub)] and fix all of those warnings to be pub(crate).

I am on the side of crate fn being a good thing ā€“ a fn for this crate ā€“ because it creates a much clearer distinction between pub-to-the-world and pub-internally.

6 Likes
crate mod ...

Means Iā€™m declaring a module that has crate-level visibility. To me that reads clearer than pub(crate). Not to dismiss yourā€™s or anyone elseā€™s opinion on this though, Iā€™m just pointing out that saying whether pub(crate) mod or crate mod reads better or makes more sense entirely depends on who you ask and how they read it.

5 Likes

@gbutler Youā€™re probably right in that once we get used to it, it will probably be quite clear. Itā€™s even likely that after a while weā€™ll prefer crate because itā€™s easier to write xD Also, Iā€™ve now noticed that my comparison to pub(super) has a flaw: pub(super) visibility is not nearly as important as crate or pub visibility because visibility limitations within a crate are less significant by comparison.

2 Likes

I always considered pub(crate) as a temporary hack to fit into the current syntax without breaking anything. The ā€žparametersā€œ or whatever it is seems clumsy. Any reason why super is not a separate visibility modifier as well?

8 Likes

+ to the question.

Quick search in the rust repo (without tests and docs) - pub(crate) - 118 results, pub(super) - 170 results.

I've gathered some statistics about distribution of "sufficient visibilities" in the original RFC - pub(restricted) item by pnkfelix Ā· Pull Request #1422 Ā· rust-lang/rfcs Ā· GitHub and pub(super) was more common too.

(I addition, pub(crate) in the root module is useless and can be removed, but pub(super) in root module is invalid, so use of pub(super) by default even in cases when super is equivalent to crate prevents this little mistake.)

4 Likes

@vorner @petrochenkov @MajorBreakfast @gbutler @illustrious-you @CAD97 @anon19897381

I have started a new thread for this discussion about super and pub(super) to keep this thread more focused on the preview: Visibility modifiers: pub(super) vs. super.

4 Likes

Iā€™m curious if stabilizing crate visibility later would be an optionā€¦

5 Likes

I like the changes to macros in module system, as someone already wrote above this will syntax will be pretty, (both foo and bar extern crates)

use foo::foo!;
use bar::{bar!, zoo!};

One thing may be inconsistent (in my opinion) is that for submodules we still need to use #[macro_use], it will be better to extents syntax for external crates for submodules.

In our crate, we have a zoo submodule with #[macro_export], the above syntax is consistent.

use zoo::{zoo!, copy!};

This even leads to re-exports for libs, being able to re-export their macros in a simplified prelude.

pub mod prelude {
    pub use macros::{scr!, link!};
    /* ... */
}
2 Likes