diff --git a/src/attributes.md b/src/attributes.md index a1ad5c60c..5ce631365 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -196,7 +196,7 @@ struct S { pub fn f() {} ``` -> Note: `rustc` currently recognizes the tools "clippy" and "rustfmt". +> Note: `rustc` currently recognizes the tools "clippy", "rustfmt" and "diagnostic". ## Built-in attributes index @@ -224,6 +224,8 @@ The following is an index of all built-in attributes. - [`allow`], [`warn`], [`deny`], [`forbid`] — Alters the default lint level. - [`deprecated`] — Generates deprecation notices. - [`must_use`] — Generates a lint for unused values. + - [`diagnostic::on_unimplemented`] — Hints the compiler to emit a certain error + message if a trait is not implemented. - ABI, linking, symbols, and FFI - [`link`] — Specifies a native library to link with an `extern` block. - [`link_name`] — Specifies the name of the symbol for functions or statics @@ -273,6 +275,7 @@ The following is an index of all built-in attributes. added in future. - Debugger - [`debugger_visualizer`] — Embeds a file that specifies debugger output for a type. + - [`collapse_debuginfo`] — Controls how macro invocations are encoded in debuginfo. [Doc comments]: comments.md#doc-comments [ECMA-334]: https://www.ecma-international.org/publications-and-standards/standards/ecma-334/ @@ -291,6 +294,7 @@ The following is an index of all built-in attributes. [`cfg_attr`]: conditional-compilation.md#the-cfg_attr-attribute [`cfg`]: conditional-compilation.md#the-cfg-attribute [`cold`]: attributes/codegen.md#the-cold-attribute +[`collapse_debuginfo`]: attributes/debugger.md#the-collapse_debuginfo-attribute [`crate_name`]: crates-and-source-files.md#the-crate_name-attribute [`crate_type`]: linkage.md [`debugger_visualizer`]: attributes/debugger.md#the-debugger_visualizer-attribute @@ -352,3 +356,4 @@ The following is an index of all built-in attributes. [closure]: expressions/closure-expr.md [function pointer]: types/function-pointer.md [variadic functions]: items/external-blocks.html#variadic-functions +[`diagnostic::on_unimplemented`]: attributes/diagnostics.md#the-diagnosticon_unimplemented-attribute diff --git a/src/attributes/codegen.md b/src/attributes/codegen.md index 348f92f37..195df2f47 100644 --- a/src/attributes/codegen.md +++ b/src/attributes/codegen.md @@ -262,7 +262,7 @@ Feature | Implicitly Enables | Description [rv-zks]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zks.adoc [rv-zksed]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zksed.adoc [rv-zksh]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zksh.adoc -[rv-zkt]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zkr.adoc +[rv-zkt]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zkt.adoc #### `wasm32` or `wasm64` @@ -273,10 +273,20 @@ attempting to use instructions unsupported by the Wasm engine will fail at load time without the risk of being interpreted in a way different from what the compiler expected. -Feature | Description -------------|------------------- -`simd128` | [WebAssembly simd proposal][simd128] - +Feature | Description +----------------------|------------------- +`bulk-memory` | [WebAssembly bulk memory operations proposal][bulk-memory] +`extended-const` | [WebAssembly extended const expressions proposal][extended-const] +`mutable-globals` | [WebAssembly mutable global proposal][mutable-globals] +`nontrapping-fptoint` | [WebAssembly non-trapping float-to-int conversion proposal][nontrapping-fptoint] +`sign-ext` | [WebAssembly sign extension operators Proposal][sign-ext] +`simd128` | [WebAssembly simd proposal][simd128] + +[bulk-memory]: https://github.com/WebAssembly/bulk-memory-operations +[extended-const]: https://github.com/WebAssembly/extended-const +[mutable-globals]: https://github.com/WebAssembly/mutable-global +[nontrapping-fptoint]: https://github.com/WebAssembly/nontrapping-float-to-int-conversions +[sign-ext]: https://github.com/WebAssembly/sign-extension-ops [simd128]: https://github.com/webassembly/simd ### Additional information diff --git a/src/attributes/debugger.md b/src/attributes/debugger.md index 6ea80221e..6d184e87e 100644 --- a/src/attributes/debugger.md +++ b/src/attributes/debugger.md @@ -139,3 +139,32 @@ When the crate's debug executable is passed into GDB[^rust-gdb], `print bob` wil [Natvis documentation]: https://docs.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects [pretty printing documentation]: https://sourceware.org/gdb/onlinedocs/gdb/Pretty-Printing.html [_MetaListNameValueStr_]: ../attributes.md#meta-item-attribute-syntax + +## The `collapse_debuginfo` attribute + +The *`collapse_debuginfo` [attribute]* controls whether code locations from a macro definition are collapsed into a single location associated with the macro's call site, +when generating debuginfo for code calling this macro. + +The attribute uses the [_MetaListIdents_] syntax to specify its inputs, and can only be applied to macro definitions. + +Accepted options: +- `#[collapse_debuginfo(yes)]` — code locations in debuginfo are collapsed. +- `#[collapse_debuginfo(no)]` — code locations in debuginfo are not collapsed. +- `#[collapse_debuginfo(external)]` — code locations in debuginfo are collapsed only if the macro comes from a different crate. + +The `external` behavior is the default for macros that don't have this attribute, unless they are built-in macros. +For built-in macros the default is `yes`. + +> **Note**: `rustc` has a `-C collapse-macro-debuginfo` CLI option to override both the default collapsing behavior and `#[collapse_debuginfo]` attributes. + +```rust +#[collapse_debuginfo(yes)] +macro_rules! example { + () => { + println!("hello!"); + }; +} +``` + +[attribute]: ../attributes.md +[_MetaListIdents_]: ../attributes.md#meta-item-attribute-syntax diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index 506e2848b..c636a96cc 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -301,6 +301,76 @@ When used on a function in a trait implementation, the attribute does nothing. > let _ = five(); > ``` +## The `diagnostic` tool attribute namespace + +The `#[diagnostic]` attribute namespace is a home for attributes to influence compile-time error messages. +The hints provided by these attributes are not guaranteed to be used. +Unknown attributes in this namespace are accepted, though they may emit warnings for unused attributes. +Additionally, invalid inputs to known attributes will typically be a warning (see the attribute definitions for details). +This is meant to allow adding or discarding attributes and changing inputs in the future to allow changes without the need to keep the non-meaningful attributes or options working. + +### The `diagnostic::on_unimplemented` attribute + +The `#[diagnostic::on_unimplemented]` attribute is a hint to the compiler to supplement the error message that would normally be generated in scenarios where a trait is required but not implemented on a type. +The attribute should be placed on a [trait declaration], though it is not an error to be located in other positions. +The attribute uses the [_MetaListNameValueStr_] syntax to specify its inputs, though any malformed input to the attribute is not considered as an error to provide both forwards and backwards compatibility. +The following keys have the given meaning: + +* `message` — The text for the top level error message. +* `label` — The text for the label shown inline in the broken code in the error message. +* `note` — Provides additional notes. + +The `note` option can appear several times, which results in several note messages being emitted. +If any of the other options appears several times the first occurrence of the relevant option specifies the actually used value. +Any other occurrence generates an lint warning. +For any other non-existing option a lint-warning is generated. + +All three options accept a string as an argument, interpreted using the same formatting as a [`std::fmt`] string. +Format parameters with the given named parameter will be replaced with the following text: + +* `{Self}` — The name of the type implementing the trait. +* `{` *GenericParameterName* `}` — The name of the generic argument's type for the given generic parameter. + +Any other format parameter will generate a warning, but will otherwise be included in the string as-is. + +Invalid format strings may generate a warning, but are otherwise allowed, but may not display as intended. +Format specifiers may generate a warning, but are otherwise ignored. + +In this example: + +```rust,compile_fail,E0277 +#[diagnostic::on_unimplemented( + message = "My Message for `ImportantTrait<{A}>` implemented for `{Self}`", + label = "My Label", + note = "Note 1", + note = "Note 2" +)] +trait ImportantTrait {} + +fn use_my_trait(_: impl ImportantTrait) {} + +fn main() { + use_my_trait(String::new()); +} +``` + +the compiler may generate an error message which looks like this: + +```text +error[E0277]: My Message for `ImportantTrait` implemented for `String` + --> src/main.rs:14:18 + | +14 | use_my_trait(String::new()); + | ------------ ^^^^^^^^^^^^^ My Label + | | + | required by a bound introduced by this call + | + = help: the trait `ImportantTrait` is not implemented for `String` + = note: Note 1 + = note: Note 2 +``` + +[`std::fmt`]: ../../std/fmt/index.html [Clippy]: https://github.com/rust-lang/rust-clippy [_MetaListNameValueStr_]: ../attributes.md#meta-item-attribute-syntax [_MetaListPaths_]: ../attributes.md#meta-item-attribute-syntax diff --git a/src/attributes/type_system.md b/src/attributes/type_system.md index 71b0243a6..dd3ea9874 100644 --- a/src/attributes/type_system.md +++ b/src/attributes/type_system.md @@ -20,6 +20,12 @@ pub struct Config { pub window_height: u16, } +#[non_exhaustive] +pub struct Token; + +#[non_exhaustive] +pub struct Id(pub u64); + #[non_exhaustive] pub enum Error { Message(String), @@ -34,11 +40,13 @@ pub enum Message { // Non-exhaustive structs can be constructed as normal within the defining crate. let config = Config { window_width: 640, window_height: 480 }; +let token = Token; +let id = Id(4); // Non-exhaustive structs can be matched on exhaustively within the defining crate. -if let Config { window_width, window_height } = config { - // ... -} +let Config { window_width, window_height } = config; +let Token = token; +let Id(id_number) = id; let error = Error::Other; let message = Message::Reaction(3); @@ -64,30 +72,49 @@ Non-exhaustive types cannot be constructed outside of the defining crate: - Non-exhaustive variants ([`struct`][struct] or [`enum` variant][enum]) cannot be constructed with a [_StructExpression_] \(including with [functional update syntax]). +- The implicitly defined same-named constant of a [unit-like struct][struct], + or the same-named constructor function of a [tuple struct][struct], + has a [visibility] no greater than `pub(crate)`. + That is, if the struct’s visibility is `pub`, then the constant or constructor’s visibility + is `pub(crate)`, and otherwise the visibility of the two items is the same + (as is the case without `#[non_exhaustive]`). - [`enum`][enum] instances can be constructed. +The following examples of construction do not compile when outside the defining crate: + ```rust,ignore -// `Config`, `Error`, and `Message` are types defined in an upstream crate that have been -// annotated as `#[non_exhaustive]`. -use upstream::{Config, Error, Message}; +// These are types defined in an upstream crate that have been annotated as +// `#[non_exhaustive]`. +use upstream::{Config, Token, Id, Error, Message}; -// Cannot construct an instance of `Config`, if new fields were added in +// Cannot construct an instance of `Config`; if new fields were added in // a new version of `upstream` then this would fail to compile, so it is // disallowed. let config = Config { window_width: 640, window_height: 480 }; -// Can construct an instance of `Error`, new variants being introduced would +// Cannot construct an instance of `Token`; if new fields were added, then +// it would not be a unit-like struct any more, so the same-named constant +// created by it being a unit-like struct is not public outside the crate; +// this code fails to compile. +let token = Token; + +// Cannot construct an instance of `Id`; if new fields were added, then +// its constructor function signature would change, so its constructor +// function is not public outside the crate; this code fails to compile. +let id = Id(5); + +// Can construct an instance of `Error`; new variants being introduced would // not result in this failing to compile. let error = Error::Message("foo".to_string()); -// Cannot construct an instance of `Message::Send` or `Message::Reaction`, +// Cannot construct an instance of `Message::Send` or `Message::Reaction`; // if new fields were added in a new version of `upstream` then this would // fail to compile, so it is disallowed. let message = Message::Send { from: 0, to: 1, contents: "foo".to_string(), }; let message = Message::Reaction(0); -// Cannot construct an instance of `Message::Quit`, if this were converted to +// Cannot construct an instance of `Message::Quit`; if this were converted to // a tuple-variant `upstream` then this would fail to compile. let message = Message::Quit; ``` @@ -95,16 +122,18 @@ let message = Message::Quit; There are limitations when matching on non-exhaustive types outside of the defining crate: - When pattern matching on a non-exhaustive variant ([`struct`][struct] or [`enum` variant][enum]), - a [_StructPattern_] must be used which must include a `..`. Tuple variant constructor visibility - is lowered to `min($vis, pub(crate))`. + a [_StructPattern_] must be used which must include a `..`. A tuple variant's constructor's + [visibility] is reduced to be no greater than `pub(crate)`. - When pattern matching on a non-exhaustive [`enum`][enum], matching on a variant does not contribute towards the exhaustiveness of the arms. +The following examples of matching do not compile when outside the defining crate: + ```rust, ignore -// `Config`, `Error`, and `Message` are types defined in an upstream crate that have been -// annotated as `#[non_exhaustive]`. -use upstream::{Config, Error, Message}; +// These are types defined in an upstream crate that have been annotated as +// `#[non_exhaustive]`. +use upstream::{Config, Token, Id, Error, Message}; // Cannot match on a non-exhaustive enum without including a wildcard arm. match error { @@ -118,6 +147,13 @@ if let Ok(Config { window_width, window_height }) = config { // would compile with: `..` } +// Cannot match a non-exhaustive unit-like or tuple struct except by using +// braced struct syntax with a wildcard. +// This would compile as `let Token { .. } = token;` +let Token = token; +// This would compile as `let Id { 0: id_number, .. } = id;` +let Id(id_number) = id; + match message { // Cannot match on a non-exhaustive struct enum variant without including a wildcard. Message::Send { from, to, contents } => { }, @@ -147,3 +183,4 @@ Non-exhaustive types are always considered inhabited in downstream crates. [enum]: ../items/enumerations.md [functional update syntax]: ../expressions/struct-expr.md#functional-update-syntax [struct]: ../items/structs.md +[visibility]: ../visibility-and-privacy.md diff --git a/src/const_eval.md b/src/const_eval.md index 34e34d703..af8d4862c 100644 --- a/src/const_eval.md +++ b/src/const_eval.md @@ -27,7 +27,7 @@ to be run. * [Tuple expressions]. * [Array expressions]. * [Struct] expressions. -* [Block expressions], including `unsafe` blocks. +* [Block expressions], including `unsafe` and `const` blocks. * [let statements] and thus irrefutable [patterns], including mutable bindings * [assignment expressions] * [compound assignment expressions] @@ -59,6 +59,7 @@ A _const context_ is one of the following: * [statics] * [enum discriminants] * A [const generic argument] +* A [const block] ## Const Functions @@ -106,6 +107,7 @@ Conversely, the following are possible in a const function, but not in a const c [cast]: expressions/operator-expr.md#type-cast-expressions [closure expressions]: expressions/closure-expr.md [comparison]: expressions/operator-expr.md#comparison-operators +[const block]: expressions/block-expr.md#const-blocks [const functions]: items/functions.md#const-functions [const generic argument]: items/generics.md#const-generics [const generic parameters]: items/generics.md#const-generics diff --git a/src/expressions.md b/src/expressions.md index ad4cc5f54..9e10dcea3 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -35,6 +35,7 @@ >    [_OuterAttribute_]\*[†](#expression-attributes)\ >    (\ >          [_BlockExpression_]\ +>       | [_ConstBlockExpression_]\ >       | [_UnsafeBlockExpression_]\ >       | [_LoopExpression_]\ >       | [_IfExpression_]\ @@ -311,6 +312,7 @@ They are never allowed before: [_ClosureExpression_]: expressions/closure-expr.md [_ComparisonExpression_]: expressions/operator-expr.md#comparison-operators [_CompoundAssignmentExpression_]: expressions/operator-expr.md#compound-assignment-expressions +[_ConstBlockExpression_]: expressions/block-expr.md#const-blocks [_ContinueExpression_]: expressions/loop-expr.md#continue-expressions [_FieldExpression_]: expressions/field-expr.md [_GroupedExpression_]: expressions/grouped-expr.md diff --git a/src/expressions/block-expr.md b/src/expressions/block-expr.md index bd9c0a623..890cf856d 100644 --- a/src/expressions/block-expr.md +++ b/src/expressions/block-expr.md @@ -117,6 +117,44 @@ loop { } ``` +## `const` blocks + +> **Syntax**\ +> _ConstBlockExpression_ :\ +>    `const` _BlockExpression_ + +A *const block* is a variant of a block expression which evaluates at compile-time instead of at runtime. + +Const blocks allows you to define a constant value without having to define new [constant items], and thus they are also sometimes referred as *inline consts*. +It also supports type inference so there is no need to specify the type, unlike [constant items]. + +Const blocks have the ability to reference generic parameters in scope, unlike [free][free item] constant items. +They are desugared to associated constant items with generic parameters in scope. +For example, this code: + +```rust +fn foo() -> usize { + const { std::mem::size_of::() + 1 } +} +``` + +is equivalent to: + +```rust +fn foo() -> usize { + { + struct Const(T); + impl Const { + const CONST: usize = std::mem::size_of::() + 1; + } + Const::::CONST + } +} +``` + +This also means that const blocks are treated similarly to associated constants. +For example, they are not guaranteed to be evaluated when the enclosing function is unused. + ## `unsafe` blocks > **Syntax**\ @@ -181,6 +219,8 @@ fn is_unix_platform() -> bool { [array expressions]: array-expr.md [call expressions]: call-expr.md [capture modes]: ../types/closure.md#capture-modes +[constant items]: ../items/constant-items.md +[free item]: ../glossary.md#free-item [function]: ../items/functions.md [inner attributes]: ../attributes.md [method]: ../items/associated-items.md#methods diff --git a/src/input-format.md b/src/input-format.md index 946e6782c..8d921bf8c 100644 --- a/src/input-format.md +++ b/src/input-format.md @@ -21,7 +21,7 @@ Other occurrences of the character `U+000D` (CR) are left in place (they are tre ## Shebang removal -If the remaining sequence begins with the characters `!#`, the characters up to and including the first `U+000A` (LF) are removed from the sequence. +If the remaining sequence begins with the characters `#!`, the characters up to and including the first `U+000A` (LF) are removed from the sequence. For example, the first line of the following file would be ignored: diff --git a/src/macros-by-example.md b/src/macros-by-example.md index a018ab2ae..cb29ceeea 100644 --- a/src/macros-by-example.md +++ b/src/macros-by-example.md @@ -146,6 +146,7 @@ For reasons of backwards compatibility, though `_` [is also an expression][_UnderscoreExpression_], a standalone underscore is not matched by the `expr` fragment specifier. However, `_` is matched by the `expr` fragment specifier when it appears as a subexpression. +For the same reason, a standalone [const block] is not matched but it is matched when appearing as a subexpression. > **Edition Differences**: Starting with the 2021 edition, `pat` fragment-specifiers match top-level or-patterns (that is, they accept [_Pattern_]). > @@ -706,6 +707,7 @@ expansions, taking separators into account. This means: For more detail, see the [formal specification]. +[const block]: expressions/block-expr.md#const-blocks [Hygiene]: #hygiene [IDENTIFIER]: identifiers.md [IDENTIFIER_OR_KEYWORD]: identifiers.md diff --git a/src/patterns.md b/src/patterns.md index c92e2dcda..4e68e0aee 100644 --- a/src/patterns.md +++ b/src/patterns.md @@ -397,6 +397,9 @@ match tuple { >    | _RangeToInclusivePattern_\ >    | _ObsoleteRangePattern_ > +> _RangeExclusivePattern_ :\ +>       _RangePatternBound_ `..` _RangePatternBound_ +> > _RangeInclusivePattern_ :\ >       _RangePatternBound_ `..=` _RangePatternBound_ > @@ -422,10 +425,11 @@ A bound on the left of the sigil is a *lower bound*. A bound on the right is an *upper bound*. A range pattern with both a lower and upper bound will match all values between and including both of its bounds. -It is written as its lower bound, followed by `..=`, followed by its upper bound. +It is written as its lower bound, followed by `..` for end-exclusive or `..=` for end-inclusive, followed by its upper bound. The type of the range pattern is the type unification of its upper and lower bounds. For example, a pattern `'m'..='p'` will match only the values `'m'`, `'n'`, `'o'`, and `'p'`. +Similarly, `'m'..'p'` will match only `'m'`, `'n'` and `'o'`, specifically **not** including `'p'`. The lower bound cannot be greater than the upper bound. That is, in `a..=b`, a ≤ b must be the case. @@ -467,7 +471,7 @@ let valid_variable = match c { # let ph = 10; println!("{}", match ph { - 0..=6 => "acid", + 0..7 => "acid", 7 => "neutral", 8..=14 => "base", _ => unreachable!(), @@ -539,9 +543,6 @@ See [issue #41620](https://github.com/rust-lang/rust/issues/41620) for more info > **Edition Differences**: Before the 2021 edition, range patterns with both a lower and upper bound may also be written using `...` in place of `..=`, with the same meaning. -> **Note**: Although range patterns use the same syntax as [range expressions], there are no exclusive range patterns. -> That is, neither `x .. y` nor `.. x` are valid range patterns. - ## Reference patterns > **Syntax**\ diff --git a/src/procedural-macros.md b/src/procedural-macros.md index 7d69ab72d..32b847c0f 100644 --- a/src/procedural-macros.md +++ b/src/procedural-macros.md @@ -234,8 +234,8 @@ shown in the comments after the function prefixed with "out:". #[proc_macro_attribute] pub fn show_streams(attr: TokenStream, item: TokenStream) -> TokenStream { - println!("attr: \"{}\"", attr.to_string()); - println!("item: \"{}\"", item.to_string()); + println!("attr: \"{attr}\""); + println!("item: \"{item}\""); item } ``` diff --git a/src/special-types-and-traits.md b/src/special-types-and-traits.md index 6355f3fb2..21cab3dc8 100644 --- a/src/special-types-and-traits.md +++ b/src/special-types-and-traits.md @@ -80,6 +80,7 @@ types: * Types with a built-in `Copy` implementation (see above) * [Tuples] of `Clone` types +* [Closures] that only capture values of `Clone` types or capture no values from the environment ## `Send` diff --git a/src/type-layout.md b/src/type-layout.md index d338eb7bc..c53e9d097 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -44,17 +44,20 @@ The size of most primitives is given in this table. | `u32` / `i32` | 4 | | `u64` / `i64` | 8 | | `u128` / `i128` | 16 | +| `usize` / `isize` | See below | | `f32` | 4 | | `f64` | 8 | | `char` | 4 | `usize` and `isize` have a size big enough to contain every address on the -target platform. For example, on a 32 bit target, this is 4 bytes and on a 64 +target platform. For example, on a 32 bit target, this is 4 bytes, and on a 64 bit target, this is 8 bytes. -Most primitives are generally aligned to their size, although this is -platform-specific behavior. In particular, on x86 u64 and f64 are only -aligned to 32 bits. +The alignment of primitives is platform-specific. +In most cases, their alignment is equal to their size, but it may be less. +In particular, `i128` and `u128` are often aligned to 4 or 8 bytes even though +their size is 16, and on many 32-bit platforms, `i64`, `u64`, and `f64` are only +aligned to 4 bytes, not 8. ## Pointers and References Layout