align_offset, align_to: no longer allow implementations to spuriously fail to align
For a long time, we have allowed `align_offset` to fail to compute a properly aligned offset, and `align_to` to return a smaller-than-maximal "middle slice". This was done to cover the implementation of `align_offset` in const-eval and Miri. See https://github.com/rust-lang/rust/issues/62420 for more background. For about the same amount of time, this has caused confusion and surprise, where people didn't realize they have to write their code to be defensive against `align_offset` failures.
Another way to put this is: the specification is effectively non-deterministic, and non-determinism is hard to test for -- in particular if the implementation everyone uses to test always produces the same reliable result, and nobody expects it to be non-deterministic to begin with.
With https://github.com/rust-lang/rust/pull/117840, Miri has stopped making use of this liberty in the spec; it now always behaves like rustc. That only leaves const-eval as potential motivation for this behavior. I do not think this is sufficient motivation. Currently, none of the relevant functions are stably const: `align_offset` is unstably const, `align_to` is not const at all. I propose that if we ever want to make these const-stable, we just accept the fact that they can behave differently at compile-time vs at run-time. This is not the end of the world, and it seems to be much less surprising to programmers than unexpected non-determinism. (Related: https://github.com/rust-lang/rfcs/pull/3352.)
`@thomcc` has repeatedly made it clear that they strongly dislike the non-determinism in align_offset, so I expect they will support this. `@oli-obk,` what do you think? Also, whom else should we involve? The primary team responsible is clearly libs-api, so I will nominate this for them. However, allowing const-evaluated code to behave different from run-time code is t-lang territory. The thing is, this is not stabilizing anything t-lang-worthy immediately, but it still does make a decision we will be bound to: if we accept this change, then
- either `align_offset`/`align_to` can never be called in const fn,
- or we allow compile-time behavior to differ from run-time behavior.
So I will nominate for t-lang as well, with the question being: are you okay with accepting either of these outcomes (without committing to which one, just accepting that it has to be one of them)? This closes the door to "have `align_offset` and `align_to` at compile-time and also always have compile-time behavior match run-time behavior".
Closes https://github.com/rust-lang/rust/issues/62420
Stabilize the `#[diagnostic]` namespace and `#[diagnostic::on_unimplemented]` attribute
This PR stabilizes the `#[diagnostic]` attribute namespace and a minimal option of the `#[diagnostic::on_unimplemented]` attribute.
The `#[diagnostic]` attribute namespace is meant to provide a home for attributes that allow users to influence error messages emitted by the compiler. The compiler is not guaranteed to use any of this hints, however it should accept any (non-)existing attribute in this namespace and potentially emit lint-warnings for unused attributes and options. This is meant to allow discarding certain attributes/options in the future to allow fundamental changes to the compiler without the need to keep then non-meaningful options working.
The `#[diagnostic::on_unimplemented]` attribute is allowed to appear on a trait definition. This allows crate authors to hint the compiler to emit a specific error message if a certain trait is not implemented. For the `#[diagnostic::on_unimplemented]` attribute the following options are implemented:
* `message` which provides the text for the top level error message
* `label` which provides the text for the label shown inline in the broken code in the error message
* `note` which 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 text as argument. This text is allowed to contain format parameters referring to generic argument or `Self` by name via the `{Self}` or `{NameOfGenericArgument}` syntax. For any non-existing argument a lint warning is generated.
This allows to have a trait definition like:
```rust
#[diagnostic::on_unimplemented(
message = "My Message for `ImportantTrait<{A}>` is not implemented for `{Self}`",
label = "My Label",
note = "Note 1",
note = "Note 2"
)]
trait ImportantTrait<A> {}
```
which then generates for the following code
```rust
fn use_my_trait(_: impl ImportantTrait<i32>) {}
fn main() {
use_my_trait(String::new());
}
```
this error message:
```
error[E0277]: My Message for `ImportantTrait<i32>` is not 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<i32>` is not implemented for `String`
= note: Note 1
= note: Note 2
```
[Playground with the unstable feature](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=05133acce8e1d163d481e97631f17536)
Fixes#111996
Rollup of 9 pull requests
Successful merges:
- #121958 (Fix redundant import errors for preload extern crate)
- #121976 (Add an option to have an external download/bootstrap cache)
- #122022 (loongarch: add frecipe and relax target feature)
- #122026 (Do not try to format removed files)
- #122027 (Uplift some feeding out of `associated_type_for_impl_trait_in_impl` and into queries)
- #122063 (Make the lowering of `thir::ExprKind::If` easier to follow)
- #122074 (Add missing PartialOrd trait implementation doc for array)
- #122082 (remove outdated fixme comment)
- #122091 (Note why we're using a new thread in `test_get_os_named_thread`)
r? `@ghost`
`@rustbot` modify labels: rollup
const_eval_select: make it safe but be careful with what we expose on stable for now
As this is all still nightly-only I think `````@rust-lang/wg-const-eval````` can do that without involving t-lang.
r? `````@oli-obk`````
Cc `````@Nilstrieb````` -- the updated version of your RFC would basically say that we can remove these comments about not making behavior differences visible in stable `const fn`
Add basic i18n guidance for `Display`
I've tried to be relatively noncommittal here. The part I think is most important is to mention the concept of "display adapters" *somewhere* in the `std::fmt` documentation that has some chance of being discovered when people go looking for ways to provide context when `Display`ing their type.
Rendered:
> ### Internationalization
>
> Because a type can only have one `Display` implementation, it is often preferable to only implement `Display` when there is a single most "obvious" way that values can be formatted as text. This could mean formatting according to the "invariant" culture and "undefined" locale, or it could mean that the type display is designed for a specific culture/locale, such as developer logs.
>
> If not all values have a justifiably canonical textual format or if you want to support alternative formats not covered by the standard set of possible [formatting traits], the most flexible approach is display adapters: methods like [`str::escape_default`] or [`Path::display`] which create a wrapper implementing `Display` to output the specific display format.
>
> [formatting traits]: https://doc.rust-lang.org/nightly/std/fmt/index.html#formatting-traits
> [`str::escape_default`]: https://doc.rust-lang.org/nightly/std/primitive.str.html#method.escape_default
> [`Path::display`]: https://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.display
The module docs do already have a [localization header](https://doc.rust-lang.org/nightly/std/fmt/index.html#localization), so maybe this header should be l10n instead of i18n, or maybe this information should live under that header? I'm not sure, but here on the `Display` trait at least isn't a *bad* spot to put it.
The other side of this that comes up a lot is `FromStr` compatibility, but that's for a different PR.
net: Don't use checked arithmetic when parsing numbers with known max digits
Add a branch to `Parser::read_number` that determines whether checked or regular arithmetic is used.
- If `max_digits.is_some()`, then we know we are parsing a `u8` or `u16` because `read_number` is only called with `Some(3)` or `Some(4)`. Both types fit within a `u32` without risk of overflow. Thus, we can use plain arithmetic to avoid extra instructions from `checked_mul` and `checked_add`.
Add benches for `IpAddr`, `Ipv4Addr`, `Ipv6Addr`, `SocketAddr`, `SocketAddrV4`, and `SocketAddrV6` parsing
Add ASCII fast-path for `char::is_grapheme_extended`
I discovered that `impl Debug for str` is quite slow because it ends up doing a `unicode_data::grapheme_extend::lookup` for each char, which ends up doing a binary search.
This introduces a fast-path for ASCII chars which do not have this property.
The `lookup` is thus completely gone from profiles.
---
As a followup, maybe it’s worth implementing this fast path directly in `unicode_data` so that it can check for the lower bound directly before going to a potentially expensive binary search.
Rollup of 10 pull requests
Successful merges:
- #121213 (Add an example to demonstrate how Rc::into_inner works)
- #121262 (Add vector time complexity)
- #121287 (Clarify/add `must_use` message for Rc/Arc/Weak::into_raw.)
- #121664 (Adjust error `yield`/`await` lowering)
- #121826 (Use root obligation on E0277 for some cases)
- #121838 (Use the correct logic for nested impl trait in assoc types)
- #121913 (Don't panic when waiting on poisoned queries)
- #121987 (pattern analysis: abort on arity mismatch)
- #121993 (Avoid using unnecessary queries when printing the query stack in panics)
- #121997 (interpret/cast: make more matches on FloatTy properly exhaustive)
r? `@ghost`
`@rustbot` modify labels: rollup
Use root obligation on E0277 for some cases
When encountering trait bound errors that satisfy some heuristics that tell us that the relevant trait for the user comes from the root obligation and not the current obligation, we use the root predicate for the main message.
This allows to talk about "X doesn't implement Pattern<'_>" over the most specific case that just happened to fail, like "char doesn't implement Fn(&mut char)" in
`tests/ui/traits/suggest-dereferences/root-obligation.rs`
The heuristics are:
- the type of the leaf predicate is (roughly) the same as the type from the root predicate, as a proxy for "we care about the root"
- the leaf trait and the root trait are different, so as to avoid talking about `&mut T: Trait` and instead remain talking about `T: Trait` instead
- the root trait is not `Unsize`, as to avoid talking about it in `tests/ui/coercion/coerce-issue-49593-box-never.rs`.
```
error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied
--> $DIR/root-obligation.rs:6:38
|
LL | .filter(|c| "aeiou".contains(c))
| -------- ^ the trait `Fn<(char,)>` is not implemented for `&char`, which is required by `&char: Pattern<'_>`
| |
| required by a bound introduced by this call
|
= note: required for `&char` to implement `FnOnce<(char,)>`
= note: required for `&char` to implement `Pattern<'_>`
note: required by a bound in `core::str::<impl str>::contains`
--> $SRC_DIR/core/src/str/mod.rs:LL:COL
help: consider dereferencing here
|
LL | .filter(|c| "aeiou".contains(*c))
| +
```
Fix#79359, fix#119983, fix#118779, cc #118415 (the suggestion needs to change), cc #121398 (doesn't fix the underlying issue).
perf: improve write_fmt to handle simple strings
In case format string has no arguments, simplify its implementation with a direct call to `output.write_str(value)`. This builds on `@dtolnay` original [suggestion](https://github.com/serde-rs/serde/pull/2697#issuecomment-1940376414). This does not change any expectations because the original `fn write()` implementation calls `write_str` for parts of the format string.
```rust
write!(f, "text") -> f.write_str("text")
```
```diff
/// [`write!`]: crate::write!
+#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
+ if let Some(s) = args.as_str() { output.write_str(s) } else { write_internal(output, args) }
+}
+
+/// Actual implementation of the [`write`], but without the simple string optimization.
+fn write_internal(output: &mut dyn Write, args: Arguments<'_>) -> Result {
let mut formatter = Formatter::new(output);
let mut idx = 0;
```
* Hopefully it will improve the simple case for the https://github.com/rust-lang/rust/issues/99012
* Another related (original?) issues #10761
* Previous similar attempt to fix it by by `@Kobzol` #100700
CC: `@m-ou-se` as probably the biggest expert in everything `format!`
Add a scheme for moving away from `extern "rust-intrinsic"` entirely
All `rust-intrinsic`s can become free functions now, either with a fallback body, or with a dummy body and an attribute, requiring backends to actually implement the intrinsic.
This PR demonstrates the dummy-body scheme with the `vtable_size` intrinsic.
cc https://github.com/rust-lang/rust/issues/63585
follow-up to #120500
MCP at https://github.com/rust-lang/compiler-team/issues/720
arithmetic
If `max_digits.is_some()`, then we know we are parsing a `u8` or `u16`
because `read_number` is only called with `Some(3)` or `Some(4)`. Both
types fit well within a `u32` without risk of overflow. Thus, we can use
plain arithmetic to avoid extra instructions from `checked_mul` and
`checked_add`.
Doc: Fix incorrect reference to integer in Atomic{Ptr,Bool}::as_ptr.
I am assuming "resulting integer" is an error, since we are talking about pointers and booleans here. Seems like it was missed while copy & pasting the docs from the integer versions. I also checked the rest of the docs, and this was the only mention of integers.
Improve assert_matches! documentation
This new documentation tries to limit the impact of the conceptual pitfall, that the if guard relaxes the constraint, when really it tightens it. This is achieved by changing the text and examples. The previous documentation also chose a rather weird and non-representative example for the if guard, that made it needlessly complicated to understand.
```
error[E0599]: no method named `map` found for struct `Vec<bool>` in the current scope
--> $DIR/vec-on-unimplemented.rs:3:23
|
LL | vec![true, false].map(|v| !v).collect::<Vec<_>>();
| ^^^ `Vec<bool>` is not an iterator
|
help: call `.into_iter()` first
|
LL | vec![true, false].into_iter().map(|v| !v).collect::<Vec<_>>();
| ++++++++++++
```
We used to provide some help through `rustc_on_unimplemented` on non-`impl Trait` and non-type-params, but this lets us get rid of some otherwise unnecessary conditions in the annotation on `Iterator`.
When encountering trait bound errors that satisfy some heuristics that
tell us that the relevant trait for the user comes from the root
obligation and not the current obligation, we use the root predicate for
the main message.
This allows to talk about "X doesn't implement Pattern<'_>" over the
most specific case that just happened to fail, like "char doesn't
implement Fn(&mut char)" in
`tests/ui/traits/suggest-dereferences/root-obligation.rs`
The heuristics are:
- the type of the leaf predicate is (roughly) the same as the type
from the root predicate, as a proxy for "we care about the root"
- the leaf trait and the root trait are different, so as to avoid
talking about `&mut T: Trait` and instead remain talking about
`T: Trait` instead
- the root trait is not `Unsize`, as to avoid talking about it in
`tests/ui/coercion/coerce-issue-49593-box-never.rs`.
```
error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied
--> $DIR/root-obligation.rs:6:38
|
LL | .filter(|c| "aeiou".contains(c))
| -------- ^ the trait `Fn<(char,)>` is not implemented for `&char`, which is required by `&char: Pattern<'_>`
| |
| required by a bound introduced by this call
|
= note: required for `&char` to implement `FnOnce<(char,)>`
= note: required for `&char` to implement `Pattern<'_>`
note: required by a bound in `core::str::<impl str>::contains`
--> $SRC_DIR/core/src/str/mod.rs:LL:COL
help: consider dereferencing here
|
LL | .filter(|c| "aeiou".contains(*c))
| +
```
Fix#79359, fix#119983, fix#118779, cc #118415 (the suggestion needs
to change).
Clarify behavior of slice prefix/suffix operations in case of equality
Operations such as starts_with, ends_with, strip_prefix and strip_suffix can be either strict (do not consider a slice to be a prefix/suffix of itself) or not. In Rust's case, they are not strict. Add a few phrases to the documentation to clarify this.
Add proper cfg to keep only one AlignmentEnum definition for different target_pointer_widths
Detected by #121752
Only one AlignmentEnum would be used with a specified target_pointer_width
Safe Transmute: Revise safety analysis
This PR migrates `BikeshedIntrinsicFrom` to a simplified safety analysis (described [here](https://github.com/rust-lang/project-safe-transmute/issues/15)) that does not rely on analyzing the visibility of types and fields.
The revised analysis treats primitive types as safe, and user-defined types as potentially carrying safety invariants. If Rust gains explicit (un)safe fields, this PR is structured so that it will be fairly easy to thread support for those annotations into the analysis.
Notably, this PR removes the `Context` type parameter from `BikeshedIntrinsicFrom`. Most of the files changed by this PR are just UI tests tweaked to accommodate the removed parameter.
r? `@compiler-errors`