The derived implementation of `partial_cmp` compares matching fields one
by one, stopping the computation when the result of a comparison is not
equal to `Some(Equal)`.
On the other hand the derived implementation for `lt`, `le`, `gt` and
`ge` continues the computation when the result of a field comparison is
`None`, consequently those operators are not transitive and inconsistent
with `partial_cmp`.
Fix the inconsistency by using the default implementation that fall-backs
to the `partial_cmp`. This also avoids creating very deeply nested
closures that were quite costly to compile.
These functions have a ton of generic parameters and are instantiated
over and over again. Hopefully this will reduce binary bloat and speed
up bootstrapping times.
parse_format: treat r" as a literal
This PR changes `format_args!` internal parsing machinery to treat raw strings starting `r"` as a literal.
Currently `"` and `r#` are recognised as valid starting combinations for string literals, but `r"` is not.
This was noticed when debugging https://github.com/rust-lang/rust/issues/67984#issuecomment-753413156
As well as fixing the behavior observed in that comment, this improves diagnostic spans for `r"` formatting strings.
improve error message for disallowed ptr-to-int casts in const eval
Improves an error message as [suggested](https://github.com/rust-lang/rust/issues/80875#issuecomment-762754580) in #80875.
Does the wording make enough sense? I tried to follow precedent for error message style while maintaining brevity.
It seems like the rest of the `ConstEvalErrKind::NeedsRfc` error messages could be improved as well. I could give that a go if this approach works.
Closes#80875
faster few span methods
Touched few methods, so it should be (hopefully) faster.
First two changes: instead splitting string from start and taking only last piece, split it from the end.
Last: swapped conditions, to first check boolean parameter.
libtest: allow multiple filters
Libtest ignores any filters after the first. This changes it so that if multiple filters are passed, it will test against all of them.
This also affects compiletest to do the same.
Closes#30422
BTree: remove Ord bound where it is absent elsewhere
Some btree methods don't really need an Ord bound and don't have one, while some methods that more obviously don't need it, do have one.
An example of the former is `iter`, even though it explicitly exposes the work of the Ord implementation (["sorted by key"](https://doc.rust-lang.org/std/collections/struct.BTreeMap.html#method.iter) - but I'm not suggesting it should have the Ord bound). An example of the latter is `new`, which doesn't involve any keys whatsoever.
The panic happens when in recovery parsing a full `impl`
(`parse_item_impl`) fails and we drop the `DiagnosticBuilder` for the
recovery suggestion and return the `parse_item_impl` error.
We now raise the original error "expected identifier found `impl`" when
parsing the `impl` fails.
Note that the regression test is slightly simplified version of the
original repro in #81806, to make the error output smaller and more
resilient to unrelated changes in parser error messages.
Fixes#81806
Stabilize remaining integer methods as `const fn`
This pull request stabilizes the following methods as `const fn`:
- `i*::checked_div`
- `i*::checked_div_euclid`
- `i*::checked_rem`
- `i*::checked_rem_euclid`
- `i*::div_euclid`
- `i*::overflowing_div`
- `i*::overflowing_div_euclid`
- `i*::overflowing_rem`
- `i*::overflowing_rem_euclid`
- `i*::rem_euclid`
- `i*::wrapping_div`
- `i*::wrapping_div_euclid`
- `i*::wrapping_rem`
- `i*::wrapping_rem_euclid`
- `u*::checked_div`
- `u*::checked_div_euclid`
- `u*::checked_rem`
- `u*::checked_rem_euclid`
- `u*::div_euclid`
- `u*::overflowing_div`
- `u*::overflowing_div_euclid`
- `u*::overflowing_rem`
- `u*::overflowing_rem_euclid`
- `u*::rem_euclid`
- `u*::wrapping_div`
- `u*::wrapping_div_euclid`
- `u*::wrapping_rem`
- `u*::wrapping_rem_euclid`
These can all be implemented on the current stable (1.49). There are two unstable details: const likely/unlikely and unchecked division/remainder. Both of these are for optimizations, and are in no way required to make the methods function; there is no exposure of these details publicly. Per comments below, it seems best practice is to stabilize the intrinsics. As such, `intrinsics::unchecked_div` and `intrinsics::unchecked_rem` have been stabilized as `const` as part of this pull request as well. The methods themselves remain unstable.
I believe part of the reason these were not stabilized previously was the behavior around division by 0 and modulo 0. After testing on nightly, the diagnostic for something like `const _: i8 = 5i8 % 0i8;` is similar to that of `const _: i8 = 5i8.rem_euclid(0i8);` (assuming the appropriate feature flag is enabled). As such, I believe these methods are ready to be stabilized as `const fn`.
This pull request represents the final methods mentioned in #53718. As such, this PR closes#53718.
`@rustbot` modify labels to +A-const-fn, +T-libs
Implement `--extern-location`
This PR implements `--extern-location` as a followup to #72342 as part of the implementation of #57274. The goal of this PR is to allow rustc, in coordination with the build system, to present a useful diagnostic about how to remove an unnecessary dependency from a dependency specification file (eg Cargo.toml).
EDIT: Updated to current PR state.
The location is specified for each named crate - that is, for a given `--extern foo[=path]` there can also be `--extern-location foo=<location>`. It supports ~~three~~ two styles of location:
~~1. `--extern-location foo=file:<path>:<line>` - a file path and line specification
1. `--extern-location foo=span:<path>:<start>:<end>` - a span specified as a file and start and end byte offsets~~
1. `--extern-location foo=raw:<anything>` - a raw string which is included in the output
1. `--extern-location foo=json:<anything>` - an arbitrary Json structure which is emitted via Json diagnostics in a `tool_metadata` field.
~~1 & 2 are turned into an internal `Span`, so long as the path exists and is readable, and the location is meaningful (within the file, etc). This is used as the `Span` for a fix suggestion which is reported like other fix suggestions.~~
`raw` and `json` are for the case where the location isn't best expressed as a file and location within that file. For example, it could be a rule name and the name of a dependency within that rule. `rustc` makes no attempt to parse the raw string, and simply includes it in the output diagnostic text. `json` is only included in json diagnostics. `raw` is emitted as text and also as a json string in `tool_metadata`.
If no `--extern-location` option is specified then it will emit a default json structure consisting of `{"name": name, "path": path}` corresponding to the name and path in `--extern name=path`.
This is a prototype/RFC to make some of the earlier conversations more concrete. It doesn't stand on its own - it's only useful if implemented by Cargo and other build systems. There's also a ton of implementation details which I'd appreciate a second eye on as well.
~~**NOTE** The first commit in this PR is #72342 and should be ignored for the purposes of review. The first commit is a very simplistic implementation which is basically raw-only, presented as a MVP. The second implements the full thing, and subsequent commits are incremental fixes.~~
cc `@ehuss` `@est31` `@petrochenkov` `@estebank`
...so we can skip serializing `tool_metadata` if it hasn't been set.
This makes the output a bit cleaner, and avoiding having to update a
bunch of unrelated tests.
This allows a build system to indicate a location in its own dependency
specification files (eg Cargo's `Cargo.toml`) which can be reported
along side any unused crate dependency.
This supports several types of location:
- 'json' - provide some json-structured data, which is included in the json diagnostics
in a `tool_metadata` field
- 'raw' - emit the provided string into the output. This also appears as a json string in
`tool_metadata`.
If no `--extern-location` is explicitly provided then a default json entry of the form
`"tool_metadata":{"name":<cratename>,"path":<cratepath>}` is emitted.
Improve SIMD type element count validation
Resolvesrust-lang/stdsimd#53.
These changes are motivated by `stdsimd` moving in the direction of const generic vectors, e.g.:
```rust
#[repr(simd)]
struct SimdF32<const N: usize>([f32; N]);
```
This makes a few changes:
* Establishes a maximum SIMD lane count of 2^16 (65536). This value is arbitrary, but attempts to validate lane count before hitting potential errors in the backend. It's not clear what LLVM's maximum lane count is, but cranelift's appears to be much less than `usize::MAX`, at least.
* Expands some SIMD intrinsics to support arbitrary lane counts. This resolves the ICE in the linked issue.
* Attempts to catch invalid-sized vectors during typeck when possible.
Unresolved questions:
* Generic-length vectors can't be validated in typeck and are only validated after monomorphization while computing layout. This "works", but the errors simply bail out with no context beyond the name of the type. Should these errors instead return `LayoutError` or otherwise provide context in some way? As it stands, users of `stdsimd` could trivially produce monomorphization errors by making zero-length vectors.
cc `@bjorn3`
Reuse as much memory as possible, reduce number of allocations.
Use BitSet instead of a HashMap, since only a single bit of
information was used as the map's value.
expand/resolve: Turn `#[derive]` into a regular macro attribute
This PR turns `#[derive]` into a regular attribute macro declared in libcore and defined in `rustc_builtin_macros`, like it was previously done with other "active" attributes in https://github.com/rust-lang/rust/pull/62086, https://github.com/rust-lang/rust/pull/62735 and other PRs.
This PR is also a continuation of #65252, #69870 and other PRs linked from them, which layed the ground for converting `#[derive]` specifically.
`#[derive]` still asks `rustc_resolve` to resolve paths inside `derive(...)`, and `rustc_expand` gets those resolution results through some backdoor (which I'll try to address later), but otherwise `#[derive]` is treated as any other macro attributes, which simplifies the resolution-expansion infra pretty significantly.
The change has several observable effects on language and library.
Some of the language changes are **feature-gated** by [`feature(macro_attributes_in_derive_output)`](https://github.com/rust-lang/rust/issues/81119).
#### Library
- `derive` is now available through standard library as `{core,std}::prelude::v1::derive`.
#### Language
- `derive` now goes through name resolution, so it can now be renamed - `use derive as my_derive; #[my_derive(Debug)] struct S;`.
- `derive` now goes through name resolution, so this resolution can fail in corner cases. Crater found one such regression, where import `use foo as derive` goes into a cycle with `#[derive(Something)]`.
- **[feature-gated]** `#[derive]` is now expanded as any other attributes in left-to-right order. This allows to remove the restriction on other macro attributes following `#[derive]` (https://github.com/rust-lang/reference/issues/566). The following macro attributes become a part of the derive's input (this is not a change, non-macro attributes following `#[derive]` were treated in the same way previously).
- `#[derive]` is now expanded as any other attributes in left-to-right order. This means two derive attributes `#[derive(Foo)] #[derive(Bar)]` are now expanded separately rather than together. It doesn't generally make difference, except for esoteric cases. For example `#[derive(Foo)]` can now produce an import bringing `Bar` into scope, but previously both `Foo` and `Bar` were required to be resolved before expanding any of them.
- **[feature-gated]** `#[derive()]` (with empty list in parentheses) actually becomes useful. For historical reasons `#[derive]` *fully configures* its input, eagerly evaluating `cfg` everywhere in its target, for example on fields.
Expansion infra doesn't do that for other attributes, but now when macro attributes attributes are allowed to be written after `#[derive]`, it means that derive can *fully configure* items for them.
```rust
#[derive()]
#[my_attr]
struct S {
#[cfg(FALSE)] // this field in removed by `#[derive()]` and not observed by `#[my_attr]`
field: u8
}
```
- `#[derive]` on some non-item targets is now prohibited. This was accidentally allowed as noop in the past, but was warned about since early 2018 (#50092), despite that crater found a few such cases in unmaintained crates.
- Derive helper attributes used before their introduction are now reported with a deprecation lint. This change is long overdue (since macro modularization, https://github.com/rust-lang/rust/issues/52226#issuecomment-422605033), but it was hard to do without fixing expansion order for derives. The deprecation is tracked by #79202.
```rust
#[trait_helper] // warning: derive helper attribute is used before it is introduced
#[derive(Trait)]
struct S {}
```
Crater analysis: https://github.com/rust-lang/rust/pull/79078#issuecomment-731436821
Identify unreachable subpatterns more reliably
In https://github.com/rust-lang/rust/pull/80104 I used `Span`s to identify unreachable sub-patterns in the presence of or-patterns during exhaustiveness checking. In https://github.com/rust-lang/rust/issues/80501 it was revealed that `Span`s are complicated and that this was not a good idea.
Instead, this PR identifies subpatterns logically: as a path in the tree of subpatterns of a given pattern. I made a struct that captures a set of such subpatterns. This is a bit complex, but thankfully self-contained; the rest of the code does not need to know anything about it.
Fixes https://github.com/rust-lang/rust/issues/80501. I think I managed to keep the perf neutral.
r? `@varkor`