From 0b87af9d4f7c6faa9e89496609f016dc3e3977e1 Mon Sep 17 00:00:00 2001 From: Mrmaxmeier Date: Sat, 27 Apr 2024 23:14:36 +0200 Subject: [PATCH 01/21] Add `-Z embed-source=yes` to embed source code in DWARF debug info --- .../src/debuginfo/metadata.rs | 9 +++++++ compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 2 ++ compiler/rustc_interface/src/tests.rs | 1 + .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 9 +++++-- compiler/rustc_session/messages.ftl | 6 +++++ compiler/rustc_session/src/errors.rs | 14 +++++++++++ compiler/rustc_session/src/options.rs | 2 ++ compiler/rustc_session/src/session.rs | 25 +++++++++++++++++-- .../src/compiler-flags/embed-source.md | 12 +++++++++ 9 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 src/doc/unstable-book/src/compiler-flags/embed-source.md diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index ad63858861261..701ea62b21a7d 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -629,6 +629,9 @@ pub fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) -> }; let hash_value = hex_encode(source_file.src_hash.hash_bytes()); + let source = + cx.sess().opts.unstable_opts.embed_source.then_some(()).and(source_file.src.as_ref()); + unsafe { llvm::LLVMRustDIBuilderCreateFile( DIB(cx), @@ -639,6 +642,8 @@ pub fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) -> hash_kind, hash_value.as_ptr().cast(), hash_value.len(), + source.map_or(ptr::null(), |x| x.as_ptr().cast()), + source.map_or(0, |x| x.len()), ) } } @@ -659,6 +664,8 @@ pub fn unknown_file_metadata<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile { llvm::ChecksumKind::None, hash_value.as_ptr().cast(), hash_value.len(), + ptr::null(), + 0, ) }) } @@ -943,6 +950,8 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>( llvm::ChecksumKind::None, ptr::null(), 0, + ptr::null(), + 0, ); let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit( diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index c8e0e075eeabc..faa675b66c8a1 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1853,6 +1853,8 @@ extern "C" { CSKind: ChecksumKind, Checksum: *const c_char, ChecksumLen: size_t, + Source: *const c_char, + SourceLen: size_t, ) -> &'a DIFile; pub fn LLVMRustDIBuilderCreateSubroutineType<'a>( diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index ce3b2f77f210a..c4704e38ce6fa 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -773,6 +773,7 @@ fn test_unstable_options_tracking_hash() { tracked!(direct_access_external_data, Some(true)); tracked!(dual_proc_macros, true); tracked!(dwarf_version, Some(5)); + tracked!(embed_source, true); tracked!(emit_thin_lto, false); tracked!(export_executable_symbols, true); tracked!(fewer_names, Some(true)); diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 4cdd8af1008c0..6e700c31e6763 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -901,14 +901,19 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(LLVMRustDIBuilderRef Builder, const char *Filename, size_t FilenameLen, const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind, - const char *Checksum, size_t ChecksumLen) { + const char *Checksum, size_t ChecksumLen, + const char *Source, size_t SourceLen) { std::optional llvmCSKind = fromRust(CSKind); std::optional> CSInfo{}; if (llvmCSKind) CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen}); + std::optional oSource{}; + if (Source) + oSource = StringRef(Source, SourceLen); return wrap(Builder->createFile(StringRef(Filename, FilenameLen), - StringRef(Directory, DirectoryLen), CSInfo)); + StringRef(Directory, DirectoryLen), CSInfo, + oSource)); } extern "C" LLVMMetadataRef diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index b84280a3ccf3f..afd5360c81194 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -14,6 +14,12 @@ session_crate_name_empty = crate name must not be empty session_crate_name_invalid = crate names cannot start with a `-`, but `{$s}` has a leading hyphen +session_embed_source_insufficient_dwarf_version = `-Zembed-source=y` requires at least `-Z dwarf-version=5` but DWARF version is {$dwarf_version} + +session_embed_source_requires_debug_info = `-Zembed-source=y` requires debug information to be enabled + +session_embed_source_requires_llvm_backend = `-Zembed-source=y` is only supported on the LLVM codegen backend + session_expr_parentheses_needed = parentheses are required to parse this as an expression session_failed_to_create_profiler = failed to create profiler: {$err} diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 5cc54a5855bbe..f708109b87a0c 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -165,6 +165,20 @@ pub(crate) struct UnsupportedDwarfVersion { pub(crate) dwarf_version: u32, } +#[derive(Diagnostic)] +#[diag(session_embed_source_insufficient_dwarf_version)] +pub(crate) struct EmbedSourceInsufficientDwarfVersion { + pub(crate) dwarf_version: u32, +} + +#[derive(Diagnostic)] +#[diag(session_embed_source_requires_debug_info)] +pub(crate) struct EmbedSourceRequiresDebugInfo; + +#[derive(Diagnostic)] +#[diag(session_embed_source_requires_llvm_backend)] +pub(crate) struct EmbedSourceRequiresLLVMBackend; + #[derive(Diagnostic)] #[diag(session_target_stack_protector_not_supported)] pub(crate) struct StackProtectorNotSupportedForTarget<'a> { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index bf54aae1cfeb0..13aac6669fe4f 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1708,6 +1708,8 @@ options! { them only if an error has not been emitted"), ehcont_guard: bool = (false, parse_bool, [TRACKED], "generate Windows EHCont Guard tables"), + embed_source: bool = (false, parse_bool, [TRACKED], + "embed source text in DWARF debug sections (default: no)"), emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED], "emit a section containing stack size metadata (default: no)"), emit_thin_lto: bool = (true, parse_bool, [TRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index be67baf57f6dc..634f3684b51aa 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -37,8 +37,9 @@ use rustc_target::spec::{ use crate::code_stats::CodeStats; pub use crate::code_stats::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo}; use crate::config::{ - self, CoverageLevel, CrateType, ErrorOutputType, FunctionReturn, Input, InstrumentCoverage, - OptLevel, OutFileName, OutputType, RemapPathScopeComponents, SwitchWithOptPath, + self, CoverageLevel, CrateType, DebugInfo, ErrorOutputType, FunctionReturn, Input, + InstrumentCoverage, OptLevel, OutFileName, OutputType, RemapPathScopeComponents, + SwitchWithOptPath, }; use crate::parse::{add_feature_diagnostics, ParseSess}; use crate::search_paths::{PathKind, SearchPath}; @@ -1300,6 +1301,26 @@ fn validate_commandline_args_with_session_available(sess: &Session) { .emit_err(errors::SplitDebugInfoUnstablePlatform { debuginfo: sess.split_debuginfo() }); } + if sess.opts.unstable_opts.embed_source { + let dwarf_version = + sess.opts.unstable_opts.dwarf_version.unwrap_or(sess.target.default_dwarf_version); + + let uses_llvm_backend = + matches!(sess.opts.unstable_opts.codegen_backend.as_deref(), None | Some("llvm")); + + if dwarf_version < 5 { + sess.dcx().emit_warn(errors::EmbedSourceInsufficientDwarfVersion { dwarf_version }); + } + + if sess.opts.debuginfo == DebugInfo::None { + sess.dcx().emit_warn(errors::EmbedSourceRequiresDebugInfo); + } + + if !uses_llvm_backend { + sess.dcx().emit_warn(errors::EmbedSourceRequiresLLVMBackend); + } + } + if sess.opts.unstable_opts.instrument_xray.is_some() && !sess.target.options.supports_xray { sess.dcx().emit_err(errors::InstrumentationNotSupported { us: "XRay".to_string() }); } diff --git a/src/doc/unstable-book/src/compiler-flags/embed-source.md b/src/doc/unstable-book/src/compiler-flags/embed-source.md new file mode 100644 index 0000000000000..01a11e3779712 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/embed-source.md @@ -0,0 +1,12 @@ +# `embed-source` + +This flag controls whether the compiler embeds the program source code text into +the object debug information section. It takes one of the following values: + +* `y`, `yes`, `on` or `true`: put source code in debug info. +* `n`, `no`, `off`, `false` or no value: omit source code from debug info (the default). + +This flag is ignored in configurations that don't emit DWARF debug information +and is ignored on non-LLVM backends. `-Z embed-source` requires DWARFv5. Use +`-Z dwarf-version=5` to control the compiler's DWARF target version and `-g` to +enable debug info generation. From 608901b9c07d7d2f3e2803378c4f0cc07c61bc36 Mon Sep 17 00:00:00 2001 From: Mrmaxmeier Date: Tue, 16 Jul 2024 20:50:28 +0200 Subject: [PATCH 02/21] Add run-make test for -Zembed-source=yes --- tests/run-make/embed-source-dwarf/main.rs | 2 + tests/run-make/embed-source-dwarf/rmake.rs | 70 ++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 tests/run-make/embed-source-dwarf/main.rs create mode 100644 tests/run-make/embed-source-dwarf/rmake.rs diff --git a/tests/run-make/embed-source-dwarf/main.rs b/tests/run-make/embed-source-dwarf/main.rs new file mode 100644 index 0000000000000..c80af84f41415 --- /dev/null +++ b/tests/run-make/embed-source-dwarf/main.rs @@ -0,0 +1,2 @@ +// hello +fn main() {} diff --git a/tests/run-make/embed-source-dwarf/rmake.rs b/tests/run-make/embed-source-dwarf/rmake.rs new file mode 100644 index 0000000000000..06d550121b0de --- /dev/null +++ b/tests/run-make/embed-source-dwarf/rmake.rs @@ -0,0 +1,70 @@ +//@ ignore-windows +//@ ignore-apple + +// LLVM 17's embed-source implementation requires that source code is attached +// for all files in the output DWARF debug info. This restriction was lifted in +// LLVM 18 (87e22bdd2bd6d77d782f9d64b3e3ae5bdcd5080d). +//@ min-llvm-version: 18 + +// This test should be replaced with one in tests/debuginfo once we can easily +// tell via GDB or LLDB if debuginfo contains source code. Cheap tricks in LLDB +// like setting an invalid source map path don't appear to work, maybe this'll +// become easier once GDB supports DWARFv6? + +use std::collections::HashMap; +use std::path::PathBuf; +use std::rc::Rc; + +use gimli::{AttributeValue, EndianRcSlice, Reader, RunTimeEndian}; +use object::{Object, ObjectSection}; +use run_make_support::{gimli, object, rfs, rustc}; + +fn main() { + let output = PathBuf::from("embed-source-main"); + rustc() + .input("main.rs") + .output(&output) + .arg("-g") + .arg("-Zembed-source=yes") + .arg("-Zdwarf-version=5") + .run(); + let output = rfs::read(output); + let obj = object::File::parse(output.as_slice()).unwrap(); + let endian = if obj.is_little_endian() { RunTimeEndian::Little } else { RunTimeEndian::Big }; + let dwarf = gimli::Dwarf::load(|section| -> Result<_, ()> { + let data = obj.section_by_name(section.name()).map(|s| s.uncompressed_data().unwrap()); + Ok(EndianRcSlice::new(Rc::from(data.unwrap_or_default().as_ref()), endian)) + }) + .unwrap(); + + let mut sources = HashMap::new(); + + let mut iter = dwarf.units(); + while let Some(header) = iter.next().unwrap() { + let unit = dwarf.unit(header).unwrap(); + let unit = unit.unit_ref(&dwarf); + + if let Some(program) = &unit.line_program { + let header = program.header(); + for file in header.file_names() { + if let Some(source) = file.source() { + let path = unit + .attr_string(file.path_name()) + .unwrap() + .to_string_lossy() + .unwrap() + .to_string(); + let source = + unit.attr_string(source).unwrap().to_string_lossy().unwrap().to_string(); + if !source.is_empty() { + sources.insert(path, source); + } + } + } + } + } + + dbg!(&sources); + assert_eq!(sources.len(), 1); + assert_eq!(sources.get("main.rs").unwrap(), "// hello\nfn main() {}\n"); +} From e65a48efd9b711281c70667c5392de70a9e1f7c3 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 1 Aug 2024 11:59:47 -0700 Subject: [PATCH 03/21] Document WebAssembly target feature expectations This commit is a result of the discussion on #128475 and incorporates parts of #109807 as well. This is all done as a new page of documentation for the `wasm32-unknown-unknown` target which previously did not exist. This new page goes into details about the preexisting target and additionally documents the expectations for WebAssembly features and code generation. The tl;dr is that LLVM will enable features over time after most engines have had support for awhile. Compiling without features requires `-Ctarget-cpu=mvp` to rustc plus `-Zbuild-std` to Cargo. Closes #109807 Closes #128475 --- src/doc/rustc/src/platform-support.md | 2 +- .../wasm32-unknown-unknown.md | 154 ++++++++++++++++++ .../src/platform-support/wasm32-wasip1.md | 7 + .../src/platform-support/wasm32-wasip2.md | 7 + 4 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index cbb338f481172..1fb7d2d150385 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -190,7 +190,7 @@ target | std | notes [`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 `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-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 diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md new file mode 100644 index 0000000000000..03126eaa50cbb --- /dev/null +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md @@ -0,0 +1,154 @@ +# `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 not 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 hosts. + +## 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 not exact number of +months or engines that are required to enable features by default. + +[proposals]: https://github.com/WebAssembly/proposals + +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 RUSTFLAG=-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 can 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. diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip1.md b/src/doc/rustc/src/platform-support/wasm32-wasip1.md index fb70bbdc2b403..7a7cac9aeeb1e 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasip1.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasip1.md @@ -132,3 +132,10 @@ 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 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 across all WebAssembly targets. For more information on WebAssembly +features see the documentation for +[`wasm32-unknown-unknokwn`](./wasm32-unknown-unknown.md) diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip2.md b/src/doc/rustc/src/platform-support/wasm32-wasip2.md index 1e53fbc178e2e..e4ef65bcfec55 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasip2.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasip2.md @@ -61,3 +61,10 @@ It's recommended to conditionally compile code for this target with: ```text #[cfg(all(target_os = "wasi", target_env = "p2"))] ``` + +## Enabled WebAssembly features + +The default set of WebAssembly features enabled for compilation is currently the +same across all WebAssembly targets. For more information on WebAssembly +features see the documentation for +[`wasm32-unknown-unknokwn`](./wasm32-unknown-unknown.md) From dea3846edc94ac2b840458594b2772f0c960e329 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 1 Aug 2024 12:16:42 -0700 Subject: [PATCH 04/21] Review comments --- .../src/platform-support/wasm32-unknown-unknown.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md index 03126eaa50cbb..85915cf90a9c3 100644 --- a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md @@ -6,7 +6,7 @@ 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 not standard for what functions can be +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. @@ -86,13 +86,13 @@ $ file foo.wasm ## Cross-compilation -This target can be cross-compiled from any hosts. +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 +`println!` doesn't work in the standard library. It's recommended to test the `wasm32-wasip1` target instead for WebAssembly compatibility. ## Conditionally compiling code @@ -118,7 +118,7 @@ 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 not exact number of +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 @@ -144,7 +144,8 @@ 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 can be found through: +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 @@ -152,3 +153,5 @@ $ 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 From 927633cae4eec359901523d8fa9a962749c89560 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 1 Aug 2024 12:20:44 -0700 Subject: [PATCH 05/21] Add a note about libraries and `#[target_feature]` --- .../wasm32-unknown-unknown.md | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md index 85915cf90a9c3..2bd50f6e6db8c 100644 --- a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md @@ -155,3 +155,36 @@ 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 sufficent 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 +#[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 +#[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. From cfe3ea65d29dbed12cf5466b51dbeb094a3729f1 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 1 Aug 2024 13:13:19 -0700 Subject: [PATCH 06/21] Add new page to SUMMARY.md --- src/doc/rustc/src/SUMMARY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 08460af15d4c7..c5622a5e14e20 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -78,6 +78,7 @@ - [wasm32-wasip1](platform-support/wasm32-wasip1.md) - [wasm32-wasip1-threads](platform-support/wasm32-wasip1-threads.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) - [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md) - [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md) From ce7f1b77f400bbf42e2ca9628dec087c1a2605c5 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 1 Aug 2024 14:33:04 -0700 Subject: [PATCH 07/21] Ignore two new doc blocks in testing --- src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md index 2bd50f6e6db8c..a4b547bd1fff1 100644 --- a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md @@ -163,7 +163,7 @@ 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 +```rust,ignore #[target_feature(enable = "simd128")] fn foo() { // ... @@ -176,7 +176,7 @@ 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 +```rust,ignore #[cfg(target_feature = "simd128")] fn foo() { // ... From b6f65a4b224ec74918ecc5e02527c72e75a18f89 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 1 Aug 2024 14:36:55 -0700 Subject: [PATCH 08/21] Document on-by-default features --- .../rustc/src/platform-support/wasm32-unknown-unknown.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md index a4b547bd1fff1..5de80fea6bf76 100644 --- a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md @@ -123,6 +123,14 @@ 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 From a5082ef5a8de1296d5d623b4a76711f2e3176e26 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 1 Aug 2024 15:02:32 -0700 Subject: [PATCH 09/21] Appease tidy --- src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md index 5de80fea6bf76..1c2894e3a7390 100644 --- a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md @@ -171,7 +171,7 @@ 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 +```rust,ignore (not-always-compiled-to-wasm) #[target_feature(enable = "simd128")] fn foo() { // ... @@ -184,7 +184,7 @@ 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 +```rust,ignore (not-always-compiled-to-wasm) #[cfg(target_feature = "simd128")] fn foo() { // ... From 06197ef3c111fad0498d30b631a141de1aed2843 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 2 Aug 2024 06:59:45 -0700 Subject: [PATCH 10/21] Review comments --- .../src/platform-support/wasm32-unknown-unknown.md | 4 ++-- .../src/platform-support/wasm32-wasip1-threads.md | 14 ++++++++++++++ .../rustc/src/platform-support/wasm32-wasip1.md | 5 ++--- .../rustc/src/platform-support/wasm32-wasip2.md | 5 ++--- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md index 1c2894e3a7390..ee37e5e90cfb4 100644 --- a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md @@ -141,7 +141,7 @@ Rust standard library additionally must be recompiled. Compiling all code for the initial release of WebAssembly looks like: ```sh -$ export RUSTFLAG=-Ctarget-cpu=mvp +$ export RUSTFLAGS=-Ctarget-cpu=mvp $ cargo +nightly build -Zbuild-std=panic_abort,std --target wasm32-unknown-unknown ``` @@ -166,7 +166,7 @@ about the supported WebAssembly features the engine has. 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 sufficent to disable all WebAssembly features. If the +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: diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md b/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md index c3eda26ca8ef9..aafb64e6778c2 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md @@ -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 `target_feature = "atomics"` is Nightly-only. Note that the precise `#[cfg]` 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 is similar to +[`wasm32-unknown-unknokwn`](./wasm32-unknown-unknown.md) but two more features +are included: + +* `bulk-memory` +* `atomics` + +For more information about features see the documentation for +[`wasm32-unknown-unknokwn`](./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. diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip1.md b/src/doc/rustc/src/platform-support/wasm32-wasip1.md index 7a7cac9aeeb1e..103cb38be09b0 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasip1.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasip1.md @@ -136,6 +136,5 @@ 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 across all WebAssembly targets. For more information on WebAssembly -features see the documentation for -[`wasm32-unknown-unknokwn`](./wasm32-unknown-unknown.md) +same as [`wasm32-unknown-unknokwn`](./wasm32-unknown-unknown.md). See the +documentation there for more information. diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip2.md b/src/doc/rustc/src/platform-support/wasm32-wasip2.md index e4ef65bcfec55..7d22e9e60d5ad 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasip2.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasip2.md @@ -65,6 +65,5 @@ It's recommended to conditionally compile code for this target with: ## Enabled WebAssembly features The default set of WebAssembly features enabled for compilation is currently the -same across all WebAssembly targets. For more information on WebAssembly -features see the documentation for -[`wasm32-unknown-unknokwn`](./wasm32-unknown-unknown.md) +same as [`wasm32-unknown-unknokwn`](./wasm32-unknown-unknown.md). See the +documentation there for more information. From 6899f5a8e12986ee16e028f1597963d0de668aca Mon Sep 17 00:00:00 2001 From: Mrmaxmeier Date: Tue, 6 Aug 2024 20:31:12 +0200 Subject: [PATCH 11/21] -Zembed-source: Don't try to warn about incompatible codegen backends --- compiler/rustc_session/messages.ftl | 2 -- compiler/rustc_session/src/errors.rs | 4 ---- compiler/rustc_session/src/session.rs | 7 ------- 3 files changed, 13 deletions(-) diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index afd5360c81194..01c371ee49884 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -18,8 +18,6 @@ session_embed_source_insufficient_dwarf_version = `-Zembed-source=y` requires at session_embed_source_requires_debug_info = `-Zembed-source=y` requires debug information to be enabled -session_embed_source_requires_llvm_backend = `-Zembed-source=y` is only supported on the LLVM codegen backend - session_expr_parentheses_needed = parentheses are required to parse this as an expression session_failed_to_create_profiler = failed to create profiler: {$err} diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index f708109b87a0c..15bbd4ff7bf4b 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -175,10 +175,6 @@ pub(crate) struct EmbedSourceInsufficientDwarfVersion { #[diag(session_embed_source_requires_debug_info)] pub(crate) struct EmbedSourceRequiresDebugInfo; -#[derive(Diagnostic)] -#[diag(session_embed_source_requires_llvm_backend)] -pub(crate) struct EmbedSourceRequiresLLVMBackend; - #[derive(Diagnostic)] #[diag(session_target_stack_protector_not_supported)] pub(crate) struct StackProtectorNotSupportedForTarget<'a> { diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 634f3684b51aa..e2ef144e732a4 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1305,9 +1305,6 @@ fn validate_commandline_args_with_session_available(sess: &Session) { let dwarf_version = sess.opts.unstable_opts.dwarf_version.unwrap_or(sess.target.default_dwarf_version); - let uses_llvm_backend = - matches!(sess.opts.unstable_opts.codegen_backend.as_deref(), None | Some("llvm")); - if dwarf_version < 5 { sess.dcx().emit_warn(errors::EmbedSourceInsufficientDwarfVersion { dwarf_version }); } @@ -1315,10 +1312,6 @@ fn validate_commandline_args_with_session_available(sess: &Session) { if sess.opts.debuginfo == DebugInfo::None { sess.dcx().emit_warn(errors::EmbedSourceRequiresDebugInfo); } - - if !uses_llvm_backend { - sess.dcx().emit_warn(errors::EmbedSourceRequiresLLVMBackend); - } } if sess.opts.unstable_opts.instrument_xray.is_some() && !sess.target.options.supports_xray { From 7d2595f78315acf6b00c0a28b5fea623bbc44135 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 8 Aug 2024 23:36:25 -0700 Subject: [PATCH 12/21] Review comments --- .../rustc/src/platform-support/wasm32-wasip1-threads.md | 8 ++++---- src/doc/rustc/src/platform-support/wasm32-wasip1.md | 2 +- src/doc/rustc/src/platform-support/wasm32-wasip2.md | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md b/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md index aafb64e6778c2..994c0f4bbb3e9 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md @@ -165,14 +165,14 @@ 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 is similar to -[`wasm32-unknown-unknokwn`](./wasm32-unknown-unknown.md) but two more features -are included: +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-unknokwn`](./wasm32-unknown-unknown.md), but note that the +[`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. diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip1.md b/src/doc/rustc/src/platform-support/wasm32-wasip1.md index 103cb38be09b0..0e4def6768dc4 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasip1.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasip1.md @@ -136,5 +136,5 @@ 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-unknokwn`](./wasm32-unknown-unknown.md). See the +same as [`wasm32-unknown-unknown`](./wasm32-unknown-unknown.md). See the documentation there for more information. diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip2.md b/src/doc/rustc/src/platform-support/wasm32-wasip2.md index 7d22e9e60d5ad..bb2348b201e39 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasip2.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasip2.md @@ -65,5 +65,5 @@ It's recommended to conditionally compile code for this target with: ## Enabled WebAssembly features The default set of WebAssembly features enabled for compilation is currently the -same as [`wasm32-unknown-unknokwn`](./wasm32-unknown-unknown.md). See the +same as [`wasm32-unknown-unknown`](./wasm32-unknown-unknown.md). See the documentation there for more information. From 6a8ec81e1c894287bfee2a6263c8044a5ffc98a9 Mon Sep 17 00:00:00 2001 From: apiraino Date: Mon, 19 Aug 2024 12:40:23 +0200 Subject: [PATCH 13/21] Add a missing compatibility note in the 1.80.0 release notes --- RELEASES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASES.md b/RELEASES.md index 2c91ddf782674..a93aa432187cb 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -143,6 +143,7 @@ Compatibility Notes - [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/) - [`std::sync::ReentrantLockGuard` 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) +- [alloc: implement FromIterator for Box](https://github.com/rust-lang/rust/pull/99969/) From cd7cc3f071a5b4bf7b621db3160bc960b5faeaa7 Mon Sep 17 00:00:00 2001 From: apiraino Date: Mon, 19 Aug 2024 14:03:16 +0200 Subject: [PATCH 14/21] Update RELEASES.md Co-authored-by: Mark Rousskov --- RELEASES.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index a93aa432187cb..7c15a3ccd1b74 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -143,7 +143,8 @@ Compatibility Notes - [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/) - [`std::sync::ReentrantLockGuard` 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) -- [alloc: implement FromIterator for Box](https://github.com/rust-lang/rust/pull/99969/) +- [Type inference will fail in some cases due to a new impl of FromIterator for Box](https://github.com/rust-lang/rust/pull/99969/) + Notably this breaks versions of the `time` crate before 0.3.55, due to no longer inferring the right impl. From 7613eee55ea9fc0bdaff6bb482cc0650a5bf3e9a Mon Sep 17 00:00:00 2001 From: apiraino Date: Mon, 19 Aug 2024 17:33:53 +0200 Subject: [PATCH 15/21] Update RELEASES.md Co-authored-by: Jubilee <46493976+workingjubilee@users.noreply.github.com> --- RELEASES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 7c15a3ccd1b74..852af4389ea89 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -144,7 +144,7 @@ Compatibility Notes - [Detect unused structs even when implementing private traits](https://github.com/rust-lang/rust/pull/122382/) - [`std::sync::ReentrantLockGuard` 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 a new impl of FromIterator for Box](https://github.com/rust-lang/rust/pull/99969/) - Notably this breaks versions of the `time` crate before 0.3.55, due to no longer inferring the right impl. + Notably this breaks versions of the `time` crate before 0.3.36, due to no longer inferring the right impl. From dbad7581348d71822573e906c165bd08c366f196 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Mon, 19 Aug 2024 20:31:48 +0200 Subject: [PATCH 16/21] Stabilize feature `char_indices_offset` --- library/core/src/lib.rs | 1 - library/core/src/str/iter.rs | 15 +++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index e3640627c562a..bbfe412fbcf1b 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -110,7 +110,6 @@ #![cfg_attr(bootstrap, feature(offset_of_nested))] #![feature(array_ptr_get)] #![feature(asm_experimental_arch)] -#![feature(char_indices_offset)] #![feature(const_align_of_val)] #![feature(const_align_of_val_raw)] #![feature(const_align_offset)] diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 06f796f9f3ad8..681ec79c0b7bf 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -241,24 +241,35 @@ impl<'a> CharIndices<'a> { /// Returns the byte position of the next character, or the length /// 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 /// /// ``` - /// #![feature(char_indices_offset)] /// 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); + /// // As expected, the first call to `next()` also returns 0 as index. /// 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); + /// // ... which matches the index returned by the next call to `next()`. /// 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.next(), None); /// ``` #[inline] #[must_use] - #[unstable(feature = "char_indices_offset", issue = "83871")] + #[stable(feature = "char_indices_offset", since = "CURRENT_RUSTC_VERSION")] pub fn offset(&self) -> usize { self.front_offset } From 87e4b6789c43c44f07211defbd8c036bc0245562 Mon Sep 17 00:00:00 2001 From: apiraino Date: Thu, 22 Aug 2024 09:19:22 +0200 Subject: [PATCH 17/21] Update RELEASES.md Co-authored-by: Josh Stone --- RELEASES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 852af4389ea89..5e4827be4ecfd 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -143,8 +143,8 @@ Compatibility Notes - [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/) - [`std::sync::ReentrantLockGuard` 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 a new impl of FromIterator for Box](https://github.com/rust-lang/rust/pull/99969/) - Notably this breaks versions of the `time` crate before 0.3.36, due to no longer inferring the right impl. +- [Type inference will fail in some cases due to new implementations of `FromIterator for Box`.](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<[_]>`. From 6a878a9630945cd6a61ad5e83ec5c543c6e8dab7 Mon Sep 17 00:00:00 2001 From: Urgau Date: Thu, 22 Aug 2024 13:30:50 +0200 Subject: [PATCH 18/21] Fix handling of macro arguments within the `dropping_copy_types lint --- .../rustc_lint/src/drop_forget_useless.rs | 5 +++-- .../ui/lint/dropping_copy_types-macros.fixed | 12 +++++++++++ tests/ui/lint/dropping_copy_types-macros.rs | 12 +++++++++++ .../ui/lint/dropping_copy_types-macros.stderr | 21 +++++++++++++++++++ 4 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 tests/ui/lint/dropping_copy_types-macros.fixed create mode 100644 tests/ui/lint/dropping_copy_types-macros.rs create mode 100644 tests/ui/lint/dropping_copy_types-macros.stderr diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs index 2060858cc8af0..a9de258e005c9 100644 --- a/compiler/rustc_lint/src/drop_forget_useless.rs +++ b/compiler/rustc_lint/src/drop_forget_useless.rs @@ -151,10 +151,11 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless { && let Node::Stmt(stmt) = node && let StmtKind::Semi(e) = stmt.kind && e.hir_id == expr.hir_id + && let Some(arg_span) = arg.span.find_ancestor_inside(expr.span) { UseLetUnderscoreIgnoreSuggestion::Suggestion { - start_span: expr.span.shrink_to_lo().until(arg.span), - end_span: arg.span.shrink_to_hi().until(expr.span.shrink_to_hi()), + start_span: expr.span.shrink_to_lo().until(arg_span), + end_span: arg_span.shrink_to_hi().until(expr.span.shrink_to_hi()), } } else { UseLetUnderscoreIgnoreSuggestion::Note diff --git a/tests/ui/lint/dropping_copy_types-macros.fixed b/tests/ui/lint/dropping_copy_types-macros.fixed new file mode 100644 index 0000000000000..a8ceedadc8063 --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-macros.fixed @@ -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` +} diff --git a/tests/ui/lint/dropping_copy_types-macros.rs b/tests/ui/lint/dropping_copy_types-macros.rs new file mode 100644 index 0000000000000..b249b0c868f37 --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-macros.rs @@ -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` +} diff --git a/tests/ui/lint/dropping_copy_types-macros.stderr b/tests/ui/lint/dropping_copy_types-macros.stderr new file mode 100644 index 0000000000000..117e9f4fe099c --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-macros.stderr @@ -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 + From f1fac42f4a6aa2f9535a32db91c7f9c93220d5a4 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Wed, 21 Aug 2024 09:21:29 +0000 Subject: [PATCH 19/21] llvm 20: adapt integer comparison tests The LLVM commit https://github.com/llvm/llvm-project/commit/abf69a167bbc99054871e3f9cc8810bbebcb6747 changed the IR in a few comparison tests: https://buildkite.com/llvm-project/rust-llvm-integrate-prototype/builds/30500#01917017-26fe-4a4d-956b-725a2903e5a8 Adapted accordingly. --- tests/assembly/x86_64-cmp.rs | 42 ++++++++++++++++++++++++------------ tests/codegen/integer-cmp.rs | 21 +++++++++++------- 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/tests/assembly/x86_64-cmp.rs b/tests/assembly/x86_64-cmp.rs index 31efdda1bfafa..67b7ff99ae2d9 100644 --- a/tests/assembly/x86_64-cmp.rs +++ b/tests/assembly/x86_64-cmp.rs @@ -1,6 +1,9 @@ -//@ revisions: DEBUG OPTIM +//@ revisions: DEBUG LLVM-PRE-20-OPTIM LLVM-20-OPTIM //@ [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 //@ compile-flags: --crate-type=lib -C llvm-args=-x86-asm-syntax=intel //@ only-x86_64 @@ -21,12 +24,18 @@ pub fn signed_cmp(a: i16, b: i16) -> std::cmp::Ordering { // DEBUG: and // DEBUG: sub - // OPTIM: xor - // OPTIM: cmp - // OPTIM: setne - // OPTIM: mov - // OPTIM: cmovge - // OPTIM: ret + // LLVM-PRE-20-OPTIM: xor + // LLVM-PRE-20-OPTIM: cmp + // LLVM-PRE-20-OPTIM: setne + // LLVM-PRE-20-OPTIM: mov + // LLVM-PRE-20-OPTIM: cmovge + // 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) } @@ -41,11 +50,16 @@ pub fn unsigned_cmp(a: u16, b: u16) -> std::cmp::Ordering { // DEBUG: and // DEBUG: sub - // OPTIM: xor - // OPTIM: cmp - // OPTIM: setne - // OPTIM: mov - // OPTIM: cmovae - // OPTIM: ret + // LLVM-PRE-20-OPTIM: xor + // LLVM-PRE-20-OPTIM: cmp + // LLVM-PRE-20-OPTIM: setne + // LLVM-PRE-20-OPTIM: mov + // LLVM-PRE-20-OPTIM: cmovae + // 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) } diff --git a/tests/codegen/integer-cmp.rs b/tests/codegen/integer-cmp.rs index bba112b246f3f..8df68d8d4906e 100644 --- a/tests/codegen/integer-cmp.rs +++ b/tests/codegen/integer-cmp.rs @@ -1,6 +1,9 @@ // This is test for more optimal Ord implementation for integers. // See 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 #![crate_type = "lib"] @@ -10,19 +13,21 @@ use std::cmp::Ordering; // CHECK-LABEL: @cmp_signed #[no_mangle] pub fn cmp_signed(a: i64, b: i64) -> Ordering { - // CHECK: icmp slt - // CHECK: icmp ne - // CHECK: zext i1 - // CHECK: select i1 + // llvm-20: @llvm.scmp.i8.i64 + // llvm-pre-20: icmp slt + // llvm-pre-20: icmp ne + // llvm-pre-20: zext i1 + // llvm-pre-20: select i1 a.cmp(&b) } // CHECK-LABEL: @cmp_unsigned #[no_mangle] pub fn cmp_unsigned(a: u32, b: u32) -> Ordering { - // CHECK: icmp ult - // CHECK: icmp ne - // CHECK: zext i1 - // CHECK: select i1 + // llvm-20: @llvm.ucmp.i8.i32 + // llvm-pre-20: icmp ult + // llvm-pre-20: icmp ne + // llvm-pre-20: zext i1 + // llvm-pre-20: select i1 a.cmp(&b) } From 4dd9be44619896b6af2005fba63f05a10f8e31f1 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Mon, 29 Jul 2024 11:12:30 -0400 Subject: [PATCH 20/21] Enable `f16` tests on x86 and x86-64 Since the `compiler_builtins` update [1], ABI bugs on x86 should be resolved. Enable tests for f16 on these platforms now. `f16` math functions (`reliable_f16_math`) are still excluded because there is an LLVM crash for powi [2]. [1]: https://github.com/rust-lang/rust/pull/125016 [2]: https://github.com/llvm/llvm-project/issues/105747 --- library/std/build.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/library/std/build.rs b/library/std/build.rs index 35a5977b6ebaf..26b8669d382d9 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -103,9 +103,6 @@ fn main() { ("arm64ec", _) => false, // MinGW ABI bugs ("x86_64", "windows") => false, - // x86 has ABI bugs that show up with optimizations. This should be partially fixed with - // the compiler-builtins update. - ("x86" | "x86_64", _) => false, // Missing `__gnu_h2f_ieee` and `__gnu_f2h_ieee` ("powerpc" | "powerpc64", _) => false, // Missing `__gnu_h2f_ieee` and `__gnu_f2h_ieee` @@ -140,17 +137,17 @@ fn main() { _ => false, }; - // These are currently empty, but will fill up as some platforms move from completely - // unreliable to reliable basics but unreliable math. + // Configure platforms that have reliable basics but may have unreliable math. // LLVM is currenlty adding missing routines, let has_reliable_f16_math = has_reliable_f16 && match (target_arch.as_str(), target_os.as_str()) { // FIXME: Disabled on Miri as the intrinsics are not implemented yet. _ if is_miri => false, - // Currently nothing special. Hooray! - // This will change as platforms gain better better support for standard ops but math - // lags behind. + // x86 has a crash for `powi`: + ("x86" | "x86_64", _) => false, + // Assume that working `f16` means working `f16` math for most platforms, since + // operations just go through `f32`. _ => true, }; From 186ff6a4401c2047be47b85f2cef373c8711a73e Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Mon, 29 Jul 2024 11:28:45 -0400 Subject: [PATCH 21/21] Change `f16` doctests in core to run on x86-64 Since `f16` now works on x86 and x86-64, change doctests to use this instead of aarch64. This is to make sure any changes get run in PR CI. --- library/core/src/num/f16.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index 41bd34a270238..c00bebadaadd0 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -261,7 +261,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(target_arch = "x86_64")] { /// /// let nan = f16::NAN; /// let f = 7.0_f16; @@ -293,7 +293,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(target_arch = "x86_64")] { /// /// let f = 7.0f16; /// let inf = f16::INFINITY; @@ -319,7 +319,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(target_arch = "x86_64")] { /// /// let f = 7.0f16; /// let inf: f16 = f16::INFINITY; @@ -347,7 +347,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(target_arch = "x86_64")] { /// /// let min = f16::MIN_POSITIVE; // 6.1035e-5 /// let max = f16::MAX; @@ -377,7 +377,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(target_arch = "x86_64")] { /// /// let min = f16::MIN_POSITIVE; // 6.1035e-5 /// let max = f16::MAX; @@ -409,7 +409,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(target_arch = "x86_64")] { /// /// use std::num::FpCategory; /// @@ -867,7 +867,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(target_arch = "x86_64")] { /// /// let value = 4.6_f16; /// let rounded = unsafe { value.to_int_unchecked::() }; @@ -910,7 +910,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(target_arch = "x86_64")] { /// /// # // FIXME(f16_f128): enable this once const casting works /// # // assert_ne!((1f16).to_bits(), 1f16 as u128); // to_bits() is not casting! @@ -958,7 +958,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(target_arch = "x86_64")] { /// /// let v = f16::from_bits(0x4a40); /// assert_eq!(v, 12.5); @@ -1071,7 +1071,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(target_arch = "x86_64")] { /// /// let value = f16::from_be_bytes([0x4a, 0x40]); /// assert_eq!(value, 12.5); @@ -1094,7 +1094,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(target_arch = "x86_64")] { /// /// let value = f16::from_le_bytes([0x40, 0x4a]); /// assert_eq!(value, 12.5); @@ -1124,7 +1124,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(target_arch = "x86_64")] { /// /// let value = f16::from_ne_bytes(if cfg!(target_endian = "big") { /// [0x4a, 0x40] @@ -1257,7 +1257,7 @@ impl f16 { /// /// ``` /// #![feature(f16)] - /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885 + /// # #[cfg(target_arch = "x86_64")] { /// /// assert!((-3.0f16).clamp(-2.0, 1.0) == -2.0); /// assert!((0.0f16).clamp(-2.0, 1.0) == 0.0);