diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 712c3af..20368e2 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -21,6 +21,7 @@ - [Doc alias policy](./policy/doc-alias.md) - [Safety comments policy](./policy/safety-comments.md) - [Reviewing target-specific code](./policy/target-code.md) + - [Policy for inclusion in the prelude](./policy/prelude.md) - [Tricky situations]() - [Drop and `#[may_dangle]`](./tricky/may-dangle.md) diff --git a/src/breaking-changes/prelude.md b/src/breaking-changes/prelude.md index cf38517..5b18ac1 100644 --- a/src/breaking-changes/prelude.md +++ b/src/breaking-changes/prelude.md @@ -1,7 +1,7 @@ # Breaking changes to the prelude Making changes to the prelude can easily cause breakage because it impacts all Rust code. -In most cases the impact is limited since prelude items have the lowest priority in name lookup (lower than glob imports), but there are two cases where this doesn't work. +In most cases the impact is limited since prelude items have the lowest priority in name lookup (lower than glob imports), but there are three cases where this requires additional care or may not be possible. ## Traits @@ -15,4 +15,14 @@ For this reason, [`TryFrom` and `TryInto`](https://github.com/rust-lang/rust/iss Unlike other item types, rustc's name resolution for macros does not support giving prelude macros a lower priority than other macros, even if the macro is unstable. As a general rule, avoid adding macros to the prelude except at edition boundaries. -This issues was encoutered when trying to land the [`assert_matches!` macro](https://github.com/rust-lang/rust/issues/82913). +This issue was encountered when trying to land the [`assert_matches!` macro](https://github.com/rust-lang/rust/issues/82913). + +## Types + +Adding a new type usually doesn't create any breakage, because prelude types have a lower priority than names in user code. + +However, code that declares an enum, *and* has a derive on that enum, *and* attempts to locally import a variant from that enum (e.g. `use EnumType::Variant;`) will break if the prelude starts exporting a type with the same name as that enum. + +This makes adding a new type to the prelude require a crater run to check for breakage in existing Rust code. + +If Rust code declares a local variable binding and the prelude adds a type of the same name, this can likewise introduce breakage. This case is much less likely to arise, as it requires declaring a variable name using the `CamelCase` convention typically used for types, and ignoring rustc's warnings about doing so. diff --git a/src/policy/prelude.md b/src/policy/prelude.md new file mode 100644 index 0000000..697e9b4 --- /dev/null +++ b/src/policy/prelude.md @@ -0,0 +1,69 @@ +Policy for inclusion in the prelude +=================================== + +The Rust standard library provides a "prelude": items that Rust programs can +use without having to import anything. For instance, the Rust prelude includes +[`Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html), so programs can +write `Vec::with_capacity(4)` without having to first import `Vec` from the +standard library. + +Each edition of Rust has its own prelude, so that new editions of Rust may add +items without making those items available to all code in older editions of +Rust. + +This policy sets out the requirements for what items we add to the prelude, and +whether we add those items to the prelude for a future edition or to the common +prelude for all Rust editions. + +When to use editions +-------------------- + +[Some kinds of additions to the prelude can cause breakage in existing +code](../breaking-changes/prelude.md), so we must either avoid making such +changes entirely or check carefully with crater before making them. + +Adding a trait to the prelude can break existing Rust code, by creating name +resolution ambiguity where none previously existed. While introducing +resolution ambiguities may be "permitted breakage", doing so is quite +disruptive, and we want to avoid doing so. Thus, we generally never add a trait +to the common prelude; we only add traits to the preludes for new editions of +Rust. + +Likewise, adding a macro to the prelude can break existing code, so we +generally can't add macros to the common prelude, and can only add macros to +the preludes for new editions of Rust. + +Finally, in some cases adding a type to the prelude can break existing code. +The cases in which this arises are narrower, but still require at a minimum +checking a crater run. + +Adding items other than traits, macros, or types to the prelude will never +produce conflicts or other compatibility issues with existing code, since we +allow shadowing and give other sources of names priority over names from the +prelude. Thus, if we choose to add another kind of item to the prelude, we +should typically add it to the common prelude for all editions of Rust. +(Exceptions to this would include names that form part of an edition +transition, such that the same name resolves to something different in +different editions.) + +Criteria for including an item +------------------------------ + +An item included in the prelude can be used by its unqualified name, by any +Rust code. Users can look up the item by name, and easily get documentation for +it. However, in general the name should make sense without any context, such as +within a diff hunk or code sample. Any name we include in the prelude should be +one that will not confuse users if they see it unqualified, without anything +introducing the name. + +In particular, the name should not be something users are likely to +misunderstand as coming from the local crate or its dependencies. While any +crate *could* define any name, the names in the prelude should be *unlikely* to +occur unqualified in another crate. (A conflict with a name typically used +qualified or in a different context is not a problem; for instance, a common +method name `Object::name`, commonly called via `expr.name`, does not +necessarily preclude adding a free function `name` to the prelude.) + +We should only add an item to the prelude if some reasonable number of crates +are likely to use the item. It need not be an item used by the *majority* of +crates, but it should be reasonably frequent across the ecosystem.