Auto merge of #129464 - GuillaumeGomez:rollup-ckfqd7h, r=GuillaumeGomez
Rollup of 9 pull requests Successful merges: - #128511 (Document WebAssembly target feature expectations) - #129243 (do not build `cargo-miri` by default on stable channel) - #129263 (Add a missing compatibility note in the 1.80.0 release notes) - #129276 (Stabilize feature `char_indices_offset`) - #129350 (adapt integer comparison tests for LLVM 20 IR changes) - #129408 (Fix handling of macro arguments within the `dropping_copy_types` lint) - #129426 (rustdoc-search: use tighter json for names and parents) - #129437 (Fix typo in a help diagnostic) - #129457 (kobzol vacation) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
a60a9e567a
22 changed files with 375 additions and 45 deletions
|
@ -143,6 +143,8 @@ Compatibility Notes
|
||||||
- [Turn `proc_macro_back_compat` lint into a hard error.](https://github.com/rust-lang/rust/pull/125596/)
|
- [Turn `proc_macro_back_compat` lint into a hard error.](https://github.com/rust-lang/rust/pull/125596/)
|
||||||
- [Detect unused structs even when implementing private traits](https://github.com/rust-lang/rust/pull/122382/)
|
- [Detect unused structs even when implementing private traits](https://github.com/rust-lang/rust/pull/122382/)
|
||||||
- [`std::sync::ReentrantLockGuard<T>` is no longer `Sync` if `T: !Sync`](https://github.com/rust-lang/rust/pull/125527) which means [`std::io::StdoutLock` and `std::io::StderrLock` are no longer Sync](https://github.com/rust-lang/rust/issues/127340)
|
- [`std::sync::ReentrantLockGuard<T>` is no longer `Sync` if `T: !Sync`](https://github.com/rust-lang/rust/pull/125527) which means [`std::io::StdoutLock` and `std::io::StderrLock` are no longer Sync](https://github.com/rust-lang/rust/issues/127340)
|
||||||
|
- [Type inference will fail in some cases due to new implementations of `FromIterator for Box<str>`.](https://github.com/rust-lang/rust/pull/99969/)
|
||||||
|
Notably, this breaks versions of the `time` crate before 0.3.35, due to no longer inferring the implementation for `Box<[_]>`.
|
||||||
|
|
||||||
<a id="1.80-Internal-Changes"></a>
|
<a id="1.80-Internal-Changes"></a>
|
||||||
|
|
||||||
|
|
|
@ -151,10 +151,11 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless {
|
||||||
&& let Node::Stmt(stmt) = node
|
&& let Node::Stmt(stmt) = node
|
||||||
&& let StmtKind::Semi(e) = stmt.kind
|
&& let StmtKind::Semi(e) = stmt.kind
|
||||||
&& e.hir_id == expr.hir_id
|
&& e.hir_id == expr.hir_id
|
||||||
|
&& let Some(arg_span) = arg.span.find_ancestor_inside(expr.span)
|
||||||
{
|
{
|
||||||
UseLetUnderscoreIgnoreSuggestion::Suggestion {
|
UseLetUnderscoreIgnoreSuggestion::Suggestion {
|
||||||
start_span: expr.span.shrink_to_lo().until(arg.span),
|
start_span: expr.span.shrink_to_lo().until(arg_span),
|
||||||
end_span: arg.span.shrink_to_hi().until(expr.span.shrink_to_hi()),
|
end_span: arg_span.shrink_to_hi().until(expr.span.shrink_to_hi()),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
UseLetUnderscoreIgnoreSuggestion::Note
|
UseLetUnderscoreIgnoreSuggestion::Note
|
||||||
|
|
|
@ -1693,7 +1693,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
StringPart::highlighted("multiple different versions".to_string()),
|
StringPart::highlighted("multiple different versions".to_string()),
|
||||||
StringPart::normal(" of crate `".to_string()),
|
StringPart::normal(" of crate `".to_string()),
|
||||||
StringPart::highlighted(format!("{name}")),
|
StringPart::highlighted(format!("{name}")),
|
||||||
StringPart::normal("` the your dependency graph".to_string()),
|
StringPart::normal("` in the dependency graph".to_string()),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
let candidates = if impl_candidates.is_empty() {
|
let candidates = if impl_candidates.is_empty() {
|
||||||
|
|
|
@ -337,6 +337,7 @@
|
||||||
# "analysis",
|
# "analysis",
|
||||||
# "src",
|
# "src",
|
||||||
# "wasm-component-ld",
|
# "wasm-component-ld",
|
||||||
|
# "miri", "cargo-miri" # for dev/nightly channels
|
||||||
#]
|
#]
|
||||||
|
|
||||||
# Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose, 3 == print environment variables on each rustc invocation
|
# Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose, 3 == print environment variables on each rustc invocation
|
||||||
|
|
|
@ -110,7 +110,6 @@
|
||||||
#![cfg_attr(bootstrap, feature(offset_of_nested))]
|
#![cfg_attr(bootstrap, feature(offset_of_nested))]
|
||||||
#![feature(array_ptr_get)]
|
#![feature(array_ptr_get)]
|
||||||
#![feature(asm_experimental_arch)]
|
#![feature(asm_experimental_arch)]
|
||||||
#![feature(char_indices_offset)]
|
|
||||||
#![feature(const_align_of_val)]
|
#![feature(const_align_of_val)]
|
||||||
#![feature(const_align_of_val_raw)]
|
#![feature(const_align_of_val_raw)]
|
||||||
#![feature(const_align_offset)]
|
#![feature(const_align_offset)]
|
||||||
|
|
|
@ -241,24 +241,35 @@ impl<'a> CharIndices<'a> {
|
||||||
/// Returns the byte position of the next character, or the length
|
/// Returns the byte position of the next character, or the length
|
||||||
/// of the underlying string if there are no more characters.
|
/// of the underlying string if there are no more characters.
|
||||||
///
|
///
|
||||||
|
/// This means that, when the iterator has not been fully consumed,
|
||||||
|
/// the returned value will match the index that will be returned
|
||||||
|
/// by the next call to [`next()`](Self::next).
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(char_indices_offset)]
|
|
||||||
/// let mut chars = "a楽".char_indices();
|
/// let mut chars = "a楽".char_indices();
|
||||||
///
|
///
|
||||||
|
/// // `next()` has not been called yet, so `offset()` returns the byte
|
||||||
|
/// // index of the first character of the string, which is always 0.
|
||||||
/// assert_eq!(chars.offset(), 0);
|
/// assert_eq!(chars.offset(), 0);
|
||||||
|
/// // As expected, the first call to `next()` also returns 0 as index.
|
||||||
/// assert_eq!(chars.next(), Some((0, 'a')));
|
/// assert_eq!(chars.next(), Some((0, 'a')));
|
||||||
///
|
///
|
||||||
|
/// // `next()` has been called once, so `offset()` returns the byte index
|
||||||
|
/// // of the second character ...
|
||||||
/// assert_eq!(chars.offset(), 1);
|
/// assert_eq!(chars.offset(), 1);
|
||||||
|
/// // ... which matches the index returned by the next call to `next()`.
|
||||||
/// assert_eq!(chars.next(), Some((1, '楽')));
|
/// assert_eq!(chars.next(), Some((1, '楽')));
|
||||||
///
|
///
|
||||||
|
/// // Once the iterator has been consumed, `offset()` returns the length
|
||||||
|
/// // in bytes of the string.
|
||||||
/// assert_eq!(chars.offset(), 4);
|
/// assert_eq!(chars.offset(), 4);
|
||||||
/// assert_eq!(chars.next(), None);
|
/// assert_eq!(chars.next(), None);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "char_indices_offset", issue = "83871")]
|
#[stable(feature = "char_indices_offset", since = "CURRENT_RUSTC_VERSION")]
|
||||||
pub fn offset(&self) -> usize {
|
pub fn offset(&self) -> usize {
|
||||||
self.front_offset
|
self.front_offset
|
||||||
}
|
}
|
||||||
|
|
|
@ -1096,7 +1096,7 @@ tool_extended!((self, builder),
|
||||||
CargoClippy, "src/tools/clippy", "cargo-clippy", stable=true;
|
CargoClippy, "src/tools/clippy", "cargo-clippy", stable=true;
|
||||||
Clippy, "src/tools/clippy", "clippy-driver", stable=true, add_bins_to_sysroot = ["clippy-driver", "cargo-clippy"];
|
Clippy, "src/tools/clippy", "clippy-driver", stable=true, add_bins_to_sysroot = ["clippy-driver", "cargo-clippy"];
|
||||||
Miri, "src/tools/miri", "miri", stable=false, add_bins_to_sysroot = ["miri"];
|
Miri, "src/tools/miri", "miri", stable=false, add_bins_to_sysroot = ["miri"];
|
||||||
CargoMiri, "src/tools/miri/cargo-miri", "cargo-miri", stable=true, add_bins_to_sysroot = ["cargo-miri"];
|
CargoMiri, "src/tools/miri/cargo-miri", "cargo-miri", stable=false, add_bins_to_sysroot = ["cargo-miri"];
|
||||||
Rls, "src/tools/rls", "rls", stable=true;
|
Rls, "src/tools/rls", "rls", stable=true;
|
||||||
Rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, add_bins_to_sysroot = ["rustfmt", "cargo-fmt"];
|
Rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, add_bins_to_sysroot = ["rustfmt", "cargo-fmt"];
|
||||||
);
|
);
|
||||||
|
|
|
@ -81,6 +81,7 @@
|
||||||
- [wasm32-wasip1](platform-support/wasm32-wasip1.md)
|
- [wasm32-wasip1](platform-support/wasm32-wasip1.md)
|
||||||
- [wasm32-wasip1-threads](platform-support/wasm32-wasip1-threads.md)
|
- [wasm32-wasip1-threads](platform-support/wasm32-wasip1-threads.md)
|
||||||
- [wasm32-wasip2](platform-support/wasm32-wasip2.md)
|
- [wasm32-wasip2](platform-support/wasm32-wasip2.md)
|
||||||
|
- [wasm32-unknown-unknown](platform-support/wasm32-unknown-unknown.md)
|
||||||
- [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md)
|
- [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md)
|
||||||
- [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md)
|
- [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md)
|
||||||
- [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md)
|
- [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md)
|
||||||
|
|
|
@ -192,7 +192,7 @@ target | std | notes
|
||||||
[`thumbv8m.main-none-eabi`](platform-support/thumbv8m.main-none-eabi.md) | * | Bare Armv8-M Mainline
|
[`thumbv8m.main-none-eabi`](platform-support/thumbv8m.main-none-eabi.md) | * | Bare Armv8-M Mainline
|
||||||
[`thumbv8m.main-none-eabihf`](platform-support/thumbv8m.main-none-eabi.md) | * | Bare Armv8-M Mainline, hardfloat
|
[`thumbv8m.main-none-eabihf`](platform-support/thumbv8m.main-none-eabi.md) | * | Bare Armv8-M Mainline, hardfloat
|
||||||
`wasm32-unknown-emscripten` | ✓ | WebAssembly via Emscripten
|
`wasm32-unknown-emscripten` | ✓ | WebAssembly via Emscripten
|
||||||
`wasm32-unknown-unknown` | ✓ | WebAssembly
|
[`wasm32-unknown-unknown`](platform-support/wasm32-unknown-unknown.md) | ✓ | WebAssembly
|
||||||
`wasm32-wasi` | ✓ | WebAssembly with WASI (undergoing a [rename to `wasm32-wasip1`][wasi-rename])
|
`wasm32-wasi` | ✓ | WebAssembly with WASI (undergoing a [rename to `wasm32-wasip1`][wasi-rename])
|
||||||
[`wasm32-wasip1`](platform-support/wasm32-wasip1.md) | ✓ | WebAssembly with WASI
|
[`wasm32-wasip1`](platform-support/wasm32-wasip1.md) | ✓ | WebAssembly with WASI
|
||||||
[`wasm32-wasip1-threads`](platform-support/wasm32-wasip1-threads.md) | ✓ | WebAssembly with WASI Preview 1 and threads
|
[`wasm32-wasip1-threads`](platform-support/wasm32-wasip1-threads.md) | ✓ | WebAssembly with WASI Preview 1 and threads
|
||||||
|
|
198
src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md
Normal file
198
src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
# `wasm32-unknown-unknown`
|
||||||
|
|
||||||
|
**Tier: 2**
|
||||||
|
|
||||||
|
The `wasm32-unknown-unknown` target is a WebAssembly compilation target which
|
||||||
|
does not import any functions from the host for the standard library. This is
|
||||||
|
the "minimal" WebAssembly in the sense of making the fewest assumptions about
|
||||||
|
the host environment. This target is often used when compiling to the web or
|
||||||
|
JavaScript environments as there is no standard for what functions can be
|
||||||
|
imported on the web. This target can also be useful for creating minimal or
|
||||||
|
bare-bones WebAssembly binaries.
|
||||||
|
|
||||||
|
The `wasm32-unknown-unknown` target has support for the Rust standard library
|
||||||
|
but many parts of the standard library do not work and return errors. For
|
||||||
|
example `println!` does nothing, `std::fs` always return errors, and
|
||||||
|
`std::thread::spawn` will panic. There is no means by which this can be
|
||||||
|
overridden. For a WebAssembly target that more fully supports the standard
|
||||||
|
library see the [`wasm32-wasip1`](./wasm32-wasip1.md) or
|
||||||
|
[`wasm32-wasip2`](./wasm32-wasip2.md) targets.
|
||||||
|
|
||||||
|
The `wasm32-unknown-unknown` target has full support for the `core` and `alloc`
|
||||||
|
crates. It additionally supports the `HashMap` type in the `std` crate, although
|
||||||
|
hash maps are not randomized like they are on other platforms.
|
||||||
|
|
||||||
|
One existing user of this target (please feel free to edit and expand this list
|
||||||
|
too) is the [`wasm-bindgen` project](https://github.com/rustwasm/wasm-bindgen)
|
||||||
|
which facilitates Rust code interoperating with JavaScript code. Note, though,
|
||||||
|
that not all uses of `wasm32-unknown-unknown` are using JavaScript and the web.
|
||||||
|
|
||||||
|
## Target maintainers
|
||||||
|
|
||||||
|
When this target was added to the compiler platform-specific documentation here
|
||||||
|
was not maintained at that time. This means that the list below is not
|
||||||
|
exhaustive and there are more interested parties in this target. That being
|
||||||
|
said since when this document was last updated those interested in maintaining
|
||||||
|
this target are:
|
||||||
|
|
||||||
|
- Alex Crichton, https://github.com/alexcrichton
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
This target is cross-compiled. The target includes support for `std` itself,
|
||||||
|
but as mentioned above many pieces of functionality that require an operating
|
||||||
|
system do not work and will return errors.
|
||||||
|
|
||||||
|
This target currently has no equivalent in C/C++. There is no C/C++ toolchain
|
||||||
|
for this target. While interop is theoretically possible it's recommended to
|
||||||
|
instead use one of:
|
||||||
|
|
||||||
|
* `wasm32-unknown-emscripten` - for web-based use cases the Emscripten
|
||||||
|
toolchain is typically chosen for running C/C++.
|
||||||
|
* [`wasm32-wasip1`](./wasm32-wasip1.md) - the wasi-sdk toolchain is used to
|
||||||
|
compile C/C++ on this target and can interop with Rust code. WASI works on
|
||||||
|
the web so far as there's no blocker, but an implementation of WASI APIs
|
||||||
|
must be either chosen or reimplemented.
|
||||||
|
|
||||||
|
This target has no build requirements beyond what's in-tree in the Rust
|
||||||
|
repository. Linking binaries requires LLD to be enabled for the `wasm-ld`
|
||||||
|
driver. This target uses the `dlmalloc` crate as the default global allocator.
|
||||||
|
|
||||||
|
## Building the target
|
||||||
|
|
||||||
|
Building this target can be done by:
|
||||||
|
|
||||||
|
* Configure the `wasm32-unknown-unknown` target to get built.
|
||||||
|
* Configure LLD to be built.
|
||||||
|
* Ensure the `WebAssembly` target backend is not disabled in LLVM.
|
||||||
|
|
||||||
|
These are all controlled through `config.toml` options. It should be possible
|
||||||
|
to build this target on any platform.
|
||||||
|
|
||||||
|
## Building Rust programs
|
||||||
|
|
||||||
|
Rust programs can be compiled by adding this target via rustup:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ rustup target add wasm32-unknown-unknown
|
||||||
|
```
|
||||||
|
|
||||||
|
and then compiling with the target:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ rustc foo.rs --target wasm32-unknown-unknown
|
||||||
|
$ file foo.wasm
|
||||||
|
```
|
||||||
|
|
||||||
|
## Cross-compilation
|
||||||
|
|
||||||
|
This target can be cross-compiled from any host.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
This target is not tested in CI for the rust-lang/rust repository. Many tests
|
||||||
|
must be disabled to run on this target and failures are non-obvious because
|
||||||
|
`println!` doesn't work in the standard library. It's recommended to test the
|
||||||
|
`wasm32-wasip1` target instead for WebAssembly compatibility.
|
||||||
|
|
||||||
|
## Conditionally compiling code
|
||||||
|
|
||||||
|
It's recommended to conditionally compile code for this target with:
|
||||||
|
|
||||||
|
```text
|
||||||
|
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that there is no way to tell via `#[cfg]` whether code will be running on
|
||||||
|
the web or not.
|
||||||
|
|
||||||
|
## Enabled WebAssembly features
|
||||||
|
|
||||||
|
WebAssembly is an evolving standard which adds new features such as new
|
||||||
|
instructions over time. This target's default set of supported WebAssembly
|
||||||
|
features will additionally change over time. The `wasm32-unknown-unknown` target
|
||||||
|
inherits the default settings of LLVM which typically matches the default
|
||||||
|
settings of Emscripten as well.
|
||||||
|
|
||||||
|
Changes to WebAssembly go through a [proposals process][proposals] but reaching
|
||||||
|
the final stage (stage 5) does not automatically mean that the feature will be
|
||||||
|
enabled in LLVM and Rust by default. At this time the general guidance is that
|
||||||
|
features must be present in most engines for a "good chunk of time" before
|
||||||
|
they're enabled in LLVM by default. There is currently no exact number of
|
||||||
|
months or engines that are required to enable features by default.
|
||||||
|
|
||||||
|
[proposals]: https://github.com/WebAssembly/proposals
|
||||||
|
|
||||||
|
As of the time of this writing the proposals that are enabled by default (the
|
||||||
|
`generic` CPU in LLVM terminology) are:
|
||||||
|
|
||||||
|
* `multivalue`
|
||||||
|
* `mutable-globals`
|
||||||
|
* `reference-types`
|
||||||
|
* `sign-ext`
|
||||||
|
|
||||||
|
If you're compiling WebAssembly code for an engine that does not support a
|
||||||
|
feature in LLVM's default feature set then the feature must be disabled at
|
||||||
|
compile time. Note, though, that enabled features may be used in the standard
|
||||||
|
library or precompiled libraries shipped via rustup. This means that not only
|
||||||
|
does your own code need to be compiled with the correct set of flags but the
|
||||||
|
Rust standard library additionally must be recompiled.
|
||||||
|
|
||||||
|
Compiling all code for the initial release of WebAssembly looks like:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ export RUSTFLAGS=-Ctarget-cpu=mvp
|
||||||
|
$ cargo +nightly build -Zbuild-std=panic_abort,std --target wasm32-unknown-unknown
|
||||||
|
```
|
||||||
|
|
||||||
|
Here the `mvp` "cpu" is a placeholder in LLVM for disabling all supported
|
||||||
|
features by default. Cargo's `-Zbuild-std` feature, a Nightly Rust feature, is
|
||||||
|
then used to recompile the standard library in addition to your own code. This
|
||||||
|
will produce a binary that uses only the original WebAssembly features by
|
||||||
|
default and no proposals since its inception.
|
||||||
|
|
||||||
|
To enable individual features it can be done with `-Ctarget-feature=+foo`.
|
||||||
|
Available features for Rust code itself are documented in the [reference] and
|
||||||
|
can also be found through:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ rustc -Ctarget-feature=help --target wasm32-unknown-unknown
|
||||||
|
```
|
||||||
|
|
||||||
|
You'll need to consult your WebAssembly engine's documentation to learn more
|
||||||
|
about the supported WebAssembly features the engine has.
|
||||||
|
|
||||||
|
[reference]: https://doc.rust-lang.org/reference/attributes/codegen.html#wasm32-or-wasm64
|
||||||
|
|
||||||
|
Note that it is still possible for Rust crates and libraries to enable
|
||||||
|
WebAssembly features on a per-function level. This means that the build
|
||||||
|
command above may not be sufficient to disable all WebAssembly features. If the
|
||||||
|
final binary still has SIMD instructions, for example, the function in question
|
||||||
|
will need to be found and the crate in question will likely contain something
|
||||||
|
like:
|
||||||
|
|
||||||
|
```rust,ignore (not-always-compiled-to-wasm)
|
||||||
|
#[target_feature(enable = "simd128")]
|
||||||
|
fn foo() {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In this situation there is no compiler flag to disable emission of SIMD
|
||||||
|
instructions and the crate must instead be modified to not include this function
|
||||||
|
at compile time either by default or through a Cargo feature. For crate authors
|
||||||
|
it's recommended to avoid `#[target_feature(enable = "...")]` except where
|
||||||
|
necessary and instead use:
|
||||||
|
|
||||||
|
```rust,ignore (not-always-compiled-to-wasm)
|
||||||
|
#[cfg(target_feature = "simd128")]
|
||||||
|
fn foo() {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
That is to say instead of enabling target features it's recommended to
|
||||||
|
conditionally compile code instead. This is notably different to the way native
|
||||||
|
platforms such as x86\_64 work, and this is due to the fact that WebAssembly
|
||||||
|
binaries must only contain code the engine understands. Native binaries work so
|
||||||
|
long as the CPU doesn't execute unknown code dynamically at runtime.
|
|
@ -162,3 +162,17 @@ It's recommended to conditionally compile code for this target with:
|
||||||
Prior to Rust 1.80 the `target_env = "p1"` key was not set. Currently the
|
Prior to Rust 1.80 the `target_env = "p1"` key was not set. Currently the
|
||||||
`target_feature = "atomics"` is Nightly-only. Note that the precise `#[cfg]`
|
`target_feature = "atomics"` is Nightly-only. Note that the precise `#[cfg]`
|
||||||
necessary to detect this target may change as the target becomes more stable.
|
necessary to detect this target may change as the target becomes more stable.
|
||||||
|
|
||||||
|
## Enabled WebAssembly features
|
||||||
|
|
||||||
|
The default set of WebAssembly features enabled for compilation includes two
|
||||||
|
more features in addition to that which
|
||||||
|
[`wasm32-unknown-unknown`](./wasm32-unknown-unknown.md) enables:
|
||||||
|
|
||||||
|
* `bulk-memory`
|
||||||
|
* `atomics`
|
||||||
|
|
||||||
|
For more information about features see the documentation for
|
||||||
|
[`wasm32-unknown-unknown`](./wasm32-unknown-unknown.md), but note that the
|
||||||
|
`mvp` CPU in LLVM does not support this target as it's required that
|
||||||
|
`bulk-memory`, `atomics`, and `mutable-globals` are all enabled.
|
||||||
|
|
|
@ -132,3 +132,9 @@ It's recommended to conditionally compile code for this target with:
|
||||||
|
|
||||||
Note that the `target_env = "p1"` condition first appeared in Rust 1.80. Prior
|
Note that the `target_env = "p1"` condition first appeared in Rust 1.80. Prior
|
||||||
to Rust 1.80 the `target_env` condition was not set.
|
to Rust 1.80 the `target_env` condition was not set.
|
||||||
|
|
||||||
|
## Enabled WebAssembly features
|
||||||
|
|
||||||
|
The default set of WebAssembly features enabled for compilation is currently the
|
||||||
|
same as [`wasm32-unknown-unknown`](./wasm32-unknown-unknown.md). See the
|
||||||
|
documentation there for more information.
|
||||||
|
|
|
@ -61,3 +61,9 @@ It's recommended to conditionally compile code for this target with:
|
||||||
```text
|
```text
|
||||||
#[cfg(all(target_os = "wasi", target_env = "p2"))]
|
#[cfg(all(target_os = "wasi", target_env = "p2"))]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Enabled WebAssembly features
|
||||||
|
|
||||||
|
The default set of WebAssembly features enabled for compilation is currently the
|
||||||
|
same as [`wasm32-unknown-unknown`](./wasm32-unknown-unknown.md). See the
|
||||||
|
documentation there for more information.
|
||||||
|
|
|
@ -579,12 +579,14 @@ pub(crate) fn build_index<'tcx>(
|
||||||
let mut names = Vec::with_capacity(self.items.len());
|
let mut names = Vec::with_capacity(self.items.len());
|
||||||
let mut types = String::with_capacity(self.items.len());
|
let mut types = String::with_capacity(self.items.len());
|
||||||
let mut full_paths = Vec::with_capacity(self.items.len());
|
let mut full_paths = Vec::with_capacity(self.items.len());
|
||||||
let mut parents = Vec::with_capacity(self.items.len());
|
let mut parents = String::with_capacity(self.items.len());
|
||||||
|
let mut parents_backref_queue = VecDeque::new();
|
||||||
let mut functions = String::with_capacity(self.items.len());
|
let mut functions = String::with_capacity(self.items.len());
|
||||||
let mut deprecated = Vec::with_capacity(self.items.len());
|
let mut deprecated = Vec::with_capacity(self.items.len());
|
||||||
|
|
||||||
let mut backref_queue = VecDeque::new();
|
let mut type_backref_queue = VecDeque::new();
|
||||||
|
|
||||||
|
let mut last_name = None;
|
||||||
for (index, item) in self.items.iter().enumerate() {
|
for (index, item) in self.items.iter().enumerate() {
|
||||||
let n = item.ty as u8;
|
let n = item.ty as u8;
|
||||||
let c = char::try_from(n + b'A').expect("item types must fit in ASCII");
|
let c = char::try_from(n + b'A').expect("item types must fit in ASCII");
|
||||||
|
@ -597,17 +599,39 @@ pub(crate) fn build_index<'tcx>(
|
||||||
"`{}` is missing idx",
|
"`{}` is missing idx",
|
||||||
item.name
|
item.name
|
||||||
);
|
);
|
||||||
// 0 is a sentinel, everything else is one-indexed
|
assert!(
|
||||||
parents.push(item.parent_idx.map(|x| x + 1).unwrap_or(0));
|
parents_backref_queue.len() <= 16,
|
||||||
|
"the string encoding only supports 16 slots of lookback"
|
||||||
|
);
|
||||||
|
let parent: i32 = item.parent_idx.map(|x| x + 1).unwrap_or(0).try_into().unwrap();
|
||||||
|
if let Some(idx) = parents_backref_queue.iter().position(|p: &i32| *p == parent) {
|
||||||
|
parents.push(
|
||||||
|
char::try_from('0' as u32 + u32::try_from(idx).unwrap())
|
||||||
|
.expect("last possible value is '?'"),
|
||||||
|
);
|
||||||
|
} else if parent == 0 {
|
||||||
|
write_vlqhex_to_string(parent, &mut parents);
|
||||||
|
} else {
|
||||||
|
parents_backref_queue.push_front(parent);
|
||||||
|
write_vlqhex_to_string(parent, &mut parents);
|
||||||
|
if parents_backref_queue.len() > 16 {
|
||||||
|
parents_backref_queue.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if Some(item.name.as_str()) == last_name {
|
||||||
|
names.push("");
|
||||||
|
} else {
|
||||||
names.push(item.name.as_str());
|
names.push(item.name.as_str());
|
||||||
|
last_name = Some(item.name.as_str());
|
||||||
|
}
|
||||||
|
|
||||||
if !item.path.is_empty() {
|
if !item.path.is_empty() {
|
||||||
full_paths.push((index, &item.path));
|
full_paths.push((index, &item.path));
|
||||||
}
|
}
|
||||||
|
|
||||||
match &item.search_type {
|
match &item.search_type {
|
||||||
Some(ty) => ty.write_to_string(&mut functions, &mut backref_queue),
|
Some(ty) => ty.write_to_string(&mut functions, &mut type_backref_queue),
|
||||||
None => functions.push('`'),
|
None => functions.push('`'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3546,7 +3546,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
|
||||||
// Used to de-duplicate inlined and re-exported stuff
|
// Used to de-duplicate inlined and re-exported stuff
|
||||||
const itemReexports = new Map(crateCorpus.r);
|
const itemReexports = new Map(crateCorpus.r);
|
||||||
// an array of (Number) the parent path index + 1 to `paths`, or 0 if none
|
// an array of (Number) the parent path index + 1 to `paths`, or 0 if none
|
||||||
const itemParentIdxs = crateCorpus.i;
|
const itemParentIdxDecoder = new VlqHexDecoder(crateCorpus.i, noop => noop);
|
||||||
// a map Number, string for impl disambiguators
|
// a map Number, string for impl disambiguators
|
||||||
const implDisambiguator = new Map(crateCorpus.b);
|
const implDisambiguator = new Map(crateCorpus.b);
|
||||||
// an array of [(Number) item type,
|
// an array of [(Number) item type,
|
||||||
|
@ -3593,6 +3593,8 @@ ${item.displayPath}<span class="${type}">${name}</span>\
|
||||||
// faster analysis operations
|
// faster analysis operations
|
||||||
lastPath = "";
|
lastPath = "";
|
||||||
len = itemTypes.length;
|
len = itemTypes.length;
|
||||||
|
let lastName = "";
|
||||||
|
let lastWord = "";
|
||||||
for (let i = 0; i < len; ++i) {
|
for (let i = 0; i < len; ++i) {
|
||||||
const bitIndex = i + 1;
|
const bitIndex = i + 1;
|
||||||
if (descIndex >= descShard.len &&
|
if (descIndex >= descShard.len &&
|
||||||
|
@ -3608,10 +3610,8 @@ ${item.displayPath}<span class="${type}">${name}</span>\
|
||||||
descIndex = 0;
|
descIndex = 0;
|
||||||
descShardList.push(descShard);
|
descShardList.push(descShard);
|
||||||
}
|
}
|
||||||
let word = "";
|
const name = itemNames[i] === "" ? lastName : itemNames[i];
|
||||||
if (typeof itemNames[i] === "string") {
|
const word = itemNames[i] === "" ? lastWord : itemNames[i].toLowerCase();
|
||||||
word = itemNames[i].toLowerCase();
|
|
||||||
}
|
|
||||||
const path = itemPaths.has(i) ? itemPaths.get(i) : lastPath;
|
const path = itemPaths.has(i) ? itemPaths.get(i) : lastPath;
|
||||||
const type = itemFunctionDecoder.next();
|
const type = itemFunctionDecoder.next();
|
||||||
if (type !== null) {
|
if (type !== null) {
|
||||||
|
@ -3633,15 +3633,16 @@ ${item.displayPath}<span class="${type}">${name}</span>\
|
||||||
}
|
}
|
||||||
// This object should have exactly the same set of fields as the "crateRow"
|
// This object should have exactly the same set of fields as the "crateRow"
|
||||||
// object defined above.
|
// object defined above.
|
||||||
|
const itemParentIdx = itemParentIdxDecoder.next();
|
||||||
const row = {
|
const row = {
|
||||||
crate,
|
crate,
|
||||||
ty: itemTypes.charCodeAt(i) - 65, // 65 = "A"
|
ty: itemTypes.charCodeAt(i) - 65, // 65 = "A"
|
||||||
name: itemNames[i],
|
name,
|
||||||
path,
|
path,
|
||||||
descShard,
|
descShard,
|
||||||
descIndex,
|
descIndex,
|
||||||
exactPath: itemReexports.has(i) ? itemPaths.get(itemReexports.get(i)) : path,
|
exactPath: itemReexports.has(i) ? itemPaths.get(itemReexports.get(i)) : path,
|
||||||
parent: itemParentIdxs[i] > 0 ? paths[itemParentIdxs[i] - 1] : undefined,
|
parent: itemParentIdx > 0 ? paths[itemParentIdx - 1] : undefined,
|
||||||
type,
|
type,
|
||||||
id,
|
id,
|
||||||
word,
|
word,
|
||||||
|
@ -3655,6 +3656,8 @@ ${item.displayPath}<span class="${type}">${name}</span>\
|
||||||
if (!searchIndexEmptyDesc.get(crate).contains(bitIndex)) {
|
if (!searchIndexEmptyDesc.get(crate).contains(bitIndex)) {
|
||||||
descIndex += 1;
|
descIndex += 1;
|
||||||
}
|
}
|
||||||
|
lastName = name;
|
||||||
|
lastWord = word;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aliases) {
|
if (aliases) {
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
//@ revisions: DEBUG OPTIM
|
//@ revisions: DEBUG LLVM-PRE-20-OPTIM LLVM-20-OPTIM
|
||||||
//@ [DEBUG] compile-flags: -C opt-level=0
|
//@ [DEBUG] compile-flags: -C opt-level=0
|
||||||
//@ [OPTIM] compile-flags: -C opt-level=3
|
//@ [LLVM-PRE-20-OPTIM] compile-flags: -C opt-level=3
|
||||||
|
//@ [LLVM-PRE-20-OPTIM] ignore-llvm-version: 20 - 99
|
||||||
|
//@ [LLVM-20-OPTIM] compile-flags: -C opt-level=3
|
||||||
|
//@ [LLVM-20-OPTIM] min-llvm-version: 20
|
||||||
//@ assembly-output: emit-asm
|
//@ assembly-output: emit-asm
|
||||||
//@ compile-flags: --crate-type=lib -C llvm-args=-x86-asm-syntax=intel
|
//@ compile-flags: --crate-type=lib -C llvm-args=-x86-asm-syntax=intel
|
||||||
//@ only-x86_64
|
//@ only-x86_64
|
||||||
|
@ -21,12 +24,18 @@ pub fn signed_cmp(a: i16, b: i16) -> std::cmp::Ordering {
|
||||||
// DEBUG: and
|
// DEBUG: and
|
||||||
// DEBUG: sub
|
// DEBUG: sub
|
||||||
|
|
||||||
// OPTIM: xor
|
// LLVM-PRE-20-OPTIM: xor
|
||||||
// OPTIM: cmp
|
// LLVM-PRE-20-OPTIM: cmp
|
||||||
// OPTIM: setne
|
// LLVM-PRE-20-OPTIM: setne
|
||||||
// OPTIM: mov
|
// LLVM-PRE-20-OPTIM: mov
|
||||||
// OPTIM: cmovge
|
// LLVM-PRE-20-OPTIM: cmovge
|
||||||
// OPTIM: ret
|
// LLVM-PRE-20-OPTIM: ret
|
||||||
|
//
|
||||||
|
// LLVM-20-OPTIM: cmp
|
||||||
|
// LLVM-20-OPTIM: setl
|
||||||
|
// LLVM-20-OPTIM: setg
|
||||||
|
// LLVM-20-OPTIM: sub
|
||||||
|
// LLVM-20-OPTIM: ret
|
||||||
three_way_compare(a, b)
|
three_way_compare(a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,11 +50,16 @@ pub fn unsigned_cmp(a: u16, b: u16) -> std::cmp::Ordering {
|
||||||
// DEBUG: and
|
// DEBUG: and
|
||||||
// DEBUG: sub
|
// DEBUG: sub
|
||||||
|
|
||||||
// OPTIM: xor
|
// LLVM-PRE-20-OPTIM: xor
|
||||||
// OPTIM: cmp
|
// LLVM-PRE-20-OPTIM: cmp
|
||||||
// OPTIM: setne
|
// LLVM-PRE-20-OPTIM: setne
|
||||||
// OPTIM: mov
|
// LLVM-PRE-20-OPTIM: mov
|
||||||
// OPTIM: cmovae
|
// LLVM-PRE-20-OPTIM: cmovae
|
||||||
// OPTIM: ret
|
// LLVM-PRE-20-OPTIM: ret
|
||||||
|
//
|
||||||
|
// LLVM-20-OPTIM: cmp
|
||||||
|
// LLVM-20-OPTIM: seta
|
||||||
|
// LLVM-20-OPTIM: sbb
|
||||||
|
// LLVM-20-OPTIM: ret
|
||||||
three_way_compare(a, b)
|
three_way_compare(a, b)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
// This is test for more optimal Ord implementation for integers.
|
// This is test for more optimal Ord implementation for integers.
|
||||||
// See <https://github.com/rust-lang/rust/issues/63758> for more info.
|
// See <https://github.com/rust-lang/rust/issues/63758> for more info.
|
||||||
|
|
||||||
|
//@ revisions: llvm-pre-20 llvm-20
|
||||||
|
//@ [llvm-20] min-llvm-version: 20
|
||||||
|
//@ [llvm-pre-20] ignore-llvm-version: 20 - 99
|
||||||
//@ compile-flags: -C opt-level=3
|
//@ compile-flags: -C opt-level=3
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
@ -10,19 +13,21 @@ use std::cmp::Ordering;
|
||||||
// CHECK-LABEL: @cmp_signed
|
// CHECK-LABEL: @cmp_signed
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn cmp_signed(a: i64, b: i64) -> Ordering {
|
pub fn cmp_signed(a: i64, b: i64) -> Ordering {
|
||||||
// CHECK: icmp slt
|
// llvm-20: @llvm.scmp.i8.i64
|
||||||
// CHECK: icmp ne
|
// llvm-pre-20: icmp slt
|
||||||
// CHECK: zext i1
|
// llvm-pre-20: icmp ne
|
||||||
// CHECK: select i1
|
// llvm-pre-20: zext i1
|
||||||
|
// llvm-pre-20: select i1
|
||||||
a.cmp(&b)
|
a.cmp(&b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @cmp_unsigned
|
// CHECK-LABEL: @cmp_unsigned
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn cmp_unsigned(a: u32, b: u32) -> Ordering {
|
pub fn cmp_unsigned(a: u32, b: u32) -> Ordering {
|
||||||
// CHECK: icmp ult
|
// llvm-20: @llvm.ucmp.i8.i32
|
||||||
// CHECK: icmp ne
|
// llvm-pre-20: icmp ult
|
||||||
// CHECK: zext i1
|
// llvm-pre-20: icmp ne
|
||||||
// CHECK: select i1
|
// llvm-pre-20: zext i1
|
||||||
|
// llvm-pre-20: select i1
|
||||||
a.cmp(&b)
|
a.cmp(&b)
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ fn main() {
|
||||||
| |
|
| |
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
help: there are multiple different versions of crate `dependency` the your dependency graph
|
help: there are multiple different versions of crate `dependency` in the dependency graph
|
||||||
--> multiple-dep-versions.rs:1:1
|
--> multiple-dep-versions.rs:1:1
|
||||||
|
|
|
|
||||||
1 | extern crate dep_2_reexport;
|
1 | extern crate dep_2_reexport;
|
||||||
|
|
12
tests/ui/lint/dropping_copy_types-macros.fixed
Normal file
12
tests/ui/lint/dropping_copy_types-macros.fixed
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
//@ check-fail
|
||||||
|
//@ run-rustfix
|
||||||
|
|
||||||
|
#![deny(dropping_copy_types)]
|
||||||
|
|
||||||
|
use std::fmt::Write;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut msg = String::new();
|
||||||
|
let _ = writeln!(&mut msg, "test");
|
||||||
|
//~^ ERROR calls to `std::mem::drop`
|
||||||
|
}
|
12
tests/ui/lint/dropping_copy_types-macros.rs
Normal file
12
tests/ui/lint/dropping_copy_types-macros.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
//@ check-fail
|
||||||
|
//@ run-rustfix
|
||||||
|
|
||||||
|
#![deny(dropping_copy_types)]
|
||||||
|
|
||||||
|
use std::fmt::Write;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut msg = String::new();
|
||||||
|
drop(writeln!(&mut msg, "test"));
|
||||||
|
//~^ ERROR calls to `std::mem::drop`
|
||||||
|
}
|
21
tests/ui/lint/dropping_copy_types-macros.stderr
Normal file
21
tests/ui/lint/dropping_copy_types-macros.stderr
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
error: calls to `std::mem::drop` with a value that implements `Copy` does nothing
|
||||||
|
--> $DIR/dropping_copy_types-macros.rs:10:5
|
||||||
|
|
|
||||||
|
LL | drop(writeln!(&mut msg, "test"));
|
||||||
|
| ^^^^^--------------------------^
|
||||||
|
| |
|
||||||
|
| argument has type `Result<(), std::fmt::Error>`
|
||||||
|
|
|
||||||
|
note: the lint level is defined here
|
||||||
|
--> $DIR/dropping_copy_types-macros.rs:4:9
|
||||||
|
|
|
||||||
|
LL | #![deny(dropping_copy_types)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
help: use `let _ = ...` to ignore the expression or result
|
||||||
|
|
|
||||||
|
LL - drop(writeln!(&mut msg, "test"));
|
||||||
|
LL + let _ = writeln!(&mut msg, "test");
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
|
@ -913,7 +913,7 @@ cc = ["@kobzol"]
|
||||||
[assign]
|
[assign]
|
||||||
warn_non_default_branch = true
|
warn_non_default_branch = true
|
||||||
contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
|
contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
|
||||||
users_on_vacation = ["jyn514", "jhpratt", "oli-obk"]
|
users_on_vacation = ["jyn514", "jhpratt", "oli-obk", "kobzol"]
|
||||||
|
|
||||||
[assign.adhoc_groups]
|
[assign.adhoc_groups]
|
||||||
compiler-team = [
|
compiler-team = [
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue