From bed0c9d97f098b71f4968808ab16d9ba40bce49c Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Sat, 12 Aug 2023 14:13:41 -0600 Subject: [PATCH 01/14] [style 2024] Combine all last arg delimited exprs --- src/doc/style-guide/src/editions.md | 4 ++ src/doc/style-guide/src/expressions.md | 55 ++++++++++++++++++++++---- 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/src/doc/style-guide/src/editions.md b/src/doc/style-guide/src/editions.md index 5c67a185b8ffa..0d60b01fac3a1 100644 --- a/src/doc/style-guide/src/editions.md +++ b/src/doc/style-guide/src/editions.md @@ -36,6 +36,10 @@ For a full history of changes in the Rust 2024 style edition, see the git history of the style guide. Notable changes in the Rust 2024 style edition include: +- [#114764](https://github.com/rust-lang/rust/pull/114764) As the last member + of a delimited expression, delimited expressions are generally combinable, + regardless of the number of members. Previously only applied with exactly + one member (except for closures with explicit blocks). - Miscellaneous `rustfmt` bugfixes. ## Rust 2015/2018/2021 style edition diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md index 32c604f9f3e10..a88404e87fb17 100644 --- a/src/doc/style-guide/src/expressions.md +++ b/src/doc/style-guide/src/expressions.md @@ -801,11 +801,11 @@ E.g., `&&Some(foo)` matches, `Foo(4, Bar)` does not. ## Combinable expressions -Where a function call has a single argument, and that argument is formatted -across multiple-lines, format the outer call as if it were a single-line call, +When the last argument in a function call is formatted across +multiple-lines, format the outer call as if it were a single-line call, if the result fits. Apply the same combining behaviour to any similar expressions which have multi-line, block-indented lists of sub-expressions -delimited by parentheses (e.g., macros or tuple struct literals). E.g., +delimited by parentheses, brackets, or braces. E.g., ```rust foo(bar( @@ -831,20 +831,61 @@ let arr = [combinable( an_expr, another_expr, )]; + +let x = Thing(an_expr, another_expr, match cond { + A => 1, + B => 2, +}); + +let x = format!("Stuff: {}", [ + an_expr, + another_expr, +]); + +let x = func(an_expr, another_expr, SomeStruct { + field: this_is_long, + another_field: 123, +}); ``` Apply this behavior recursively. -For a function with multiple arguments, if the last argument is a multi-line -closure with an explicit block, there are no other closure arguments, and all -the arguments and the first line of the closure fit on the first line, use the -same combining behavior: +If the last argument is a multi-line closure with an explicit block, +only apply the combining behavior if there are no other closure arguments. ```rust +// Combinable foo(first_arg, x, |param| { action(); foo(param) }) +// Not combinable, because the closure is not the last argument +foo( + first_arg, + |param| { + action(); + foo(param) + }, + whatever, +) +// Not combinable, because the first line of the closure does not fit +foo( + first_arg, + x, + move |very_long_param_causing_line_to_overflow| -> Bar { + action(); + foo(param) + }, +) +// Not combinable, because there is more than one closure argument +foo( + first_arg, + |x| x.bar(), + |param| { + action(); + foo(param) + }, +) ``` ## Ranges From b152de29c59fc0d34ab26b0be445a45e9ffe2dfb Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 5 Jan 2024 13:23:05 +1100 Subject: [PATCH 02/14] coverage: Discard code regions that might cause fatal errors in `llvm-cov` --- .../rustc_mir_transform/src/coverage/mod.rs | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index dcd7014f4fc90..4b91f042f007a 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -330,7 +330,7 @@ fn make_code_region( start_line = source_map.doctest_offset_line(&file.name, start_line); end_line = source_map.doctest_offset_line(&file.name, end_line); - Some(CodeRegion { + check_code_region(CodeRegion { file_name, start_line: start_line as u32, start_col: start_col as u32, @@ -339,6 +339,41 @@ fn make_code_region( }) } +/// If `llvm-cov` sees a code region that is improperly ordered (end < start), +/// it will immediately exit with a fatal error. To prevent that from happening, +/// discard regions that are improperly ordered, or might be interpreted in a +/// way that makes them improperly ordered. +fn check_code_region(code_region: CodeRegion) -> Option { + let CodeRegion { file_name: _, start_line, start_col, end_line, end_col } = code_region; + + // Line/column coordinates are supposed to be 1-based. If we ever emit + // coordinates of 0, `llvm-cov` might misinterpret them. + let all_nonzero = [start_line, start_col, end_line, end_col].into_iter().all(|x| x != 0); + // Coverage mappings use the high bit of `end_col` to indicate that a + // region is actually a "gap" region, so make sure it's unset. + let end_col_has_high_bit_unset = (end_col & (1 << 31)) == 0; + // If a region is improperly ordered (end < start), `llvm-cov` will exit + // with a fatal error, which is inconvenient for users and hard to debug. + let is_ordered = (start_line, start_col) <= (end_line, end_col); + + if all_nonzero && end_col_has_high_bit_unset && is_ordered { + Some(code_region) + } else { + debug!( + ?code_region, + ?all_nonzero, + ?end_col_has_high_bit_unset, + ?is_ordered, + "Skipping code region that would be misinterpreted or rejected by LLVM" + ); + if cfg!(debug_assertions) { + // If this happens in a debug build, ICE to make it easier to notice. + bug!("Improper code region: {code_region:?}"); + } + None + } +} + fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { // Only instrument functions, methods, and closures (not constants since they are evaluated // at compile time by Miri). From 41dcba805d8ea2c5142cce7044c146aa15d0358c Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 21 Jan 2024 15:07:11 +1100 Subject: [PATCH 03/14] coverage: Don't instrument `#[automatically_derived]` functions --- .../rustc_mir_transform/src/coverage/mod.rs | 11 +++++ tests/coverage-run-rustdoc/doctest.coverage | 5 +- tests/coverage/bad_counter_ids.cov-map | 16 ------- tests/coverage/bad_counter_ids.coverage | 2 +- tests/coverage/issue-83601.cov-map | 16 ------- tests/coverage/issue-83601.coverage | 3 +- tests/coverage/issue-84561.cov-map | 8 ---- tests/coverage/issue-84561.coverage | 2 +- tests/coverage/partial_eq.cov-map | 48 ------------------- tests/coverage/partial_eq.coverage | 3 +- 10 files changed, 17 insertions(+), 97 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index a11d224e8f1b5..a495dcdbc4e19 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -351,7 +351,18 @@ fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { return false; } + // Don't instrument functions with `#[automatically_derived]` on their + // enclosing impl block, on the assumption that most users won't care about + // coverage for derived impls. + if let Some(impl_of) = tcx.impl_of_method(def_id.to_def_id()) + && tcx.is_automatically_derived(impl_of) + { + trace!("InstrumentCoverage skipped for {def_id:?} (automatically derived)"); + return false; + } + if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NO_COVERAGE) { + trace!("InstrumentCoverage skipped for {def_id:?} (`#[coverage(off)]`)"); return false; } diff --git a/tests/coverage-run-rustdoc/doctest.coverage b/tests/coverage-run-rustdoc/doctest.coverage index 5797784f411cc..5125dc075ee2c 100644 --- a/tests/coverage-run-rustdoc/doctest.coverage +++ b/tests/coverage-run-rustdoc/doctest.coverage @@ -34,8 +34,7 @@ $DIR/doctest.rs: LL| |//! LL| |//! doctest returning a result: LL| 1|//! ``` - LL| 2|//! #[derive(Debug, PartialEq)] - ^1 + LL| 1|//! #[derive(Debug, PartialEq)] LL| 1|//! struct SomeError { LL| 1|//! msg: String, LL| 1|//! } @@ -63,7 +62,7 @@ $DIR/doctest.rs: LL| 1|//! println!("called some_func()"); LL| 1|//! } LL| |//! - LL| 0|//! #[derive(Debug)] + LL| |//! #[derive(Debug)] LL| |//! struct SomeError; LL| |//! LL| |//! extern crate doctest_crate; diff --git a/tests/coverage/bad_counter_ids.cov-map b/tests/coverage/bad_counter_ids.cov-map index 0b8081acfa6d8..3b51e3ef9de66 100644 --- a/tests/coverage/bad_counter_ids.cov-map +++ b/tests/coverage/bad_counter_ids.cov-map @@ -1,19 +1,3 @@ -Function name: ::eq -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0c, 11, 00, 1a] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 12, 17) to (start + 0, 26) - -Function name: ::fmt -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0c, 0a, 00, 0f] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 12, 10) to (start + 0, 15) - Function name: bad_counter_ids::eq_bad Raw bytes (14): 0x[01, 01, 00, 02, 01, 23, 01, 02, 1f, 00, 03, 01, 00, 02] Number of files: 1 diff --git a/tests/coverage/bad_counter_ids.coverage b/tests/coverage/bad_counter_ids.coverage index d69ebf160ea64..5474ec2f78552 100644 --- a/tests/coverage/bad_counter_ids.coverage +++ b/tests/coverage/bad_counter_ids.coverage @@ -9,7 +9,7 @@ LL| |// a too-large counter ID and silently discard the entire function from its LL| |// coverage reports. LL| | - LL| 8|#[derive(Debug, PartialEq, Eq)] + LL| |#[derive(Debug, PartialEq, Eq)] LL| |struct Foo(u32); LL| | LL| 1|fn eq_good() { diff --git a/tests/coverage/issue-83601.cov-map b/tests/coverage/issue-83601.cov-map index f5db3a89750c7..f2447e3c92c8a 100644 --- a/tests/coverage/issue-83601.cov-map +++ b/tests/coverage/issue-83601.cov-map @@ -1,19 +1,3 @@ -Function name: ::eq -Raw bytes (9): 0x[01, 01, 00, 01, 01, 03, 11, 00, 1a] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 3, 17) to (start + 0, 26) - -Function name: ::fmt -Raw bytes (9): 0x[01, 01, 00, 01, 01, 03, 0a, 00, 0f] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 3, 10) to (start + 0, 15) - Function name: issue_83601::main Raw bytes (21): 0x[01, 01, 01, 05, 09, 03, 01, 06, 01, 02, 1c, 05, 03, 09, 01, 1c, 02, 02, 05, 03, 02] Number of files: 1 diff --git a/tests/coverage/issue-83601.coverage b/tests/coverage/issue-83601.coverage index 7995332cad339..e050106e6f0b0 100644 --- a/tests/coverage/issue-83601.coverage +++ b/tests/coverage/issue-83601.coverage @@ -1,7 +1,6 @@ LL| |// Shows that rust-lang/rust/83601 is resolved LL| | - LL| 3|#[derive(Debug, PartialEq, Eq)] - ^2 + LL| |#[derive(Debug, PartialEq, Eq)] LL| |struct Foo(u32); LL| | LL| 1|fn main() { diff --git a/tests/coverage/issue-84561.cov-map b/tests/coverage/issue-84561.cov-map index 6d577b3d4851d..88436964af0f7 100644 --- a/tests/coverage/issue-84561.cov-map +++ b/tests/coverage/issue-84561.cov-map @@ -1,11 +1,3 @@ -Function name: ::eq -Raw bytes (9): 0x[01, 01, 00, 01, 01, 04, 0a, 00, 13] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 4, 10) to (start + 0, 19) - Function name: ::fmt Raw bytes (29): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 8a, 01, 05, 01, 25, 05, 01, 25, 00, 26, 02, 01, 09, 00, 0f, 07, 01, 05, 00, 06] Number of files: 1 diff --git a/tests/coverage/issue-84561.coverage b/tests/coverage/issue-84561.coverage index 9080d95eff5fc..90a2d069d3949 100644 --- a/tests/coverage/issue-84561.coverage +++ b/tests/coverage/issue-84561.coverage @@ -1,7 +1,7 @@ LL| |// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results. LL| | LL| |// failure-status: 101 - LL| 21|#[derive(PartialEq, Eq)] + LL| |#[derive(PartialEq, Eq)] LL| |struct Foo(u32); LL| | LL| |#[rustfmt::skip] diff --git a/tests/coverage/partial_eq.cov-map b/tests/coverage/partial_eq.cov-map index 5e4aae0260b5c..80670fbfa5a75 100644 --- a/tests/coverage/partial_eq.cov-map +++ b/tests/coverage/partial_eq.cov-map @@ -1,51 +1,3 @@ -Function name: ::clone (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 04, 0a, 00, 0f] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 4, 10) to (start + 0, 15) - -Function name: ::cmp (unused) -Raw bytes (14): 0x[01, 01, 00, 02, 00, 04, 33, 00, 34, 00, 00, 35, 00, 36] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 2 -- Code(Zero) at (prev + 4, 51) to (start + 0, 52) -- Code(Zero) at (prev + 0, 53) to (start + 0, 54) - -Function name: ::eq (unused) -Raw bytes (14): 0x[01, 01, 00, 02, 00, 04, 18, 00, 19, 00, 00, 20, 00, 21] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 2 -- Code(Zero) at (prev + 4, 24) to (start + 0, 25) -- Code(Zero) at (prev + 0, 32) to (start + 0, 33) - -Function name: ::partial_cmp -Raw bytes (22): 0x[01, 01, 04, 07, 0b, 00, 09, 0f, 15, 00, 11, 02, 01, 04, 27, 00, 28, 03, 00, 30, 00, 31] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 4 -- expression 0 operands: lhs = Expression(1, Add), rhs = Expression(2, Add) -- expression 1 operands: lhs = Zero, rhs = Counter(2) -- expression 2 operands: lhs = Expression(3, Add), rhs = Counter(5) -- expression 3 operands: lhs = Zero, rhs = Counter(4) -Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 4, 39) to (start + 0, 40) -- Code(Expression(0, Add)) at (prev + 0, 48) to (start + 0, 49) - = ((Zero + c2) + ((Zero + c4) + c5)) - -Function name: ::fmt -Raw bytes (9): 0x[01, 01, 00, 01, 01, 04, 11, 00, 16] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 4, 17) to (start + 0, 22) - Function name: ::new Raw bytes (9): 0x[01, 01, 00, 01, 01, 0c, 05, 06, 06] Number of files: 1 diff --git a/tests/coverage/partial_eq.coverage b/tests/coverage/partial_eq.coverage index 6e3696386a773..9de1c933570cb 100644 --- a/tests/coverage/partial_eq.coverage +++ b/tests/coverage/partial_eq.coverage @@ -1,8 +1,7 @@ LL| |// This test confirms an earlier problem was resolved, supporting the MIR graph generated by the LL| |// structure of this test. LL| | - LL| 2|#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] - ^0 ^0 ^0 ^1 ^1 ^0^0 + LL| |#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] LL| |pub struct Version { LL| | major: usize, LL| | minor: usize, From 21e5beae3cc4ffd2adea9ae7b4a9d8b84a4bc0a8 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Mon, 22 Jan 2024 10:10:00 -0600 Subject: [PATCH 04/14] Use debug_assert instead of expanded equivalent --- compiler/rustc_mir_transform/src/coverage/mod.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 4b91f042f007a..afeacbf2232d3 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -366,10 +366,8 @@ fn check_code_region(code_region: CodeRegion) -> Option { ?is_ordered, "Skipping code region that would be misinterpreted or rejected by LLVM" ); - if cfg!(debug_assertions) { - // If this happens in a debug build, ICE to make it easier to notice. - bug!("Improper code region: {code_region:?}"); - } + // If this happens in a debug build, ICE to make it easier to notice. + debug_assert!(false, "Improper code region: {code_region:?}"); None } } From 1b1040dadc4b3b85adb2ea8c4a1feecb8202f1f2 Mon Sep 17 00:00:00 2001 From: h1467792822 <1467792822@qq.com> Date: Tue, 5 Dec 2023 12:42:57 +0800 Subject: [PATCH 05/14] MCP #705: Provide the option `-Csymbol-mangling-version=hashed -Z unstable-options` to shorten symbol names by replacing them with a digest. Enrich test cases --- compiler/rustc_session/src/config.rs | 15 +++ compiler/rustc_session/src/options.rs | 6 +- compiler/rustc_symbol_mangling/src/hashed.rs | 43 ++++++++ compiler/rustc_symbol_mangling/src/lib.rs | 4 + compiler/rustc_symbol_mangling/src/v0.rs | 104 ++++++++++-------- .../run-make/symbol-mangling-hashed/Makefile | 47 ++++++++ .../symbol-mangling-hashed/a_dylib.rs | 4 + .../run-make/symbol-mangling-hashed/a_rlib.rs | 5 + .../run-make/symbol-mangling-hashed/b_bin.rs | 9 ++ .../symbol-mangling-hashed/b_dylib.rs | 9 ++ .../bad-value.bad.stderr | 2 +- .../bad-value.blank.stderr | 2 +- .../bad-value.no-value.stderr | 2 +- .../unstable.hashed.stderr | 2 + tests/ui/symbol-mangling-version/unstable.rs | 5 +- 15 files changed, 210 insertions(+), 49 deletions(-) create mode 100644 compiler/rustc_symbol_mangling/src/hashed.rs create mode 100644 tests/run-make/symbol-mangling-hashed/Makefile create mode 100644 tests/run-make/symbol-mangling-hashed/a_dylib.rs create mode 100644 tests/run-make/symbol-mangling-hashed/a_rlib.rs create mode 100644 tests/run-make/symbol-mangling-hashed/b_bin.rs create mode 100644 tests/run-make/symbol-mangling-hashed/b_dylib.rs create mode 100644 tests/ui/symbol-mangling-version/unstable.hashed.stderr diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index e751ff13a34ca..2ec1a726cef1f 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -347,6 +347,7 @@ impl SwitchWithOptPath { pub enum SymbolManglingVersion { Legacy, V0, + Hashed, } #[derive(Clone, Copy, Debug, PartialEq, Hash)] @@ -2692,6 +2693,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M match cg.symbol_mangling_version { // Stable values: None | Some(SymbolManglingVersion::V0) => {} + // Unstable values: Some(SymbolManglingVersion::Legacy) => { if !unstable_opts.unstable_options { @@ -2700,6 +2702,13 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M ); } } + Some(SymbolManglingVersion::Hashed) => { + if !unstable_opts.unstable_options { + early_dcx.early_fatal( + "`-C symbol-mangling-version=hashed` requires `-Z unstable-options`", + ); + } + } } // Check for unstable values of `-C instrument-coverage`. @@ -2741,6 +2750,12 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M ); } Some(SymbolManglingVersion::V0) => {} + Some(SymbolManglingVersion::Hashed) => { + early_dcx.early_warn( + "-C instrument-coverage requires symbol mangling version `v0`, \ + but `-C symbol-mangling-version=hashed` was specified", + ); + } } } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 486b6d4bf2e14..d8d201d5f244d 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -407,7 +407,8 @@ mod desc { pub const parse_switch_with_opt_path: &str = "an optional path to the profiling data output directory"; pub const parse_merge_functions: &str = "one of: `disabled`, `trampolines`, or `aliases`"; - pub const parse_symbol_mangling_version: &str = "either `legacy` or `v0` (RFC 2603)"; + pub const parse_symbol_mangling_version: &str = + "one of: `legacy`, `v0` (RFC 2603), or `hashed`"; pub const parse_src_file_hash: &str = "either `md5` or `sha1`"; pub const parse_relocation_model: &str = "one of supported relocation models (`rustc --print relocation-models`)"; @@ -1180,6 +1181,7 @@ mod parse { *slot = match v { Some("legacy") => Some(SymbolManglingVersion::Legacy), Some("v0") => Some(SymbolManglingVersion::V0), + Some("hashed") => Some(SymbolManglingVersion::Hashed), _ => return false, }; true @@ -1504,7 +1506,7 @@ options! { "tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"), symbol_mangling_version: Option = (None, parse_symbol_mangling_version, [TRACKED], - "which mangling version to use for symbol names ('legacy' (default) or 'v0')"), + "which mangling version to use for symbol names ('legacy' (default), 'v0', or 'hashed')"), target_cpu: Option = (None, parse_opt_string, [TRACKED], "select target processor (`rustc --print target-cpus` for details)"), target_feature: String = (String::new(), parse_target_feature, [TRACKED], diff --git a/compiler/rustc_symbol_mangling/src/hashed.rs b/compiler/rustc_symbol_mangling/src/hashed.rs new file mode 100644 index 0000000000000..d4cd6161ac040 --- /dev/null +++ b/compiler/rustc_symbol_mangling/src/hashed.rs @@ -0,0 +1,43 @@ +use crate::v0; +use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher}; +use rustc_hir::def_id::CrateNum; +use rustc_middle::ty::{Instance, TyCtxt}; + +use std::fmt::Write; + +pub(super) fn mangle<'tcx>( + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, + instantiating_crate: Option, + full_mangling_name: impl FnOnce() -> String, +) -> String { + // The symbol of a generic function may be scattered in multiple downstream dylibs. + // If the symbol of a generic function still contains `crate name`, hash conflicts between the + // generic funcion and other symbols of the same `crate` cannot be detected in time during + // construction. This symbol conflict is left over until it occurs during run time. + // In this case, `instantiating-crate name` is used to replace `crate name` can completely + // eliminate the risk of the preceding potential hash conflict. + let crate_num = + if let Some(krate) = instantiating_crate { krate } else { instance.def_id().krate }; + + let mut symbol = "_RNxC".to_string(); + v0::push_ident(tcx.crate_name(crate_num).as_str(), &mut symbol); + + let hash = tcx.with_stable_hashing_context(|mut hcx| { + let mut hasher = StableHasher::new(); + full_mangling_name().hash_stable(&mut hcx, &mut hasher); + hasher.finish::().as_u64() + }); + + push_hash64(hash, &mut symbol); + + symbol +} + +// The hash is encoded based on `base-62` and the final terminator `_` is removed because it does +// not help prevent hash collisions +fn push_hash64(hash: u64, output: &mut String) { + let hash = v0::encode_integer_62(hash); + let hash_len = hash.len(); + let _ = write!(output, "{hash_len}H{}", &hash[..hash_len - 1]); +} diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 8c035ba948b15..bf4ea0003abb4 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -111,6 +111,7 @@ use rustc_middle::query::Providers; use rustc_middle::ty::{self, Instance, TyCtxt}; use rustc_session::config::SymbolManglingVersion; +mod hashed; mod legacy; mod v0; @@ -265,6 +266,9 @@ fn compute_symbol_name<'tcx>( let symbol = match mangling_version { SymbolManglingVersion::Legacy => legacy::mangle(tcx, instance, instantiating_crate), SymbolManglingVersion::V0 => v0::mangle(tcx, instance, instantiating_crate), + SymbolManglingVersion::Hashed => hashed::mangle(tcx, instance, instantiating_crate, || { + v0::mangle(tcx, instance, instantiating_crate) + }), }; debug_assert!( diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index e89a640767f22..16ebda55a7a51 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -116,10 +116,7 @@ impl<'tcx> SymbolMangler<'tcx> { /// * `x > 0` is encoded as `x - 1` in base 62, followed by `"_"`, /// e.g. `1` becomes `"0_"`, `62` becomes `"Z_"`, etc. fn push_integer_62(&mut self, x: u64) { - if let Some(x) = x.checked_sub(1) { - base_n::push_str(x as u128, 62, &mut self.out); - } - self.push("_"); + push_integer_62(x, &mut self.out) } /// Push a `tag`-prefixed base 62 integer, when larger than `0`, that is: @@ -138,45 +135,7 @@ impl<'tcx> SymbolMangler<'tcx> { } fn push_ident(&mut self, ident: &str) { - let mut use_punycode = false; - for b in ident.bytes() { - match b { - b'_' | b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' => {} - 0x80..=0xff => use_punycode = true, - _ => bug!("symbol_names: bad byte {} in ident {:?}", b, ident), - } - } - - let punycode_string; - let ident = if use_punycode { - self.push("u"); - - // FIXME(eddyb) we should probably roll our own punycode implementation. - let mut punycode_bytes = match punycode::encode(ident) { - Ok(s) => s.into_bytes(), - Err(()) => bug!("symbol_names: punycode encoding failed for ident {:?}", ident), - }; - - // Replace `-` with `_`. - if let Some(c) = punycode_bytes.iter_mut().rfind(|&&mut c| c == b'-') { - *c = b'_'; - } - - // FIXME(eddyb) avoid rechecking UTF-8 validity. - punycode_string = String::from_utf8(punycode_bytes).unwrap(); - &punycode_string - } else { - ident - }; - - let _ = write!(self.out, "{}", ident.len()); - - // Write a separating `_` if necessary (leading digit or `_`). - if let Some('_' | '0'..='9') = ident.chars().next() { - self.push("_"); - } - - self.push(ident); + push_ident(ident, &mut self.out) } fn path_append_ns( @@ -836,3 +795,62 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { Ok(()) } } +/// Push a `_`-terminated base 62 integer, using the format +/// specified in the RFC as ``, that is: +/// * `x = 0` is encoded as just the `"_"` terminator +/// * `x > 0` is encoded as `x - 1` in base 62, followed by `"_"`, +/// e.g. `1` becomes `"0_"`, `62` becomes `"Z_"`, etc. +pub(crate) fn push_integer_62(x: u64, output: &mut String) { + if let Some(x) = x.checked_sub(1) { + base_n::push_str(x as u128, 62, output); + } + output.push('_'); +} + +pub(crate) fn encode_integer_62(x: u64) -> String { + let mut output = String::new(); + push_integer_62(x, &mut output); + output +} + +pub(crate) fn push_ident(ident: &str, output: &mut String) { + let mut use_punycode = false; + for b in ident.bytes() { + match b { + b'_' | b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' => {} + 0x80..=0xff => use_punycode = true, + _ => bug!("symbol_names: bad byte {} in ident {:?}", b, ident), + } + } + + let punycode_string; + let ident = if use_punycode { + output.push('u'); + + // FIXME(eddyb) we should probably roll our own punycode implementation. + let mut punycode_bytes = match punycode::encode(ident) { + Ok(s) => s.into_bytes(), + Err(()) => bug!("symbol_names: punycode encoding failed for ident {:?}", ident), + }; + + // Replace `-` with `_`. + if let Some(c) = punycode_bytes.iter_mut().rfind(|&&mut c| c == b'-') { + *c = b'_'; + } + + // FIXME(eddyb) avoid rechecking UTF-8 validity. + punycode_string = String::from_utf8(punycode_bytes).unwrap(); + &punycode_string + } else { + ident + }; + + let _ = write!(output, "{}", ident.len()); + + // Write a separating `_` if necessary (leading digit or `_`). + if let Some('_' | '0'..='9') = ident.chars().next() { + output.push('_'); + } + + output.push_str(ident); +} diff --git a/tests/run-make/symbol-mangling-hashed/Makefile b/tests/run-make/symbol-mangling-hashed/Makefile new file mode 100644 index 0000000000000..6107cd2d6b5e0 --- /dev/null +++ b/tests/run-make/symbol-mangling-hashed/Makefile @@ -0,0 +1,47 @@ +# ignore-cross-compile +include ../tools.mk + +# ignore-windows-msvc + +NM=nm -D +RLIB_NAME=liba_rlib.rlib +DYLIB_NAME=liba_dylib.so +SO_NAME=libb_dylib.so +BIN_NAME=b_bin + +ifeq ($(UNAME),Darwin) +NM=nm -gU +RLIB_NAME=liba_rlib.rlib +DYLIB_NAME=liba_dylib.dylib +SO_NAME=libb_dylib.dylib +BIN_NAME=b_bin +endif + +ifdef IS_WINDOWS +NM=nm -g +RLIB_NAME=liba_rlib.dll.a +DYLIB_NAME=liba_dylib.dll +SO_NAME=libb_dylib.dll +BIN_NAME=b_bin.exe +endif + +all: + $(RUSTC) -C prefer-dynamic -Z unstable-options -C symbol-mangling-version=hashed -C metadata=foo a_dylib.rs + $(RUSTC) -C prefer-dynamic -Z unstable-options -C symbol-mangling-version=hashed -C metadata=bar a_rlib.rs + $(RUSTC) -C prefer-dynamic -L $(TMPDIR) b_dylib.rs + $(RUSTC) -C prefer-dynamic -L $(TMPDIR) b_bin.rs + + # Check hashed symbol name + + [ "$$($(NM) $(TMPDIR)/$(DYLIB_NAME) | grep -c hello)" -eq "0" ] + [ "$$($(NM) $(TMPDIR)/$(DYLIB_NAME) | grep _RNxC7a_dylib | grep -c ' T ')" -eq "1" ] + + [ "$$($(NM) $(TMPDIR)/$(SO_NAME) | grep b_dylib | grep -c hello)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(SO_NAME) | grep _RNxC6a_rlib | grep -c ' T ')" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(SO_NAME) | grep _RNxC7a_dylib | grep -c ' U ')" -eq "1" ] + + [ "$$($(NM) $(TMPDIR)/$(BIN_NAME) | grep _RNxC6a_rlib | grep -c ' U ')" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(BIN_NAME) | grep _RNxC7a_dylib | grep -c ' U ')" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(BIN_NAME) | grep b_dylib | grep hello | grep -c ' U ')" -eq "1" ] + + $(call RUN,$(BIN_NAME)) diff --git a/tests/run-make/symbol-mangling-hashed/a_dylib.rs b/tests/run-make/symbol-mangling-hashed/a_dylib.rs new file mode 100644 index 0000000000000..8aec8fd82a53f --- /dev/null +++ b/tests/run-make/symbol-mangling-hashed/a_dylib.rs @@ -0,0 +1,4 @@ +#![crate_type="dylib"] +pub fn hello() { + println!("hello dylib"); +} diff --git a/tests/run-make/symbol-mangling-hashed/a_rlib.rs b/tests/run-make/symbol-mangling-hashed/a_rlib.rs new file mode 100644 index 0000000000000..873c86c5d0b4c --- /dev/null +++ b/tests/run-make/symbol-mangling-hashed/a_rlib.rs @@ -0,0 +1,5 @@ +#![crate_type="rlib"] + +pub fn hello() { + println!("hello rlib"); +} diff --git a/tests/run-make/symbol-mangling-hashed/b_bin.rs b/tests/run-make/symbol-mangling-hashed/b_bin.rs new file mode 100644 index 0000000000000..bcc53c37e122a --- /dev/null +++ b/tests/run-make/symbol-mangling-hashed/b_bin.rs @@ -0,0 +1,9 @@ +extern crate a_rlib; +extern crate a_dylib; +extern crate b_dylib; + +fn main() { + a_rlib::hello(); + a_dylib::hello(); + b_dylib::hello(); +} diff --git a/tests/run-make/symbol-mangling-hashed/b_dylib.rs b/tests/run-make/symbol-mangling-hashed/b_dylib.rs new file mode 100644 index 0000000000000..c26a04b39ec32 --- /dev/null +++ b/tests/run-make/symbol-mangling-hashed/b_dylib.rs @@ -0,0 +1,9 @@ +#![crate_type="dylib"] + +extern crate a_rlib; +extern crate a_dylib; + +pub fn hello() { + a_rlib::hello(); + a_dylib::hello(); +} diff --git a/tests/ui/symbol-mangling-version/bad-value.bad.stderr b/tests/ui/symbol-mangling-version/bad-value.bad.stderr index c36c73c6069f1..a12e5e241c022 100644 --- a/tests/ui/symbol-mangling-version/bad-value.bad.stderr +++ b/tests/ui/symbol-mangling-version/bad-value.bad.stderr @@ -1,2 +1,2 @@ -error: incorrect value `bad-value` for codegen option `symbol-mangling-version` - either `legacy` or `v0` (RFC 2603) was expected +error: incorrect value `bad-value` for codegen option `symbol-mangling-version` - one of: `legacy`, `v0` (RFC 2603), or `hashed` was expected diff --git a/tests/ui/symbol-mangling-version/bad-value.blank.stderr b/tests/ui/symbol-mangling-version/bad-value.blank.stderr index 0e70af5b8ffbe..95456587781e6 100644 --- a/tests/ui/symbol-mangling-version/bad-value.blank.stderr +++ b/tests/ui/symbol-mangling-version/bad-value.blank.stderr @@ -1,2 +1,2 @@ -error: incorrect value `` for codegen option `symbol-mangling-version` - either `legacy` or `v0` (RFC 2603) was expected +error: incorrect value `` for codegen option `symbol-mangling-version` - one of: `legacy`, `v0` (RFC 2603), or `hashed` was expected diff --git a/tests/ui/symbol-mangling-version/bad-value.no-value.stderr b/tests/ui/symbol-mangling-version/bad-value.no-value.stderr index 77013b72b6c1d..325e47a281fae 100644 --- a/tests/ui/symbol-mangling-version/bad-value.no-value.stderr +++ b/tests/ui/symbol-mangling-version/bad-value.no-value.stderr @@ -1,2 +1,2 @@ -error: codegen option `symbol-mangling-version` requires either `legacy` or `v0` (RFC 2603) (C symbol-mangling-version=) +error: codegen option `symbol-mangling-version` requires one of: `legacy`, `v0` (RFC 2603), or `hashed` (C symbol-mangling-version=) diff --git a/tests/ui/symbol-mangling-version/unstable.hashed.stderr b/tests/ui/symbol-mangling-version/unstable.hashed.stderr new file mode 100644 index 0000000000000..f2ae18290f261 --- /dev/null +++ b/tests/ui/symbol-mangling-version/unstable.hashed.stderr @@ -0,0 +1,2 @@ +error: `-C symbol-mangling-version=hashed` requires `-Z unstable-options` + diff --git a/tests/ui/symbol-mangling-version/unstable.rs b/tests/ui/symbol-mangling-version/unstable.rs index df87a39cdfbd1..42750a64574dc 100644 --- a/tests/ui/symbol-mangling-version/unstable.rs +++ b/tests/ui/symbol-mangling-version/unstable.rs @@ -1,6 +1,9 @@ -// revisions: legacy legacy-ok +// revisions: legacy legacy-ok hashed hashed-ok // [legacy] compile-flags: -Csymbol-mangling-version=legacy // [legacy-ok] check-pass // [legacy-ok] compile-flags: -Zunstable-options -Csymbol-mangling-version=legacy +// [hashed] compile-flags: -Csymbol-mangling-version=hashed +// [hashed-ok] check-pass +// [hashed-ok] compile-flags: -Zunstable-options -Csymbol-mangling-version=hashed fn main() {} From 823e8b041a03c4e5f33d95cdc6fb996ecbcf0fa5 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 22 Jan 2024 10:13:06 +0100 Subject: [PATCH 06/14] Allow disjoint flag in codegen test --- tests/codegen/array-map.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/codegen/array-map.rs b/tests/codegen/array-map.rs index 4d218e6a951b2..bdae43054d0b2 100644 --- a/tests/codegen/array-map.rs +++ b/tests/codegen/array-map.rs @@ -10,7 +10,7 @@ pub fn short_integer_map(x: [u32; 8]) -> [u32; 8] { // CHECK: load <8 x i32> // CHECK: shl <8 x i32> - // CHECK: or <8 x i32> + // CHECK: or{{( disjoint)?}} <8 x i32> // CHECK: store <8 x i32> x.map(|x| 2 * x + 1) } From 31f5f033e9a712cf586534e505a81f6e241f9db1 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 23 Jan 2024 10:17:05 +0100 Subject: [PATCH 07/14] Remove uses of no-system-llvm It looks like none of these are actually needed. --- tests/codegen/alloc-optimisation.rs | 2 -- tests/codegen/array-map.rs | 1 - tests/codegen/dealloc-no-unwind.rs | 1 - tests/codegen/fewer-names.rs | 1 - tests/codegen/integer-overflow.rs | 1 - tests/codegen/issues/issue-116878.rs | 1 - tests/codegen/issues/issue-44056-macos-tls-align.rs | 1 - tests/codegen/issues/issue-69101-bounds-check.rs | 1 - tests/codegen/match-optimizes-away.rs | 1 - tests/codegen/ptr-read-metadata.rs | 1 - tests/codegen/slice-as_chunks.rs | 1 - tests/codegen/slice-iter-len-eq-zero.rs | 1 - tests/codegen/slice-iter-nonnull.rs | 1 - tests/codegen/slice-position-bounds-check.rs | 1 - tests/codegen/vec-iter-collect-len.rs | 1 - tests/codegen/vec-optimizes-away.rs | 1 - tests/rustdoc/doc-cfg-target-feature.rs | 1 - tests/ui/for-loop-while/issue-69841.rs | 1 - tests/ui/issue-76387-llvm-miscompile.rs | 1 - 19 files changed, 20 deletions(-) diff --git a/tests/codegen/alloc-optimisation.rs b/tests/codegen/alloc-optimisation.rs index f88d695d87e1e..900eb687a45bb 100644 --- a/tests/codegen/alloc-optimisation.rs +++ b/tests/codegen/alloc-optimisation.rs @@ -1,5 +1,3 @@ -// -// no-system-llvm // compile-flags: -O #![crate_type = "lib"] diff --git a/tests/codegen/array-map.rs b/tests/codegen/array-map.rs index bdae43054d0b2..9846cc7f5c836 100644 --- a/tests/codegen/array-map.rs +++ b/tests/codegen/array-map.rs @@ -1,5 +1,4 @@ // compile-flags: -C opt-level=3 -C target-cpu=x86-64-v3 -// no-system-llvm // only-x86_64 // ignore-debug (the extra assertions get in the way) diff --git a/tests/codegen/dealloc-no-unwind.rs b/tests/codegen/dealloc-no-unwind.rs index 3812ef44ff2ac..c2656908f16d7 100644 --- a/tests/codegen/dealloc-no-unwind.rs +++ b/tests/codegen/dealloc-no-unwind.rs @@ -1,4 +1,3 @@ -// no-system-llvm // compile-flags: -O #![crate_type="lib"] diff --git a/tests/codegen/fewer-names.rs b/tests/codegen/fewer-names.rs index df1080bff2b1c..05643fab96a1d 100644 --- a/tests/codegen/fewer-names.rs +++ b/tests/codegen/fewer-names.rs @@ -1,4 +1,3 @@ -// no-system-llvm // compile-flags: -Coverflow-checks=no -O // revisions: YES NO // [YES]compile-flags: -Zfewer-names=yes diff --git a/tests/codegen/integer-overflow.rs b/tests/codegen/integer-overflow.rs index 183de56db9685..b5c351b5e35de 100644 --- a/tests/codegen/integer-overflow.rs +++ b/tests/codegen/integer-overflow.rs @@ -1,4 +1,3 @@ -// no-system-llvm // compile-flags: -O -C overflow-checks=on #![crate_type = "lib"] diff --git a/tests/codegen/issues/issue-116878.rs b/tests/codegen/issues/issue-116878.rs index d5f679459f731..5864f53232493 100644 --- a/tests/codegen/issues/issue-116878.rs +++ b/tests/codegen/issues/issue-116878.rs @@ -1,4 +1,3 @@ -// no-system-llvm // compile-flags: -O // ignore-debug: the debug assertions get in the way #![crate_type = "lib"] diff --git a/tests/codegen/issues/issue-44056-macos-tls-align.rs b/tests/codegen/issues/issue-44056-macos-tls-align.rs index 1a3923f1bb1ab..44aa9766d3c0d 100644 --- a/tests/codegen/issues/issue-44056-macos-tls-align.rs +++ b/tests/codegen/issues/issue-44056-macos-tls-align.rs @@ -1,6 +1,5 @@ // // only-macos -// no-system-llvm // compile-flags: -O #![crate_type = "rlib"] diff --git a/tests/codegen/issues/issue-69101-bounds-check.rs b/tests/codegen/issues/issue-69101-bounds-check.rs index a3aca3a2912a6..655de45fd51e9 100644 --- a/tests/codegen/issues/issue-69101-bounds-check.rs +++ b/tests/codegen/issues/issue-69101-bounds-check.rs @@ -1,4 +1,3 @@ -// no-system-llvm // compile-flags: -O // ignore-debug: the debug assertions get in the way #![crate_type = "lib"] diff --git a/tests/codegen/match-optimizes-away.rs b/tests/codegen/match-optimizes-away.rs index 8f66c518ccf48..400606b42d550 100644 --- a/tests/codegen/match-optimizes-away.rs +++ b/tests/codegen/match-optimizes-away.rs @@ -1,5 +1,4 @@ // -// no-system-llvm // compile-flags: -O #![crate_type="lib"] diff --git a/tests/codegen/ptr-read-metadata.rs b/tests/codegen/ptr-read-metadata.rs index 73d1db6df277b..94152ed11ba13 100644 --- a/tests/codegen/ptr-read-metadata.rs +++ b/tests/codegen/ptr-read-metadata.rs @@ -1,5 +1,4 @@ // compile-flags: -O -Z merge-functions=disabled -// no-system-llvm // ignore-debug (the extra assertions get in the way) #![crate_type = "lib"] diff --git a/tests/codegen/slice-as_chunks.rs b/tests/codegen/slice-as_chunks.rs index efac9f3d68da8..e832f90d07a52 100644 --- a/tests/codegen/slice-as_chunks.rs +++ b/tests/codegen/slice-as_chunks.rs @@ -1,4 +1,3 @@ -// no-system-llvm // compile-flags: -O // only-64bit (because the LLVM type of i64 for usize shows up) // ignore-debug: the debug assertions get in the way diff --git a/tests/codegen/slice-iter-len-eq-zero.rs b/tests/codegen/slice-iter-len-eq-zero.rs index c7515ce35a35f..77febf5170da7 100644 --- a/tests/codegen/slice-iter-len-eq-zero.rs +++ b/tests/codegen/slice-iter-len-eq-zero.rs @@ -1,4 +1,3 @@ -// no-system-llvm // compile-flags: -O // ignore-debug: the debug assertions add extra comparisons #![crate_type = "lib"] diff --git a/tests/codegen/slice-iter-nonnull.rs b/tests/codegen/slice-iter-nonnull.rs index 1e691cc34c995..93c8828ccd336 100644 --- a/tests/codegen/slice-iter-nonnull.rs +++ b/tests/codegen/slice-iter-nonnull.rs @@ -1,4 +1,3 @@ -// no-system-llvm // compile-flags: -O // ignore-debug (these add extra checks that make it hard to verify) #![crate_type = "lib"] diff --git a/tests/codegen/slice-position-bounds-check.rs b/tests/codegen/slice-position-bounds-check.rs index b494f42b2965d..57904e5e49999 100644 --- a/tests/codegen/slice-position-bounds-check.rs +++ b/tests/codegen/slice-position-bounds-check.rs @@ -1,4 +1,3 @@ -// no-system-llvm // compile-flags: -O -C panic=abort #![crate_type = "lib"] diff --git a/tests/codegen/vec-iter-collect-len.rs b/tests/codegen/vec-iter-collect-len.rs index 73348ddd063dc..3a0d6c3091927 100644 --- a/tests/codegen/vec-iter-collect-len.rs +++ b/tests/codegen/vec-iter-collect-len.rs @@ -1,5 +1,4 @@ // ignore-debug: the debug assertions get in the way -// no-system-llvm // compile-flags: -O #![crate_type="lib"] diff --git a/tests/codegen/vec-optimizes-away.rs b/tests/codegen/vec-optimizes-away.rs index 6f477a796b65d..3be342dabeb62 100644 --- a/tests/codegen/vec-optimizes-away.rs +++ b/tests/codegen/vec-optimizes-away.rs @@ -1,5 +1,4 @@ // ignore-debug: the debug assertions get in the way -// no-system-llvm // compile-flags: -O #![crate_type = "lib"] diff --git a/tests/rustdoc/doc-cfg-target-feature.rs b/tests/rustdoc/doc-cfg-target-feature.rs index f1b000dc82362..98d230c978b7e 100644 --- a/tests/rustdoc/doc-cfg-target-feature.rs +++ b/tests/rustdoc/doc-cfg-target-feature.rs @@ -1,7 +1,6 @@ // only-x86_64 // compile-flags:--test // should-fail -// no-system-llvm // #49723: rustdoc didn't add target features when extracting or running doctests diff --git a/tests/ui/for-loop-while/issue-69841.rs b/tests/ui/for-loop-while/issue-69841.rs index 1aca16ca80451..942b99b742bc6 100644 --- a/tests/ui/for-loop-while/issue-69841.rs +++ b/tests/ui/for-loop-while/issue-69841.rs @@ -2,7 +2,6 @@ // LLVM bug which needed a fix to be backported. // run-pass -// no-system-llvm fn main() { let buffer = [49u8, 10]; diff --git a/tests/ui/issue-76387-llvm-miscompile.rs b/tests/ui/issue-76387-llvm-miscompile.rs index a9b4686c97021..a7fc9da633963 100644 --- a/tests/ui/issue-76387-llvm-miscompile.rs +++ b/tests/ui/issue-76387-llvm-miscompile.rs @@ -1,4 +1,3 @@ -// no-system-llvm // compile-flags: -C opt-level=3 // aux-build: issue-76387.rs // run-pass From f4f589a028f56f6957942d0ceafbb5e83b906777 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 23 Jan 2024 11:19:51 +0100 Subject: [PATCH 08/14] Remove support for no-system-llvm Also add tests for min-system-llvm-version. --- src/tools/compiletest/src/header.rs | 3 --- src/tools/compiletest/src/header/tests.rs | 21 ++++++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index e70e01e8757e0..ff907152ca916 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -1109,9 +1109,6 @@ fn ignore_lldb(config: &Config, line: &str) -> IgnoreDecision { } fn ignore_llvm(config: &Config, line: &str) -> IgnoreDecision { - if config.system_llvm && line.starts_with("no-system-llvm") { - return IgnoreDecision::Ignore { reason: "ignored when the system LLVM is used".into() }; - } if let Some(needed_components) = config.parse_name_value_directive(line, "needs-llvm-components") { diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 8882f1582acc7..c859e8acadebd 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -242,15 +242,6 @@ fn aux_build() { ); } -#[test] -fn no_system_llvm() { - let config: Config = cfg().system_llvm(false).build(); - assert!(!check_ignore(&config, "// no-system-llvm")); - - let config: Config = cfg().system_llvm(true).build(); - assert!(check_ignore(&config, "// no-system-llvm")); -} - #[test] fn llvm_version() { let config: Config = cfg().llvm_version("8.1.2").build(); @@ -266,6 +257,18 @@ fn llvm_version() { assert!(!check_ignore(&config, "// min-llvm-version: 9.0")); } +#[test] +fn system_llvm_version() { + let config: Config = cfg().system_llvm(true).llvm_version("17.0.0").build(); + assert!(check_ignore(&config, "// min-system-llvm-version: 18.0")); + + let config: Config = cfg().system_llvm(true).llvm_version("18.0.0").build(); + assert!(!check_ignore(&config, "// min-system-llvm-version: 18.0")); + + let config: Config = cfg().llvm_version("17.0.0").build(); + assert!(!check_ignore(&config, "// min-system-llvm-version: 18.0")); +} + #[test] fn ignore_target() { let config: Config = cfg().target("x86_64-unknown-linux-gnu").build(); From 31ecf341250a889ac1154b2cbe3f0b97f9d008c1 Mon Sep 17 00:00:00 2001 From: Ryan Levick Date: Mon, 18 Dec 2023 21:43:02 +0100 Subject: [PATCH 09/14] Add the wasm32-wasi-preview2 target Signed-off-by: Ryan Levick --- compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_target/src/spec/mod.rs | 1 + .../targets/wasm32_wasi_preview1_threads.rs | 3 +- .../src/spec/targets/wasm32_wasi_preview2.rs | 64 +++++++++ library/std/src/os/mod.rs | 3 + library/std/src/os/wasi/mod.rs | 3 +- library/std/src/os/wasi_preview2/mod.rs | 5 + library/std/src/sys/pal/mod.rs | 3 + library/std/src/sys/pal/wasi/helpers.rs | 123 ++++++++++++++++ library/std/src/sys/pal/wasi/mod.rs | 132 ++---------------- library/std/src/sys/pal/wasi_preview2/mod.rs | 78 +++++++++++ src/bootstrap/src/core/build_steps/compile.rs | 7 +- src/bootstrap/src/lib.rs | 2 +- src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/platform-support.md | 1 + .../platform-support/wasm32-wasi-preview2.md | 30 ++++ tests/assembly/targets/targets-elf.rs | 3 + tests/ui/check-cfg/well-known-values.stderr | 4 +- 18 files changed, 334 insertions(+), 130 deletions(-) create mode 100644 compiler/rustc_target/src/spec/targets/wasm32_wasi_preview2.rs create mode 100644 library/std/src/os/wasi_preview2/mod.rs create mode 100644 library/std/src/sys/pal/wasi/helpers.rs create mode 100644 library/std/src/sys/pal/wasi_preview2/mod.rs create mode 100644 src/doc/rustc/src/platform-support/wasm32-wasi-preview2.md diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6c39a38750ec9..0eb6ab991512f 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1792,6 +1792,7 @@ symbols! { warn, wasm_abi, wasm_import_module, + wasm_preview2, wasm_target_feature, while_let, windows, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 884bd23e8cce9..ead3be7fd529b 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1574,6 +1574,7 @@ supported_targets! { ("wasm32-unknown-emscripten", wasm32_unknown_emscripten), ("wasm32-unknown-unknown", wasm32_unknown_unknown), ("wasm32-wasi", wasm32_wasi), + ("wasm32-wasi-preview2", wasm32_wasi_preview2), ("wasm32-wasi-preview1-threads", wasm32_wasi_preview1_threads), ("wasm64-unknown-unknown", wasm64_unknown_unknown), diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs index 28ea4cc9ece30..389c67f8ae93b 100644 --- a/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs +++ b/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs @@ -72,11 +72,12 @@ //! best we can with this target. Don't start relying on too much here unless //! you know what you're getting in to! -use crate::spec::{base, crt_objects, Cc, LinkSelfContainedDefault, LinkerFlavor, Target}; +use crate::spec::{base, crt_objects, cvs, Cc, LinkSelfContainedDefault, LinkerFlavor, Target}; pub fn target() -> Target { let mut options = base::wasm::options(); + options.families = cvs!["wasm", "wasi"]; options.os = "wasi".into(); options.add_pre_link_args( diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview2.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview2.rs new file mode 100644 index 0000000000000..fc44e5d4cbce9 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview2.rs @@ -0,0 +1,64 @@ +//! The `wasm32-wasi-preview2` target is the next evolution of the +//! wasm32-wasi target. While the wasi specification is still under +//! active development, the {review 2 iteration is considered an "island +//! of stability" that should allow users to rely on it indefinitely. +//! +//! The `wasi` target is a proposal to define a standardized set of WebAssembly +//! component imports that allow it to interoperate with the host system in a +//! standardized way. This set of imports is intended to empower WebAssembly +//! binaries with host capabilities such as filesystem access, network access, etc. +//! +//! Wasi Preview 2 relies on the WebAssembly component model which is an extension of +//! the core WebAssembly specification which allows interoperability between WebAssembly +//! modules (known as "components") through high-level, shared-nothing APIs instead of the +//! low-level, shared-everything linear memory model of the core WebAssembly specification. +//! +//! You can see more about wasi at and the component model at +//! . + +use crate::spec::crt_objects; +use crate::spec::LinkSelfContainedDefault; +use crate::spec::{base, Target}; + +pub fn target() -> Target { + let mut options = base::wasm::options(); + + options.os = "wasi".into(); + options.env = "preview2".into(); + options.linker = Some("wasm-component-ld".into()); + + options.pre_link_objects_self_contained = crt_objects::pre_wasi_self_contained(); + options.post_link_objects_self_contained = crt_objects::post_wasi_self_contained(); + + // FIXME: Figure out cases in which WASM needs to link with a native toolchain. + options.link_self_contained = LinkSelfContainedDefault::True; + + // Right now this is a bit of a workaround but we're currently saying that + // the target by default has a static crt which we're taking as a signal + // for "use the bundled crt". If that's turned off then the system's crt + // will be used, but this means that default usage of this target doesn't + // need an external compiler but it's still interoperable with an external + // compiler if configured correctly. + options.crt_static_default = true; + options.crt_static_respected = true; + + // Allow `+crt-static` to create a "cdylib" output which is just a wasm file + // without a main function. + options.crt_static_allows_dylibs = true; + + // WASI's `sys::args::init` function ignores its arguments; instead, + // `args::args()` makes the WASI API calls itself. + options.main_needs_argc_argv = false; + + // And, WASI mangles the name of "main" to distinguish between different + // signatures. + options.entry_name = "__main_void".into(); + + Target { + llvm_target: "wasm32-unknown-unknown".into(), + pointer_width: 32, + data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(), + arch: "wasm32".into(), + options, + } +} diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index 6e11b92b618a3..f03e079030503 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -85,6 +85,9 @@ pub mod linux; #[cfg(any(target_os = "wasi", doc))] pub mod wasi; +#[cfg(any(all(target_os = "wasi", target_env = "preview2"), doc))] +pub mod wasi_preview2; + // windows #[cfg(not(all( doc, diff --git a/library/std/src/os/wasi/mod.rs b/library/std/src/os/wasi/mod.rs index bbaf328f457e4..05c8d30073f42 100644 --- a/library/std/src/os/wasi/mod.rs +++ b/library/std/src/os/wasi/mod.rs @@ -28,7 +28,8 @@ //! [`OsStr`]: crate::ffi::OsStr //! [`OsString`]: crate::ffi::OsString -#![stable(feature = "rust1", since = "1.0.0")] +#![cfg_attr(not(target_env = "preview2"), stable(feature = "rust1", since = "1.0.0"))] +#![cfg_attr(target_env = "preview2", unstable(feature = "wasm_preview2", issue = "none"))] #![deny(unsafe_op_in_unsafe_fn)] #![doc(cfg(target_os = "wasi"))] diff --git a/library/std/src/os/wasi_preview2/mod.rs b/library/std/src/os/wasi_preview2/mod.rs new file mode 100644 index 0000000000000..1d44dd72814b8 --- /dev/null +++ b/library/std/src/os/wasi_preview2/mod.rs @@ -0,0 +1,5 @@ +//! Platform-specific extensions to `std` for Preview 2 of the WebAssembly System Interface (WASI). +//! +//! This module is currently empty, but will be filled over time as wasi-libc support for WASI Preview 2 is stabilized. + +#![stable(feature = "raw_ext", since = "1.1.0")] diff --git a/library/std/src/sys/pal/mod.rs b/library/std/src/sys/pal/mod.rs index 041b7c355822a..f927d88d46c34 100644 --- a/library/std/src/sys/pal/mod.rs +++ b/library/std/src/sys/pal/mod.rs @@ -40,6 +40,9 @@ cfg_if::cfg_if! { } else if #[cfg(target_os = "wasi")] { mod wasi; pub use self::wasi::*; + } else if #[cfg(all(target_os = "wasi", target_env = "preview2"))] { + mod wasi_preview2; + pub use self::wasi_preview2::*; } else if #[cfg(target_family = "wasm")] { mod wasm; pub use self::wasm::*; diff --git a/library/std/src/sys/pal/wasi/helpers.rs b/library/std/src/sys/pal/wasi/helpers.rs new file mode 100644 index 0000000000000..82149cef8fad1 --- /dev/null +++ b/library/std/src/sys/pal/wasi/helpers.rs @@ -0,0 +1,123 @@ +use crate::io as std_io; +use crate::mem; + +#[inline] +pub fn is_interrupted(errno: i32) -> bool { + errno == wasi::ERRNO_INTR.raw().into() +} + +pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind { + use std_io::ErrorKind; + + let Ok(errno) = u16::try_from(errno) else { + return ErrorKind::Uncategorized; + }; + + macro_rules! match_errno { + ($($($errno:ident)|+ => $errkind:ident),*, _ => $wildcard:ident $(,)?) => { + match errno { + $(e if $(e == ::wasi::$errno.raw())||+ => ErrorKind::$errkind),*, + _ => ErrorKind::$wildcard, + } + }; + } + + match_errno! { + ERRNO_2BIG => ArgumentListTooLong, + ERRNO_ACCES => PermissionDenied, + ERRNO_ADDRINUSE => AddrInUse, + ERRNO_ADDRNOTAVAIL => AddrNotAvailable, + ERRNO_AFNOSUPPORT => Unsupported, + ERRNO_AGAIN => WouldBlock, + // ALREADY => "connection already in progress", + // BADF => "bad file descriptor", + // BADMSG => "bad message", + ERRNO_BUSY => ResourceBusy, + // CANCELED => "operation canceled", + // CHILD => "no child processes", + ERRNO_CONNABORTED => ConnectionAborted, + ERRNO_CONNREFUSED => ConnectionRefused, + ERRNO_CONNRESET => ConnectionReset, + ERRNO_DEADLK => Deadlock, + // DESTADDRREQ => "destination address required", + ERRNO_DOM => InvalidInput, + // DQUOT => /* reserved */, + ERRNO_EXIST => AlreadyExists, + // FAULT => "bad address", + ERRNO_FBIG => FileTooLarge, + ERRNO_HOSTUNREACH => HostUnreachable, + // IDRM => "identifier removed", + // ILSEQ => "illegal byte sequence", + // INPROGRESS => "operation in progress", + ERRNO_INTR => Interrupted, + ERRNO_INVAL => InvalidInput, + ERRNO_IO => Uncategorized, + // ISCONN => "socket is connected", + ERRNO_ISDIR => IsADirectory, + ERRNO_LOOP => FilesystemLoop, + // MFILE => "file descriptor value too large", + ERRNO_MLINK => TooManyLinks, + // MSGSIZE => "message too large", + // MULTIHOP => /* reserved */, + ERRNO_NAMETOOLONG => InvalidFilename, + ERRNO_NETDOWN => NetworkDown, + // NETRESET => "connection aborted by network", + ERRNO_NETUNREACH => NetworkUnreachable, + // NFILE => "too many files open in system", + // NOBUFS => "no buffer space available", + ERRNO_NODEV => NotFound, + ERRNO_NOENT => NotFound, + // NOEXEC => "executable file format error", + // NOLCK => "no locks available", + // NOLINK => /* reserved */, + ERRNO_NOMEM => OutOfMemory, + // NOMSG => "no message of the desired type", + // NOPROTOOPT => "protocol not available", + ERRNO_NOSPC => StorageFull, + ERRNO_NOSYS => Unsupported, + ERRNO_NOTCONN => NotConnected, + ERRNO_NOTDIR => NotADirectory, + ERRNO_NOTEMPTY => DirectoryNotEmpty, + // NOTRECOVERABLE => "state not recoverable", + // NOTSOCK => "not a socket", + ERRNO_NOTSUP => Unsupported, + // NOTTY => "inappropriate I/O control operation", + ERRNO_NXIO => NotFound, + // OVERFLOW => "value too large to be stored in data type", + // OWNERDEAD => "previous owner died", + ERRNO_PERM => PermissionDenied, + ERRNO_PIPE => BrokenPipe, + // PROTO => "protocol error", + ERRNO_PROTONOSUPPORT => Unsupported, + // PROTOTYPE => "protocol wrong type for socket", + // RANGE => "result too large", + ERRNO_ROFS => ReadOnlyFilesystem, + ERRNO_SPIPE => NotSeekable, + ERRNO_SRCH => NotFound, + // STALE => /* reserved */, + ERRNO_TIMEDOUT => TimedOut, + ERRNO_TXTBSY => ResourceBusy, + ERRNO_XDEV => CrossesDevices, + ERRNO_NOTCAPABLE => PermissionDenied, + _ => Uncategorized, + } +} + +pub fn abort_internal() -> ! { + unsafe { libc::abort() } +} + +pub fn hashmap_random_keys() -> (u64, u64) { + let mut ret = (0u64, 0u64); + unsafe { + let base = &mut ret as *mut (u64, u64) as *mut u8; + let len = mem::size_of_val(&ret); + wasi::random_get(base, len).expect("random_get failure"); + } + return ret; +} + +#[inline] +pub(crate) fn err2io(err: wasi::Errno) -> std_io::Error { + std_io::Error::from_raw_os_error(err.raw().into()) +} diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs index 4ffc8ecdd67ee..a4b55093bf47f 100644 --- a/library/std/src/sys/pal/wasi/mod.rs +++ b/library/std/src/sys/pal/wasi/mod.rs @@ -14,9 +14,6 @@ //! compiling for wasm. That way it's a compile time error for something that's //! guaranteed to be a runtime error! -use crate::io as std_io; -use crate::mem; - #[path = "../unix/alloc.rs"] pub mod alloc; pub mod args; @@ -72,123 +69,12 @@ cfg_if::cfg_if! { mod common; pub use common::*; -#[inline] -pub fn is_interrupted(errno: i32) -> bool { - errno == wasi::ERRNO_INTR.raw().into() -} - -pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind { - use std_io::ErrorKind; - - let Ok(errno) = u16::try_from(errno) else { - return ErrorKind::Uncategorized; - }; - - macro_rules! match_errno { - ($($($errno:ident)|+ => $errkind:ident),*, _ => $wildcard:ident $(,)?) => { - match errno { - $(e if $(e == ::wasi::$errno.raw())||+ => ErrorKind::$errkind),*, - _ => ErrorKind::$wildcard, - } - }; - } - - match_errno! { - ERRNO_2BIG => ArgumentListTooLong, - ERRNO_ACCES => PermissionDenied, - ERRNO_ADDRINUSE => AddrInUse, - ERRNO_ADDRNOTAVAIL => AddrNotAvailable, - ERRNO_AFNOSUPPORT => Unsupported, - ERRNO_AGAIN => WouldBlock, - // ALREADY => "connection already in progress", - // BADF => "bad file descriptor", - // BADMSG => "bad message", - ERRNO_BUSY => ResourceBusy, - // CANCELED => "operation canceled", - // CHILD => "no child processes", - ERRNO_CONNABORTED => ConnectionAborted, - ERRNO_CONNREFUSED => ConnectionRefused, - ERRNO_CONNRESET => ConnectionReset, - ERRNO_DEADLK => Deadlock, - // DESTADDRREQ => "destination address required", - ERRNO_DOM => InvalidInput, - // DQUOT => /* reserved */, - ERRNO_EXIST => AlreadyExists, - // FAULT => "bad address", - ERRNO_FBIG => FileTooLarge, - ERRNO_HOSTUNREACH => HostUnreachable, - // IDRM => "identifier removed", - // ILSEQ => "illegal byte sequence", - // INPROGRESS => "operation in progress", - ERRNO_INTR => Interrupted, - ERRNO_INVAL => InvalidInput, - ERRNO_IO => Uncategorized, - // ISCONN => "socket is connected", - ERRNO_ISDIR => IsADirectory, - ERRNO_LOOP => FilesystemLoop, - // MFILE => "file descriptor value too large", - ERRNO_MLINK => TooManyLinks, - // MSGSIZE => "message too large", - // MULTIHOP => /* reserved */, - ERRNO_NAMETOOLONG => InvalidFilename, - ERRNO_NETDOWN => NetworkDown, - // NETRESET => "connection aborted by network", - ERRNO_NETUNREACH => NetworkUnreachable, - // NFILE => "too many files open in system", - // NOBUFS => "no buffer space available", - ERRNO_NODEV => NotFound, - ERRNO_NOENT => NotFound, - // NOEXEC => "executable file format error", - // NOLCK => "no locks available", - // NOLINK => /* reserved */, - ERRNO_NOMEM => OutOfMemory, - // NOMSG => "no message of the desired type", - // NOPROTOOPT => "protocol not available", - ERRNO_NOSPC => StorageFull, - ERRNO_NOSYS => Unsupported, - ERRNO_NOTCONN => NotConnected, - ERRNO_NOTDIR => NotADirectory, - ERRNO_NOTEMPTY => DirectoryNotEmpty, - // NOTRECOVERABLE => "state not recoverable", - // NOTSOCK => "not a socket", - ERRNO_NOTSUP => Unsupported, - // NOTTY => "inappropriate I/O control operation", - ERRNO_NXIO => NotFound, - // OVERFLOW => "value too large to be stored in data type", - // OWNERDEAD => "previous owner died", - ERRNO_PERM => PermissionDenied, - ERRNO_PIPE => BrokenPipe, - // PROTO => "protocol error", - ERRNO_PROTONOSUPPORT => Unsupported, - // PROTOTYPE => "protocol wrong type for socket", - // RANGE => "result too large", - ERRNO_ROFS => ReadOnlyFilesystem, - ERRNO_SPIPE => NotSeekable, - ERRNO_SRCH => NotFound, - // STALE => /* reserved */, - ERRNO_TIMEDOUT => TimedOut, - ERRNO_TXTBSY => ResourceBusy, - ERRNO_XDEV => CrossesDevices, - ERRNO_NOTCAPABLE => PermissionDenied, - _ => Uncategorized, - } -} - -pub fn abort_internal() -> ! { - unsafe { libc::abort() } -} - -pub fn hashmap_random_keys() -> (u64, u64) { - let mut ret = (0u64, 0u64); - unsafe { - let base = &mut ret as *mut (u64, u64) as *mut u8; - let len = mem::size_of_val(&ret); - wasi::random_get(base, len).expect("random_get failure"); - } - return ret; -} - -#[inline] -fn err2io(err: wasi::Errno) -> std_io::Error { - std_io::Error::from_raw_os_error(err.raw().into()) -} +mod helpers; +// These exports are listed individually to work around Rust's glob import +// conflict rules. If we glob export `helpers` and `common` together, then +// the compiler complains about conflicts. +pub use helpers::abort_internal; +pub use helpers::decode_error_kind; +use helpers::err2io; +pub use helpers::hashmap_random_keys; +pub use helpers::is_interrupted; diff --git a/library/std/src/sys/pal/wasi_preview2/mod.rs b/library/std/src/sys/pal/wasi_preview2/mod.rs new file mode 100644 index 0000000000000..b61695015bbd9 --- /dev/null +++ b/library/std/src/sys/pal/wasi_preview2/mod.rs @@ -0,0 +1,78 @@ +//! System bindings for the wasi preview 2 target. +//! +//! This is the next evolution of the original wasi target, and is intended to +//! replace that target over time. +//! +//! To begin with, this target mirrors the wasi target 1 to 1, but over +//! time this will change significantly. + +#[path = "../unix/alloc.rs"] +pub mod alloc; +#[path = "../wasi/args.rs"] +pub mod args; +#[path = "../unix/cmath.rs"] +pub mod cmath; +#[path = "../wasi/env.rs"] +pub mod env; +#[path = "../wasi/fd.rs"] +pub mod fd; +#[path = "../wasi/fs.rs"] +pub mod fs; +#[allow(unused)] +#[path = "../wasm/atomics/futex.rs"] +pub mod futex; +#[path = "../wasi/io.rs"] +pub mod io; + +#[path = "../wasi/net.rs"] +pub mod net; +#[path = "../wasi/os.rs"] +pub mod os; +#[path = "../unix/os_str.rs"] +pub mod os_str; +#[path = "../unix/path.rs"] +pub mod path; +#[path = "../unsupported/pipe.rs"] +pub mod pipe; +#[path = "../unsupported/process.rs"] +pub mod process; +#[path = "../wasi/stdio.rs"] +pub mod stdio; +#[path = "../wasi/thread.rs"] +pub mod thread; +#[path = "../unsupported/thread_local_dtor.rs"] +pub mod thread_local_dtor; +#[path = "../unsupported/thread_local_key.rs"] +pub mod thread_local_key; +#[path = "../wasi/time.rs"] +pub mod time; + +cfg_if::cfg_if! { + if #[cfg(target_feature = "atomics")] { + compile_error!("The wasm32-wasi-preview2 target does not support atomics"); + } else { + #[path = "../unsupported/locks/mod.rs"] + pub mod locks; + #[path = "../unsupported/once.rs"] + pub mod once; + #[path = "../unsupported/thread_parking.rs"] + pub mod thread_parking; + } +} + +#[path = "../unsupported/common.rs"] +#[deny(unsafe_op_in_unsafe_fn)] +#[allow(unused)] +mod common; +pub use common::*; + +#[path = "../wasi/helpers.rs"] +mod helpers; +// These exports are listed individually to work around Rust's glob import +// conflict rules. If we glob export `helpers` and `common` together, then +// the compiler complains about conflicts. +pub use helpers::abort_internal; +pub use helpers::decode_error_kind; +use helpers::err2io; +pub use helpers::hashmap_random_keys; +pub use helpers::is_interrupted; diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index f954f01fe4eda..e06bc3fb09ac1 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -367,10 +367,13 @@ fn copy_self_contained_objects( let srcdir = builder .wasi_root(target) .unwrap_or_else(|| { - panic!("Target {:?} does not have a \"wasi-root\" key", target.triple) + panic!( + "Target {:?} does not have a \"wasi-root\" key in Config.toml", + target.triple + ) }) .join("lib") - .join(target.to_string().replace("-preview1", "")); + .join(target.to_string().replace("-preview1", "").replace("-preview2", "")); for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] { copy_and_stamp( builder, diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 1336abf6c7aba..1726e7aacbcea 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -88,7 +88,7 @@ const EXTRA_CHECK_CFGS: &[(Option, &str, Option<&[&'static str]>)] = &[ (Some(Mode::Std), "no_sync", None), (Some(Mode::Std), "backtrace_in_libstd", None), /* Extra values not defined in the built-in targets yet, but used in std */ - (Some(Mode::Std), "target_env", Some(&["libnx"])), + (Some(Mode::Std), "target_env", Some(&["libnx", "preview2"])), // (Some(Mode::Std), "target_os", Some(&[])), // #[cfg(bootstrap)] zkvm (Some(Mode::Std), "target_os", Some(&["zkvm"])), diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 1998b008dc811..990998ea70431 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -59,6 +59,7 @@ - [*-unknown-openbsd](platform-support/openbsd.md) - [\*-unknown-uefi](platform-support/unknown-uefi.md) - [wasm32-wasi-preview1-threads](platform-support/wasm32-wasi-preview1-threads.md) + - [wasm32-wasi-preview2](platform-support/wasm32-wasi-preview2.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) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index f648a60b6c48d..fb751b7229eb4 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -360,6 +360,7 @@ target | std | host | notes `thumbv7a-pc-windows-msvc` | ? | | `thumbv7a-uwp-windows-msvc` | ✓ | | `thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode ARMv7-A Linux with NEON, MUSL +[`wasm32-wasi-preview2`](platform-support/wasm32-wasi-preview2.md) | ✓ | | WebAssembly [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly `x86_64-apple-ios-macabi` | ✓ | | Apple Catalyst on x86_64 [`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ? | | x86 64-bit tvOS diff --git a/src/doc/rustc/src/platform-support/wasm32-wasi-preview2.md b/src/doc/rustc/src/platform-support/wasm32-wasi-preview2.md new file mode 100644 index 0000000000000..837efd13d417e --- /dev/null +++ b/src/doc/rustc/src/platform-support/wasm32-wasi-preview2.md @@ -0,0 +1,30 @@ +# `wasm32-wasi-preview2` + +**Tier: 3** + +The `wasm32-wasi-preview2` target is a new and still (as of January 2024) an +experimental target. This target is an extension to `wasm32-wasi-preview1` target, +originally known as `wasm32-wasi`. It is the next evolution in the development of +wasi (the [WebAssembly System Interface](https://wasi.dev)) that uses the WebAssembly +[component model] to allow for a standardized set of syscalls that are intended to empower +WebAssembly binaries with native host capabilities. + +[component model]: https://github.com/WebAssembly/component-model + +## Target maintainers + +- Alex Crichton, https://github.com/alexcrichton +- Ryan Levick, https://github.com/rylev + +## Requirements + +This target is cross-compiled. The target supports `std` fully. + +## Platform requirements + +The WebAssembly runtime should support the wasi preview 2 API set. + +This target is not a stable target. This means that there are only a few engines +which implement wasi preview 2, for example: + +* Wasmtime - `-W component-model` diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs index 6eec05e85ac71..f6f2f5e88ffc3 100644 --- a/tests/assembly/targets/targets-elf.rs +++ b/tests/assembly/targets/targets-elf.rs @@ -534,6 +534,9 @@ // revisions: wasm64_unknown_unknown // [wasm64_unknown_unknown] compile-flags: --target wasm64-unknown-unknown // [wasm64_unknown_unknown] needs-llvm-components: webassembly +// revisions: wasm32_wasi_preview2 +// [wasm32_wasi_preview2] compile-flags: --target wasm32-wasi-preview2 +// [wasm32_wasi_preview2] needs-llvm-components: webassembly // revisions: x86_64_apple_darwin // [x86_64_apple_darwin] compile-flags: --target x86_64-apple-darwin // [x86_64_apple_darwin] needs-llvm-components: x86 diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 814d473619777..d7d538c0b9e3e 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -125,7 +125,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_env = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_env` are: ``, `eabihf`, `gnu`, `gnueabihf`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `ohos`, `psx`, `relibc`, `sgx`, `uclibc` + = note: expected values for `target_env` are: ``, `eabihf`, `gnu`, `gnueabihf`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `ohos`, `preview2`, `psx`, `relibc`, `sgx`, `uclibc` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -134,7 +134,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_family = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_family` are: `unix`, `wasm`, `windows` + = note: expected values for `target_family` are: `unix`, `wasi`, `wasm`, `windows` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` From ba75970473ea93b720deddf29201f65086b51095 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 24 Jan 2024 00:07:00 +0300 Subject: [PATCH 10/14] privacy: Refactor top-level visiting in `TypePrivacyVisitor` --- compiler/rustc_privacy/src/lib.rs | 90 ++++++------------- tests/ui/privacy/private-type-in-interface.rs | 3 +- .../privacy/private-type-in-interface.stderr | 16 +++- 3 files changed, 43 insertions(+), 66 deletions(-) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 0d4ee1e8dcaad..ae10695fae453 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -24,13 +24,13 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId, CRATE_DEF_ID}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{AssocItemKind, ForeignItemKind, ItemId, PatKind}; -use rustc_middle::bug; use rustc_middle::hir::nested_filter; use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level}; use rustc_middle::query::Providers; use rustc_middle::ty::GenericArgs; use rustc_middle::ty::{self, Const, GenericParamDefKind}; use rustc_middle::ty::{TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor}; +use rustc_middle::{bug, span_bug}; use rustc_session::lint; use rustc_span::hygiene::Transparency; use rustc_span::symbol::{kw, sym, Ident}; @@ -1064,29 +1064,22 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> { struct TypePrivacyVisitor<'tcx> { tcx: TyCtxt<'tcx>, + module_def_id: LocalModDefId, maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>, - current_item: LocalDefId, span: Span, } impl<'tcx> TypePrivacyVisitor<'tcx> { - /// Gets the type-checking results for the current body. - /// As this will ICE if called outside bodies, only call when working with - /// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies). - #[track_caller] - fn typeck_results(&self) -> &'tcx ty::TypeckResults<'tcx> { - self.maybe_typeck_results - .expect("`TypePrivacyVisitor::typeck_results` called outside of body") - } - fn item_is_accessible(&self, did: DefId) -> bool { - self.tcx.visibility(did).is_accessible_from(self.current_item, self.tcx) + self.tcx.visibility(did).is_accessible_from(self.module_def_id, self.tcx) } // Take node-id of an expression or pattern and check its type for privacy. fn check_expr_pat_type(&mut self, id: hir::HirId, span: Span) -> bool { self.span = span; - let typeck_results = self.typeck_results(); + let typeck_results = self + .maybe_typeck_results + .unwrap_or_else(|| span_bug!(span, "`hir::Expr` or `hir::Pat` outside of a body")); let result: ControlFlow<()> = try { self.visit(typeck_results.node_type(id))?; self.visit(typeck_results.node_args(id))?; @@ -1107,35 +1100,13 @@ impl<'tcx> TypePrivacyVisitor<'tcx> { } impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { - type NestedFilter = nested_filter::All; - - /// We want to visit items in the context of their containing - /// module and so forth, so supply a crate for doing a deep walk. - fn nested_visit_map(&mut self) -> Self::Map { - self.tcx.hir() - } - - fn visit_mod(&mut self, _m: &'tcx hir::Mod<'tcx>, _s: Span, _n: hir::HirId) { - // Don't visit nested modules, since we run a separate visitor walk - // for each module in `effective_visibilities` - } - - fn visit_nested_body(&mut self, body: hir::BodyId) { + fn visit_nested_body(&mut self, body_id: hir::BodyId) { let old_maybe_typeck_results = - self.maybe_typeck_results.replace(self.tcx.typeck_body(body)); - let body = self.tcx.hir().body(body); - self.visit_body(body); + self.maybe_typeck_results.replace(self.tcx.typeck_body(body_id)); + self.visit_body(self.tcx.hir().body(body_id)); self.maybe_typeck_results = old_maybe_typeck_results; } - fn visit_generic_arg(&mut self, generic_arg: &'tcx hir::GenericArg<'tcx>) { - match generic_arg { - hir::GenericArg::Type(t) => self.visit_ty(t), - hir::GenericArg::Infer(inf) => self.visit_infer(inf), - hir::GenericArg::Lifetime(_) | hir::GenericArg::Const(_) => {} - } - } - fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) { self.span = hir_ty.span; if let Some(typeck_results) = self.maybe_typeck_results { @@ -1163,19 +1134,19 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { return; } } else { - // We don't do anything for const infers here. + // FIXME: check types of const infers here. } } else { - bug!("visit_infer without typeck_results"); + span_bug!(self.span, "`hir::InferArg` outside of a body"); } intravisit::walk_inf(self, inf); } fn visit_trait_ref(&mut self, trait_ref: &'tcx hir::TraitRef<'tcx>) { self.span = trait_ref.path.span; - if self.maybe_typeck_results.is_none() { - // Avoid calling `hir_trait_to_predicates` in bodies, it will ICE. - // The traits' privacy in bodies is already checked as a part of trait object types. + if self.maybe_typeck_results.is_some() { + // Privacy of traits in bodies is checked as a part of trait object types. + } else { let bounds = rustc_hir_analysis::hir_trait_to_predicates( self.tcx, trait_ref, @@ -1223,7 +1194,10 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { hir::ExprKind::MethodCall(segment, ..) => { // Method calls have to be checked specially. self.span = segment.ident.span; - if let Some(def_id) = self.typeck_results().type_dependent_def_id(expr.hir_id) { + let typeck_results = self + .maybe_typeck_results + .unwrap_or_else(|| span_bug!(self.span, "`hir::Expr` outside of a body")); + if let Some(def_id) = typeck_results.type_dependent_def_id(expr.hir_id) { if self.visit(self.tcx.type_of(def_id).instantiate_identity()).is_break() { return; } @@ -1251,9 +1225,13 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { Res::Def(kind, def_id) => Some((kind, def_id)), _ => None, }, - hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self - .maybe_typeck_results - .and_then(|typeck_results| typeck_results.type_dependent_def(id)), + hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => { + match self.maybe_typeck_results { + Some(typeck_results) => typeck_results.type_dependent_def(id), + // FIXME: Check type-relative associated types in signatures. + None => None, + } + } }; let def = def.filter(|(kind, _)| { matches!( @@ -1307,15 +1285,6 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { intravisit::walk_local(self, local); } - - // Check types in item interfaces. - fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { - let orig_current_item = mem::replace(&mut self.current_item, item.owner_id.def_id); - let old_maybe_typeck_results = self.maybe_typeck_results.take(); - intravisit::walk_item(self, item); - self.maybe_typeck_results = old_maybe_typeck_results; - self.current_item = orig_current_item; - } } impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> { @@ -1785,13 +1754,8 @@ fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { // Check privacy of explicitly written types and traits as well as // inferred types of expressions and patterns. - let mut visitor = TypePrivacyVisitor { - tcx, - maybe_typeck_results: None, - current_item: module_def_id.to_local_def_id(), - span, - }; - intravisit::walk_mod(&mut visitor, module, hir_id); + let mut visitor = TypePrivacyVisitor { tcx, module_def_id, maybe_typeck_results: None, span }; + tcx.hir().visit_item_likes_in_module(module_def_id, &mut visitor); } fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities { diff --git a/tests/ui/privacy/private-type-in-interface.rs b/tests/ui/privacy/private-type-in-interface.rs index 39e0bf23cacb2..9f55127fd168e 100644 --- a/tests/ui/privacy/private-type-in-interface.rs +++ b/tests/ui/privacy/private-type-in-interface.rs @@ -26,6 +26,7 @@ type A = ::X; //~ ERROR type `Priv` is private trait Tr2 {} impl Tr2 for u8 {} fn g() -> impl Tr2 { 0 } //~ ERROR type `Priv` is private + //~| ERROR type `Priv` is private fn g_ext() -> impl Tr2 { 0 } //~ ERROR type `ext::Priv` is private - + //~| ERROR type `ext::Priv` is private fn main() {} diff --git a/tests/ui/privacy/private-type-in-interface.stderr b/tests/ui/privacy/private-type-in-interface.stderr index 03225d84fdb34..a5e80d6962dba 100644 --- a/tests/ui/privacy/private-type-in-interface.stderr +++ b/tests/ui/privacy/private-type-in-interface.stderr @@ -46,11 +46,23 @@ error: type `Priv` is private LL | fn g() -> impl Tr2 { 0 } | ^^^^^^^^^^^^^^^^^^ private type +error: type `Priv` is private + --> $DIR/private-type-in-interface.rs:28:16 + | +LL | fn g() -> impl Tr2 { 0 } + | ^^^^^^^^^^^^^ private type + error: type `ext::Priv` is private - --> $DIR/private-type-in-interface.rs:29:15 + --> $DIR/private-type-in-interface.rs:30:15 | LL | fn g_ext() -> impl Tr2 { 0 } | ^^^^^^^^^^^^^^^^^^^^ private type -error: aborting due to 9 previous errors +error: type `ext::Priv` is private + --> $DIR/private-type-in-interface.rs:30:20 + | +LL | fn g_ext() -> impl Tr2 { 0 } + | ^^^^^^^^^^^^^^^ private type + +error: aborting due to 11 previous errors From 9676e188683da0dbde7e3798e47703e072cbb589 Mon Sep 17 00:00:00 2001 From: est31 Date: Wed, 24 Jan 2024 00:08:43 +0100 Subject: [PATCH 11/14] Remove extra # from url --- .../src/traits/error_reporting/suggestions.rs | 2 +- tests/ui/array-slice-vec/repeat_empty_ok.stderr | 4 ++-- tests/ui/const-generics/issues/issue-61336-2.stderr | 2 +- tests/ui/const-generics/issues/issue-61336.stderr | 2 +- tests/ui/consts/const-blocks/migrate-fail.stderr | 4 ++-- tests/ui/consts/const-blocks/nll-fail.stderr | 4 ++-- tests/ui/repeat-expr/repeat-to-run-dtor-twice.stderr | 2 +- tests/ui/trait-bounds/issue-119530-sugg-from-fn.stderr | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index e31aaaa196985..f3b04b55a35c5 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -3155,7 +3155,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } else { // FIXME: we may suggest array::repeat instead err.help("consider using `core::array::from_fn` to initialize the array"); - err.help("see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information"); + err.help("see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html for more information"); } if self.tcx.sess.is_nightly_build() diff --git a/tests/ui/array-slice-vec/repeat_empty_ok.stderr b/tests/ui/array-slice-vec/repeat_empty_ok.stderr index bc3a68c905d4f..c272d47d9617f 100644 --- a/tests/ui/array-slice-vec/repeat_empty_ok.stderr +++ b/tests/ui/array-slice-vec/repeat_empty_ok.stderr @@ -6,7 +6,7 @@ LL | let headers = [Header{value: &[]}; 128]; | = note: the `Copy` trait is required because this value will be copied for each element of the array = help: consider using `core::array::from_fn` to initialize the array - = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information + = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html for more information help: consider annotating `Header<'_>` with `#[derive(Copy)]` | LL + #[derive(Copy)] @@ -21,7 +21,7 @@ LL | let headers = [Header{value: &[0]}; 128]; | = note: the `Copy` trait is required because this value will be copied for each element of the array = help: consider using `core::array::from_fn` to initialize the array - = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information + = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html for more information help: consider annotating `Header<'_>` with `#[derive(Copy)]` | LL + #[derive(Copy)] diff --git a/tests/ui/const-generics/issues/issue-61336-2.stderr b/tests/ui/const-generics/issues/issue-61336-2.stderr index 9064c2d0b94f7..b0864689f7400 100644 --- a/tests/ui/const-generics/issues/issue-61336-2.stderr +++ b/tests/ui/const-generics/issues/issue-61336-2.stderr @@ -6,7 +6,7 @@ LL | [x; { N }] | = note: the `Copy` trait is required because this value will be copied for each element of the array = help: consider using `core::array::from_fn` to initialize the array - = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information + = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html for more information help: consider restricting type parameter `T` | LL | fn g(x: T) -> [T; N] { diff --git a/tests/ui/const-generics/issues/issue-61336.stderr b/tests/ui/const-generics/issues/issue-61336.stderr index 9935d6c168918..111afbda343f7 100644 --- a/tests/ui/const-generics/issues/issue-61336.stderr +++ b/tests/ui/const-generics/issues/issue-61336.stderr @@ -6,7 +6,7 @@ LL | [x; N] | = note: the `Copy` trait is required because this value will be copied for each element of the array = help: consider using `core::array::from_fn` to initialize the array - = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information + = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html for more information help: consider restricting type parameter `T` | LL | fn g(x: T) -> [T; N] { diff --git a/tests/ui/consts/const-blocks/migrate-fail.stderr b/tests/ui/consts/const-blocks/migrate-fail.stderr index 95fece0ae8ae2..3c116026e5804 100644 --- a/tests/ui/consts/const-blocks/migrate-fail.stderr +++ b/tests/ui/consts/const-blocks/migrate-fail.stderr @@ -7,7 +7,7 @@ LL | let arr: [Option; 2] = [x; 2]; = note: required for `Option` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array = help: consider using `core::array::from_fn` to initialize the array - = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information + = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html for more information help: consider annotating `Bar` with `#[derive(Copy)]` | LL + #[derive(Copy)] @@ -23,7 +23,7 @@ LL | let arr: [Option; 2] = [x; 2]; = note: required for `Option` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array = help: consider using `core::array::from_fn` to initialize the array - = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information + = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html for more information help: consider annotating `Bar` with `#[derive(Copy)]` | LL + #[derive(Copy)] diff --git a/tests/ui/consts/const-blocks/nll-fail.stderr b/tests/ui/consts/const-blocks/nll-fail.stderr index ed1dc78f77dba..ff2b62da66828 100644 --- a/tests/ui/consts/const-blocks/nll-fail.stderr +++ b/tests/ui/consts/const-blocks/nll-fail.stderr @@ -7,7 +7,7 @@ LL | let arr: [Option; 2] = [x; 2]; = note: required for `Option` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array = help: consider using `core::array::from_fn` to initialize the array - = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information + = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html for more information help: consider annotating `Bar` with `#[derive(Copy)]` | LL + #[derive(Copy)] @@ -23,7 +23,7 @@ LL | let arr: [Option; 2] = [x; 2]; = note: required for `Option` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array = help: consider using `core::array::from_fn` to initialize the array - = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information + = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html for more information help: consider annotating `Bar` with `#[derive(Copy)]` | LL + #[derive(Copy)] diff --git a/tests/ui/repeat-expr/repeat-to-run-dtor-twice.stderr b/tests/ui/repeat-expr/repeat-to-run-dtor-twice.stderr index f3fe8c10c0251..1f7487e68be8a 100644 --- a/tests/ui/repeat-expr/repeat-to-run-dtor-twice.stderr +++ b/tests/ui/repeat-expr/repeat-to-run-dtor-twice.stderr @@ -6,7 +6,7 @@ LL | let _ = [ a; 5 ]; | = note: the `Copy` trait is required because this value will be copied for each element of the array = help: consider using `core::array::from_fn` to initialize the array - = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information + = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html for more information help: consider annotating `Foo` with `#[derive(Copy)]` | LL + #[derive(Copy)] diff --git a/tests/ui/trait-bounds/issue-119530-sugg-from-fn.stderr b/tests/ui/trait-bounds/issue-119530-sugg-from-fn.stderr index f394c4cf027e2..9217637901b85 100644 --- a/tests/ui/trait-bounds/issue-119530-sugg-from-fn.stderr +++ b/tests/ui/trait-bounds/issue-119530-sugg-from-fn.stderr @@ -6,7 +6,7 @@ LL | let string_arr = [foo(); 64]; | = note: the `Copy` trait is required because this value will be copied for each element of the array = help: consider using `core::array::from_fn` to initialize the array - = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information + = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html for more information error: aborting due to 1 previous error From 0b1d7ffbd4d5c0546ccab819971f1d87a2d76d62 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sun, 26 Nov 2023 16:55:25 +0000 Subject: [PATCH 12/14] Add `NonZero*::count_ones` --- library/core/src/num/nonzero.rs | 37 +++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index a59195105d6d0..52edb757ba9a8 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -285,6 +285,43 @@ macro_rules! nonzero_integer { unsafe { intrinsics::cttz_nonzero(self.get() as $UnsignedPrimitive) as u32 } } + /// Returns the number of ones in the binary representation of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(non_zero_count_ones)] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("# use std::num::{self, ", stringify!($Ty), "};")] + /// + /// let one = num::NonZeroU32::new(1)?; + /// let three = num::NonZeroU32::new(3)?; + #[doc = concat!("let a = ", stringify!($Ty), "::new(0b100_0000)?;")] + #[doc = concat!("let b = ", stringify!($Ty), "::new(0b100_0011)?;")] + /// + /// assert_eq!(a.count_ones(), one); + /// assert_eq!(b.count_ones(), three); + /// # Some(()) + /// # } + /// ``` + /// + #[unstable(feature = "non_zero_count_ones", issue = "120287")] + #[rustc_const_unstable(feature = "non_zero_count_ones", issue = "120287")] + #[doc(alias = "popcount")] + #[doc(alias = "popcnt")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn count_ones(self) -> NonZeroU32 { + // SAFETY: + // `self` is non-zero, which means it has at least one bit set, which means + // that the result of `count_ones` is non-zero. + unsafe { NonZeroU32::new_unchecked(self.get().count_ones()) } + } + nonzero_integer_signedness_dependent_methods! { Self = $Ty, Primitive = $signedness $Int, From eabfe455ec65e19218a3381189cc78665fb7b81e Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 24 Jan 2024 10:13:28 +0100 Subject: [PATCH 13/14] Add mw to review rotation and add some owner assignments --- triagebot.toml | 135 ++++++++++++++++++++++++++----------------------- 1 file changed, 72 insertions(+), 63 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index 36e58f0f9d8a2..8fd457468e861 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -646,6 +646,7 @@ compiler-team = [ "@estebank", "@oli-obk", "@wesleywiser", + "@michaelwoerister", ] compiler-team-contributors = [ "@TaKO8Ki", @@ -738,6 +739,9 @@ ast_lowering = [ "@estebank", "@spastorino", ] +debuginfo = [ + "@michaelwoerister", +] fallback = [ "@Mark-Simulacrum" ] @@ -761,66 +765,71 @@ project-stable-mir = [ ] [assign.owners] -"/.github/workflows" = ["infra-ci"] -"/Cargo.lock" = ["@Mark-Simulacrum"] -"/Cargo.toml" = ["@Mark-Simulacrum"] -"/compiler" = ["compiler"] -"/compiler/rustc_arena" = ["compiler", "arena"] -"/compiler/rustc_ast" = ["compiler", "parser"] -"/compiler/rustc_ast_lowering" = ["compiler", "ast_lowering"] -"/compiler/rustc_hir_analysis" = ["compiler", "types"] -"/compiler/rustc_lexer" = ["compiler", "lexer"] -"/compiler/rustc_llvm" = ["@cuviper"] -"/compiler/rustc_middle/src/mir" = ["compiler", "mir"] -"/compiler/rustc_middle/src/traits" = ["compiler", "types"] -"/compiler/rustc_middle/src/ty" = ["compiler", "types"] -"/compiler/rustc_const_eval/src/interpret" = ["compiler", "mir"] -"/compiler/rustc_const_eval/src/transform" = ["compiler", "mir-opt"] -"/compiler/rustc_mir_build/src/build" = ["compiler", "mir"] -"/compiler/rustc_smir" = ["project-stable-mir"] -"/compiler/rustc_parse" = ["compiler", "parser"] -"/compiler/rustc_parse/src/lexer" = ["compiler", "lexer"] -"/compiler/rustc_query_impl" = ["compiler", "query-system"] -"/compiler/rustc_query_system" = ["compiler", "query-system"] -"/compiler/rustc_trait_selection" = ["compiler", "types"] -"/compiler/rustc_traits" = ["compiler", "types"] -"/compiler/rustc_type_ir" = ["compiler", "types"] -"/compiler/stable_mir" = ["project-stable-mir"] -"/library/alloc" = ["libs"] -"/library/core" = ["libs"] -"/library/panic_abort" = ["libs"] -"/library/panic_unwind" = ["libs"] -"/library/proc_macro" = ["@petrochenkov"] -"/library/std" = ["libs"] -"/library/std/src/sys/pal/windows" = ["@ChrisDenton", "@thomcc"] -"/library/stdarch" = ["libs"] -"/library/test" = ["libs"] -"/src/bootstrap" = ["bootstrap"] -"/src/ci" = ["infra-ci"] -"/src/doc" = ["docs"] -"/src/doc/book" = ["@ehuss"] -"/src/doc/edition-guide" = ["@ehuss"] -"/src/doc/embedded-book" = ["@ehuss"] -"/src/doc/nomicon" = ["@ehuss"] -"/src/doc/reference" = ["@ehuss"] -"/src/doc/rust-by-example" = ["@ehuss"] -"/src/doc/rustc-dev-guide" = ["@ehuss"] -"/src/doc/rustdoc" = ["rustdoc"] -"/src/doc/style-guide" = ["style-team"] -"/src/etc" = ["@Mark-Simulacrum"] -"/src/librustdoc" = ["rustdoc"] -"/src/llvm-project" = ["@cuviper"] -"/src/rustdoc-json-types" = ["rustdoc"] -"/src/stage0.json" = ["bootstrap"] -"/tests/ui" = ["compiler"] -"/src/tools/cargo" = ["@ehuss", "@joshtriplett"] -"/src/tools/compiletest" = ["bootstrap", "@wesleywiser", "@oli-obk", "@compiler-errors"] -"/src/tools/linkchecker" = ["@ehuss"] -"/src/tools/rust-installer" = ["bootstrap"] -"/src/tools/rustbook" = ["@ehuss"] -"/src/tools/rustdoc" = ["rustdoc"] -"/src/tools/rustdoc-js" = ["rustdoc"] -"/src/tools/rustdoc-themes" = ["rustdoc"] -"/src/tools/tidy" = ["bootstrap"] -"/src/tools/x" = ["bootstrap"] -"/src/tools/rustdoc-gui-test" = ["bootstrap", "@onur-ozkan"] +"/.github/workflows" = ["infra-ci"] +"/Cargo.lock" = ["@Mark-Simulacrum"] +"/Cargo.toml" = ["@Mark-Simulacrum"] +"/compiler" = ["compiler"] +"/compiler/rustc_arena" = ["compiler", "arena"] +"/compiler/rustc_ast" = ["compiler", "parser"] +"/compiler/rustc_ast_lowering" = ["compiler", "ast_lowering"] +"/compiler/rustc_data_structures/src/stable_hasher.rs" = ["compiler", "incremental"] +"/compiler/rustc_hir_analysis" = ["compiler", "types"] +"/compiler/rustc_incremental" = ["compiler", "incremental"] +"/compiler/rustc_lexer" = ["compiler", "lexer"] +"/compiler/rustc_llvm" = ["@cuviper"] +"/compiler/rustc_codegen_llvm/src/debuginfo" = ["compiler", "debuginfo"] +"/compiler/rustc_middle/src/mir" = ["compiler", "mir"] +"/compiler/rustc_middle/src/traits" = ["compiler", "types"] +"/compiler/rustc_middle/src/ty" = ["compiler", "types"] +"/compiler/rustc_const_eval/src/interpret" = ["compiler", "mir"] +"/compiler/rustc_const_eval/src/transform" = ["compiler", "mir-opt"] +"/compiler/rustc_mir_build/src/build" = ["compiler", "mir"] +"/compiler/rustc_smir" = ["project-stable-mir"] +"/compiler/rustc_parse" = ["compiler", "parser"] +"/compiler/rustc_parse/src/lexer" = ["compiler", "lexer"] +"/compiler/rustc_query_impl" = ["compiler", "query-system"] +"/compiler/rustc_query_system" = ["compiler", "query-system"] +"/compiler/rustc_query_system/src/dep_graph" = ["compiler", "incremental", "query-system"] +"/compiler/rustc_query_system/src/ich" = ["compiler", "incremental", "query-system"] +"/compiler/rustc_trait_selection" = ["compiler", "types"] +"/compiler/rustc_traits" = ["compiler", "types"] +"/compiler/rustc_type_ir" = ["compiler", "types"] +"/compiler/stable_mir" = ["project-stable-mir"] +"/library/alloc" = ["libs"] +"/library/core" = ["libs"] +"/library/panic_abort" = ["libs"] +"/library/panic_unwind" = ["libs"] +"/library/proc_macro" = ["@petrochenkov"] +"/library/std" = ["libs"] +"/library/std/src/sys/pal/windows" = ["@ChrisDenton", "@thomcc"] +"/library/stdarch" = ["libs"] +"/library/test" = ["libs"] +"/src/bootstrap" = ["bootstrap"] +"/src/ci" = ["infra-ci"] +"/src/doc" = ["docs"] +"/src/doc/book" = ["@ehuss"] +"/src/doc/edition-guide" = ["@ehuss"] +"/src/doc/embedded-book" = ["@ehuss"] +"/src/doc/nomicon" = ["@ehuss"] +"/src/doc/reference" = ["@ehuss"] +"/src/doc/rust-by-example" = ["@ehuss"] +"/src/doc/rustc-dev-guide" = ["@ehuss"] +"/src/doc/rustdoc" = ["rustdoc"] +"/src/doc/style-guide" = ["style-team"] +"/src/etc" = ["@Mark-Simulacrum"] +"/src/librustdoc" = ["rustdoc"] +"/src/llvm-project" = ["@cuviper"] +"/src/rustdoc-json-types" = ["rustdoc"] +"/src/stage0.json" = ["bootstrap"] +"/tests/ui" = ["compiler"] +"/src/tools/cargo" = ["@ehuss", "@joshtriplett"] +"/src/tools/compiletest" = ["bootstrap", "@wesleywiser", "@oli-obk", "@compiler-errors"] +"/src/tools/linkchecker" = ["@ehuss"] +"/src/tools/rust-installer" = ["bootstrap"] +"/src/tools/rustbook" = ["@ehuss"] +"/src/tools/rustdoc" = ["rustdoc"] +"/src/tools/rustdoc-js" = ["rustdoc"] +"/src/tools/rustdoc-themes" = ["rustdoc"] +"/src/tools/tidy" = ["bootstrap"] +"/src/tools/x" = ["bootstrap"] +"/src/tools/rustdoc-gui-test" = ["bootstrap", "@onur-ozkan"] From db4cf5d88b414ebd65653ed42168628e86c46498 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 24 Jan 2024 10:40:35 +0100 Subject: [PATCH 14/14] Add @davidtwco to debuginfo group in triage.toml Co-authored-by: David Wood --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index 8fd457468e861..264f6efd982c7 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -741,6 +741,7 @@ ast_lowering = [ ] debuginfo = [ "@michaelwoerister", + "@davidtwco" ] fallback = [ "@Mark-Simulacrum"